Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 114 additions & 11 deletions agent-primer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ emit() {
esac
}

# An initialized index = the .codegraph/ dir AND at least one SQLite db file inside it.
# We check for the db file rather than running `codegraph status` on purpose: a bare
# .codegraph/ directory left behind by an aborted/half-finished `init` would otherwise
# look "set up" and make once-mode go silent on a broken index. Running `codegraph status`
# every session is exactly the cost once-mode removes, so this cheap filesystem check is the
# right middle ground; deep corruption is still `codegraph status`/--always's job.
index_initialized() {
[ -d "$PROJECT_DIR/.codegraph" ] || return 1
for _db in "$PROJECT_DIR"/.codegraph/*.db; do
[ -f "$_db" ] && return 0
done
return 1
}

# --- checks ----------------------------------------------------------------

if ! command -v codegraph >/dev/null 2>&1; then
Expand All @@ -117,18 +131,22 @@ direct yes/no question in chat:

CodeGraph is not installed yet. Want me to install it and index this repo now? I will run:
${INSTALL_SH}
codegraph install
codegraph install -y
codegraph init -i

If the user says yes, announce each command, run the three commands, then ask them to RESTART this
agent/IDE so the codegraph_* MCP tools load. Until restart, use the \`codegraph\` CLI directly.
agent/IDE so the codegraph_* MCP tools load. (Use \`codegraph install -y\`: a bare \`codegraph
install\` prompts interactively and hangs without a TTY.) After the restart, VERIFY the codegraph_*
tools loaded; if they are missing, the binary is usually in ~/.local/bin off the agent's PATH — add
it to PATH or re-register the MCP server's command with the absolute path. Until restart, use the
\`codegraph\` CLI directly.
If the user says no, proceed without CodeGraph and mention that structural code answers may be weaker."
exit 0
fi

if [ ! -d "$PROJECT_DIR/.codegraph" ]; then
emit "[CodeGraph] CLI present, but this project is NOT initialized (no .codegraph/ at
${PROJECT_DIR}).
if ! index_initialized; then
emit "[CodeGraph] CLI present, but this project is NOT initialized (no index DB under
${PROJECT_DIR}/.codegraph/).
Do NOT leave this as a passive note. Before substantive work, ask using the host's structured
prompt/confirmation dialog when one is available (the same kind of UI used for permissions or
command approvals, such as a request_user_input or confirm tool). If no such tool exists, ask this
Expand All @@ -137,7 +155,7 @@ direct yes/no question in chat:
CodeGraph is installed, but this repo is not indexed yet. Want me to run \`codegraph init -i\` now?

If the user says yes, announce and run \`codegraph init -i\`. If the codegraph_* MCP tools are
missing afterwards, run \`codegraph install\` and ask the user to restart this agent/IDE.
missing afterwards, run \`codegraph install -y\` and ask the user to restart this agent/IDE.
If the user says no, proceed without CodeGraph and mention that structural code answers may be weaker."
exit 0
fi
Expand Down Expand Up @@ -203,7 +221,9 @@ exists.
1. **Is the `codegraph` CLI installed?** — `command -v codegraph` (or `codegraph --version`).
- **No →** ask the user this exact simple question, then install if they say yes:
"CodeGraph is not installed yet. Want me to install it and index this repo now? I will run:
`<install command>`, `codegraph install`, and `codegraph init -i`."
`<install command>`, `codegraph install -y`, and `codegraph init -i`."
Use `codegraph install -y` (non-interactive). A bare `codegraph install` opens an interactive
agent-picker prompt that has no TTY in an agent context and will hang session startup.
2. **Is THIS project indexed?** — does `.codegraph/` exist at the repo root, and does
`codegraph status` succeed?
- **No →** ask: "CodeGraph is installed, but this repo is not indexed yet. Want me to run
Expand Down Expand Up @@ -231,25 +251,36 @@ announce each command before running it (it touches the user's machine), in orde
| 1. Install CLI (macOS/Linux) | `curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh \| sh` | Self-contained binary; no Node required |
| 1. Install CLI (any OS, alt) | `npm i -g @colbymchenry/codegraph` | npm alternative |
| 1. Install CLI (Windows) | `irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 \| iex` | PowerShell |
| 2. Register MCP into agents | `codegraph install` | Adds the `codegraph` MCP server to Claude Code / Cursor / Codex / opencode / Gemini / etc. config |
| 2. Register MCP into agents | `codegraph install -y` | Adds the `codegraph` MCP server to Claude Code / Cursor / Codex / opencode / Gemini / etc. config. Use `-y` — a bare `codegraph install` prompts interactively and hangs in a non-TTY agent context |
| 3. Build the index | `codegraph init -i` | Creates `.codegraph/` and indexes the repo |
| 4. Keep it fresh later | `codegraph sync` | Incremental update since last index |

---

## The restart reality — be honest about it

Registering the MCP server (`codegraph install`) makes the `codegraph_*` **MCP tools** available
Registering the MCP server (`codegraph install -y`) makes the `codegraph_*` **MCP tools** available
**only after the agent/IDE restarts** — and **you cannot restart yourself or your host app**. So:

- Do **everything that does not need a restart** right now: install the CLI, `codegraph install`,
- Do **everything that does not need a restart** right now: install the CLI, `codegraph install -y`,
`codegraph init -i`, `codegraph sync`.
- **Use the `codegraph` CLI via your shell/Bash immediately** for the current task — it works
without the MCP tools (`codegraph query`, `codegraph context <task>`, `codegraph callers`,
`codegraph callees`, `codegraph impact`, `codegraph files`, `codegraph status`).
- Then **explicitly ask the user to restart** the agent/IDE (Claude Code: restart or `/mcp`
reconnect; Cursor: Reload Window; Codex/Gemini/opencode/Kimi: restart the CLI; Antigravity/Qoder:
restart the IDE) so the `codegraph_*` MCP tools load, and resume the task afterward.
- **After the restart, VERIFY the `codegraph_*` tools actually loaded** — don't assume the restart
worked. If they're still missing, the usual cause is a **PATH mismatch**: the CLI installer links
the binary into `~/.local/bin`, which is often **not** on the PATH a GUI-launched agent inherits
(VS Code, desktop apps), so the MCP server — registered as the bare command `codegraph` — fails to
spawn **silently**. To fix, find the real binary with `command -v codegraph` (try
`~/.local/bin/codegraph --version` if PATH can't see it), then EITHER add `~/.local/bin` to PATH
(e.g. append `export PATH="$HOME/.local/bin:$PATH"` to the shell profile) **or** re-register the
server with the absolute path — rewrite the `codegraph` MCP entry's `command` from `"codegraph"` to
the absolute binary path (e.g. `"$HOME/.local/bin/codegraph"`) in the agent's MCP config, then
restart once more. The absolute-path form is the more robust fix because it does not depend on the
agent's PATH.
- **Never claim you restarted yourself.** Never fabricate that the MCP tools are available when
they are not — verify, or use the CLI.

Expand Down Expand Up @@ -969,6 +1000,18 @@ primer_gitignore() { # primer_gitignore GITIGNORE_FILE
else note "could not update $gi (add .primer/ manually)"; fi
}

# Idempotently gitignore CodeGraph's machine-local index. The codegraph-policy has the agent
# run `codegraph init -i`, which writes a per-machine `.codegraph/` index that must never be
# committed — on a team-shared project install nothing else stops someone checking it in.
codegraph_gitignore() { # codegraph_gitignore GITIGNORE_FILE
local gi="$1"
if [ "$DRYRUN" = 1 ]; then note "would add .codegraph/ to $gi"; return 0; fi
if [ -f "$gi" ] && grep -qE '^/?\.codegraph/?$' "$gi" 2>/dev/null; then return 0; fi
if printf '\n# codegraph: local code-structure index (rebuilt per machine; do not commit)\n.codegraph/\n' >> "$gi" 2>/dev/null; then
note "added .codegraph/ to $gi"
else note "could not update $gi (add .codegraph/ manually)"; fi
}

selected() { case ",$AGENTS," in *",$1,"*) return 0 ;; *) return 1 ;; esac }

# Once-mode is the default. With --always, every wired hook command gets the flag so the
Expand Down Expand Up @@ -1036,6 +1079,9 @@ else
note "would place kit in $KIT_DEST"
fi

# On a project install the CodeGraph index lands at the repo root — keep it out of version control.
[ "$SCOPE" = "project" ] && codegraph_gitignore "$ROOT/.gitignore"

# --- per-agent wiring ----------------------------------------------------------

if selected claude; then
Expand Down Expand Up @@ -1612,6 +1658,55 @@ PY
else FAILED=1; note "ERROR: failed to remove $tag hooks from $file"; fi
}

# Reverse install's Gemini `context.fileName` additions (AGENTS.md / GEMINI.md), but ONLY for
# entries whose instruction file is now gone — a dangling reference. If the file still exists the
# user may rely on it, so we leave it. Args after FILE are NAME=PATH pairs; NAME is pruned only when
# PATH does not exist. Tidies an emptied fileName/context. Atomic; refuses malformed JSON.
prune_gemini_filename() { # prune_gemini_filename SETTINGS_JSON NAME=PATH [NAME=PATH ...]
local file="$1"; shift; [ -f "$file" ] || return 0
local prune="" pair name path
for pair in "$@"; do
name="${pair%%=*}"; path="${pair#*=}"
[ -e "$path" ] || prune="$prune $name"
done
prune="$(printf '%s' "$prune" | sed 's/^ *//')"
[ -z "$prune" ] && return 0
if [ "$DRYRUN" = 1 ]; then note "would prune dangling fileName entries ($prune) from $file"; return 0; fi
if [ "$HAVE_PY" = 0 ]; then note "python3 not found — remove dangling [$prune] from context.fileName in $file by hand"; return 0; fi
if CG_FILE="$file" CG_PRUNE="$prune" "$PY" - <<'PY'
import os, json, sys, tempfile
f=os.environ["CG_FILE"]; prune=set(os.environ["CG_PRUNE"].split())
raw=open(f,encoding="utf-8").read()
if not raw.strip(): sys.exit(0)
try: data=json.loads(raw)
except Exception as ex:
sys.stderr.write(f"[agent-primer] {f}: invalid JSON ({ex}); refusing to modify it\n"); sys.exit(2)
if not isinstance(data, dict): sys.exit(0)
ctx=data.get("context")
if not isinstance(ctx, dict): sys.exit(0)
names=ctx.get("fileName")
if isinstance(names, str): names=[names]
if not isinstance(names, list): sys.exit(0)
new=[n for n in names if n not in prune]
if new==names: sys.exit(0)
if new: ctx["fileName"]=new
else:
ctx.pop("fileName", None)
if not ctx: data.pop("context", None)
text=json.dumps(data, indent=2)+"\n"
d=os.path.dirname(f) or "."; fd,tmp=tempfile.mkstemp(dir=d, prefix=".ap-", suffix=".tmp")
try:
with os.fdopen(fd,"w",encoding="utf-8") as o: o.write(text)
os.replace(tmp,f)
except Exception as ex:
try: os.unlink(tmp)
except OSError: pass
sys.stderr.write(f"[agent-primer] {f}: write failed ({ex})\n"); sys.exit(3)
PY
then note "pruned dangling fileName entries ($prune) from $file"
else FAILED=1; note "ERROR: failed to prune fileName entries from $file"; fi
}

note "uninstall scope=$SCOPE target=$ROOT agents=$AGENTS dry-run=$DRYRUN purge=$PURGE"

if selected claude; then
Expand All @@ -1624,7 +1719,15 @@ if selected cursor; then
[ -n "$CURSOR_RULE_DIR" ] && for n in $STANDALONE_NAMES; do rm_path "$CURSOR_RULE_DIR/$n.mdc"; done
unhook_json "$HFILE" cursor
fi
if selected gemini; then strip_markers "$GEMINI_INSTR"; unhook_json "$GS" gemini; fi # leaves context.fileName (harmless, user may rely on it)
if selected gemini; then
strip_markers "$GEMINI_INSTR"; unhook_json "$GS" gemini
# Reverse install's context.fileName additions — but only entries now pointing at a deleted
# file (strip_markers removes GEMINI.md/AGENTS.md when they held only our blocks). A file the
# user still has is left referenced. AGENTS.md is project-scope only: globally that entry means
# "read each project's AGENTS.md", which agent-primer's global install does not own.
if [ "$SCOPE" = "project" ]; then prune_gemini_filename "$GS" "GEMINI.md=$GEMINI_INSTR" "AGENTS.md=$ROOT/AGENTS.md"
else prune_gemini_filename "$GS" "GEMINI.md=$GEMINI_INSTR"; fi
fi
if selected opencode; then rm_path "$OPENCODE_PLUG"; rm_path "${OPENCODE_PLUG%/*}/primer-session-check.js"; strip_markers "$OPENCODE_INSTR"; fi
if selected antigravity; then
[ -n "$ANTI_RULE_DIR" ] && for n in $STANDALONE_NAMES; do rm_path "$ANTI_RULE_DIR/$n.md"; done
Expand Down
21 changes: 17 additions & 4 deletions codegraph-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ exists.
1. **Is the `codegraph` CLI installed?** — `command -v codegraph` (or `codegraph --version`).
- **No →** ask the user this exact simple question, then install if they say yes:
"CodeGraph is not installed yet. Want me to install it and index this repo now? I will run:
`<install command>`, `codegraph install`, and `codegraph init -i`."
`<install command>`, `codegraph install -y`, and `codegraph init -i`."
Use `codegraph install -y` (non-interactive). A bare `codegraph install` opens an interactive
agent-picker prompt that has no TTY in an agent context and will hang session startup.
2. **Is THIS project indexed?** — does `.codegraph/` exist at the repo root, and does
`codegraph status` succeed?
- **No →** ask: "CodeGraph is installed, but this repo is not indexed yet. Want me to run
Expand Down Expand Up @@ -68,25 +70,36 @@ announce each command before running it (it touches the user's machine), in orde
| 1. Install CLI (macOS/Linux) | `curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh \| sh` | Self-contained binary; no Node required |
| 1. Install CLI (any OS, alt) | `npm i -g @colbymchenry/codegraph` | npm alternative |
| 1. Install CLI (Windows) | `irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 \| iex` | PowerShell |
| 2. Register MCP into agents | `codegraph install` | Adds the `codegraph` MCP server to Claude Code / Cursor / Codex / opencode / Gemini / etc. config |
| 2. Register MCP into agents | `codegraph install -y` | Adds the `codegraph` MCP server to Claude Code / Cursor / Codex / opencode / Gemini / etc. config. Use `-y` — a bare `codegraph install` prompts interactively and hangs in a non-TTY agent context |
| 3. Build the index | `codegraph init -i` | Creates `.codegraph/` and indexes the repo |
| 4. Keep it fresh later | `codegraph sync` | Incremental update since last index |

---

## The restart reality — be honest about it

Registering the MCP server (`codegraph install`) makes the `codegraph_*` **MCP tools** available
Registering the MCP server (`codegraph install -y`) makes the `codegraph_*` **MCP tools** available
**only after the agent/IDE restarts** — and **you cannot restart yourself or your host app**. So:

- Do **everything that does not need a restart** right now: install the CLI, `codegraph install`,
- Do **everything that does not need a restart** right now: install the CLI, `codegraph install -y`,
`codegraph init -i`, `codegraph sync`.
- **Use the `codegraph` CLI via your shell/Bash immediately** for the current task — it works
without the MCP tools (`codegraph query`, `codegraph context <task>`, `codegraph callers`,
`codegraph callees`, `codegraph impact`, `codegraph files`, `codegraph status`).
- Then **explicitly ask the user to restart** the agent/IDE (Claude Code: restart or `/mcp`
reconnect; Cursor: Reload Window; Codex/Gemini/opencode/Kimi: restart the CLI; Antigravity/Qoder:
restart the IDE) so the `codegraph_*` MCP tools load, and resume the task afterward.
- **After the restart, VERIFY the `codegraph_*` tools actually loaded** — don't assume the restart
worked. If they're still missing, the usual cause is a **PATH mismatch**: the CLI installer links
the binary into `~/.local/bin`, which is often **not** on the PATH a GUI-launched agent inherits
(VS Code, desktop apps), so the MCP server — registered as the bare command `codegraph` — fails to
spawn **silently**. To fix, find the real binary with `command -v codegraph` (try
`~/.local/bin/codegraph --version` if PATH can't see it), then EITHER add `~/.local/bin` to PATH
(e.g. append `export PATH="$HOME/.local/bin:$PATH"` to the shell profile) **or** re-register the
server with the absolute path — rewrite the `codegraph` MCP entry's `command` from `"codegraph"` to
the absolute binary path (e.g. `"$HOME/.local/bin/codegraph"`) in the agent's MCP config, then
restart once more. The absolute-path form is the more robust fix because it does not depend on the
agent's PATH.
- **Never claim you restarted yourself.** Never fabricate that the MCP tools are available when
they are not — verify, or use the CLI.

Expand Down
30 changes: 24 additions & 6 deletions codegraph-session-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ emit() {
esac
}

# An initialized index = the .codegraph/ dir AND at least one SQLite db file inside it.
# We check for the db file rather than running `codegraph status` on purpose: a bare
# .codegraph/ directory left behind by an aborted/half-finished `init` would otherwise
# look "set up" and make once-mode go silent on a broken index. Running `codegraph status`
# every session is exactly the cost once-mode removes, so this cheap filesystem check is the
# right middle ground; deep corruption is still `codegraph status`/--always's job.
index_initialized() {
[ -d "$PROJECT_DIR/.codegraph" ] || return 1
for _db in "$PROJECT_DIR"/.codegraph/*.db; do
[ -f "$_db" ] && return 0
done
return 1
}

# --- checks ----------------------------------------------------------------

if ! command -v codegraph >/dev/null 2>&1; then
Expand All @@ -107,18 +121,22 @@ direct yes/no question in chat:

CodeGraph is not installed yet. Want me to install it and index this repo now? I will run:
${INSTALL_SH}
codegraph install
codegraph install -y
codegraph init -i

If the user says yes, announce each command, run the three commands, then ask them to RESTART this
agent/IDE so the codegraph_* MCP tools load. Until restart, use the \`codegraph\` CLI directly.
agent/IDE so the codegraph_* MCP tools load. (Use \`codegraph install -y\`: a bare \`codegraph
install\` prompts interactively and hangs without a TTY.) After the restart, VERIFY the codegraph_*
tools loaded; if they are missing, the binary is usually in ~/.local/bin off the agent's PATH — add
it to PATH or re-register the MCP server's command with the absolute path. Until restart, use the
\`codegraph\` CLI directly.
If the user says no, proceed without CodeGraph and mention that structural code answers may be weaker."
exit 0
fi

if [ ! -d "$PROJECT_DIR/.codegraph" ]; then
emit "[CodeGraph] CLI present, but this project is NOT initialized (no .codegraph/ at
${PROJECT_DIR}).
if ! index_initialized; then
emit "[CodeGraph] CLI present, but this project is NOT initialized (no index DB under
${PROJECT_DIR}/.codegraph/).
Do NOT leave this as a passive note. Before substantive work, ask using the host's structured
prompt/confirmation dialog when one is available (the same kind of UI used for permissions or
command approvals, such as a request_user_input or confirm tool). If no such tool exists, ask this
Expand All @@ -127,7 +145,7 @@ direct yes/no question in chat:
CodeGraph is installed, but this repo is not indexed yet. Want me to run \`codegraph init -i\` now?

If the user says yes, announce and run \`codegraph init -i\`. If the codegraph_* MCP tools are
missing afterwards, run \`codegraph install\` and ask the user to restart this agent/IDE.
missing afterwards, run \`codegraph install -y\` and ask the user to restart this agent/IDE.
If the user says no, proceed without CodeGraph and mention that structural code answers may be weaker."
exit 0
fi
Expand Down
Loading
Loading