Skip to content

SessionStart hook ignores inject_claude_md: false config and .cognilayer-no-inject sentinel (v4.3.0) #3

@nordscope-fi

Description

@nordscope-fi

GitHub issue draft — file at https://github.com/LakyFx/CogniLayer/issues/new

Title:
SessionStart hook ignores inject_claude_md: false config and .cognilayer-no-inject sentinel (v4.3.0)

Body:

Summary

hooks/on_session_start.py in v4.3.0 unconditionally rewrites the === COGNILAYER === block in CLAUDE.md from the claude_md.template i18n string. Two documented opt-out mechanisms are no longer honored.

Reproduction

  1. CogniLayer v4.3.0 installed at ~/.cognilayer/
  2. Project at ~/Documents/GitHub/<name> with:
    • ~/.cognilayer/config.yaml containing:
      project_overrides:
        <name>:
          inject_claude_md: false
    • Repo root sentinel file .cognilayer-no-inject present
    • CLAUDE.md committed to git with a hand-edited === COGNILAYER (auto-generated, do not delete) === block
  3. Start a Claude Code session in that project.
  4. Observe: git status shows CLAUDE.md modified. The COGNILAYER block has been overwritten with the current claude_md.template output.

Evidence

$ grep -rn "inject_claude_md\|no-inject\|no_inject" ~/.cognilayer/ --include="*.py"
(empty — zero matches across all Python files, including hooks/on_session_start.py)
$ diff <(awk '/# === COGNILAYER/,/=== END COGNILAYER ===/' CLAUDE.md | ...) \
       <(python3 -c "from i18n import t; print(t('claude_md.template'))")
(empty — byte-identical match, confirming the COGNILAYER block came from the template)

config.yaml documents the override:

project_overrides:
  portalpilot:
    # Don't inject CogniLayer block into CLAUDE.md — it's committed to git
    # and already well-structured. Use MCP tools instead.
    inject_claude_md: false

But inject_cognilayer_block() and _inject_once() in hooks/on_session_start.py make no reference to inject_claude_md or to the project name when deciding whether to write — only when deciding what content to write.

Impact

For projects that commit CLAUDE.md to git:

  • Every session start produces a permanent dirty working tree
  • CI/lint hooks that block dirty trees (e.g. branch-guard) interfere
  • Any hand-edits to the COGNILAYER block (e.g. project-specific guidance kept in-band) are silently reverted on every session start
  • Project-specific inject_claude_md: false and the historically working .cognilayer-no-inject sentinel both became no-ops between earlier 4.x versions and 4.3.0

Expected behavior

_inject_once() (or its caller) should short-circuit when either:

  1. project_overrides[<project_name>].inject_claude_md is false, OR
  2. A sentinel file exists at <project_path>/.cognilayer-no-inject

The MCP tools (memory_search, project_context, session_bridge) provide on-demand access to the same DNA/bridge/briefs content, so opting out of the in-CLAUDE.md mirror is reasonable.

Suggested fix

Roughly:

def _should_inject(project_path: Path, project_name: str, config: dict) -> bool:
    if (project_path / ".cognilayer-no-inject").exists():
        return False
    overrides = config.get("project_overrides", {}).get(project_name, {})
    if overrides.get("inject_claude_md") is False:
        return False
    return True

Called inside inject_cognilayer_block() (or earlier in on_session_start_hook()) before the file write.

Workaround for affected users

Disable the CogniLayer SessionStart hook entirely in ~/.claude/settings.json (Claude Code's user-global settings). MCP tools remain functional.

Environment

  • CogniLayer: v4.3.0 (~/.cognilayer/VERSION)
  • Claude Code (recent), macOS Darwin 25.4.0
  • Hook mtimes confirm a recent upgrade rewrote on_session_start.py, i18n.py, and most of mcp-server/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions