Symptom
CLAUDE.md (and AGENTS.md) both instruct the agent to run ox agent prime at the start of every session:
From CLAUDE.md top:
BLOCKING: Run ox agent prime NOW before ANY other action. Do NOT respond to the user first.
From the ox-managed block near the bottom:
AGENT_ENV=pi ox agent prime
But .claude/settings.json (installed by ox init) already runs an equivalent command from the SessionStart hook:
SessionStart: AGENT_ENV=claude-code ox agent hook SessionStart
The hook fires before the agent sees the user's first message. By the time the agent reads CLAUDE.md and follows the "BLOCKING" instruction, priming is already done.
Impact
Every Claude Code session in an ox repo performs priming twice:
- Once from the SessionStart hook with the correct
AGENT_ENV=claude-code → registers agent_type=claude.
- Once from the CLAUDE.md instruction — using whatever
AGENT_ENV the block hardcodes.
Observed in the wild during #519 investigation — fervent-curie's agent_instances.jsonl had 3 entries for the same agent_id within 3 minutes:
21:19:35 agent_type=claude ← SessionStart hook (correct)
21:21:55 agent_type=pi ← CLAUDE.md-driven re-prime
21:22:00 agent_type=pi ← another CLAUDE.md-driven re-prime
Combined with the sibling issue (CLAUDE.md → AGENTS.md symlink causing Pi's block to be served), every manual re-prime mislabels the registration. Even fixing the AGENT_ENV mismatch, the duplication itself is wasted work and extra state-store churn.
Why this was added (likely)
Defensive coverage for:
- Agents that don't support hook config (no Claude Code settings.json equivalent).
- Session resume /
/clear / /compact scenarios where hooks may or may not fire.
But for Claude Code specifically, the hook path is reliable and covers all these cases — including /clear (there's a SessionStart variant for resumes). The CLAUDE.md instruction is belt-and-suspenders that actively causes harm.
Fix direction
For adapters with reliable hook support (Claude Code, Codex):
- Remove the ox-managed prime block from CLAUDE.md entirely. Hooks cover it.
- Remove the top-of-file "BLOCKING: Run ox agent prime NOW" directive. Same reason.
- Keep the prime block only in
AGENTS.md (or Pi's equivalent) for adapters that genuinely have no hook mechanism.
The ox init templates in cmd/ox/integrate.go and related files would need per-adapter branching.
Alternative: make ox agent prime idempotent and free when a prime already happened in this process. The --idempotent flag already exists and is used in some paths. Making the CLAUDE.md-driven prime use it would mean the duplicate call is nearly free (skips context loading) but still cheap and doesn't clutter agent_instances.jsonl.
Acceptance
- A fresh Claude Code session in an ox repo produces exactly one registration in
agent_instances.jsonl (from the hook), not three.
/clear and /compact flows still re-prime correctly.
- Adapters without hook support still prime via their instruction file.
Related
Symptom
CLAUDE.md(andAGENTS.md) both instruct the agent to runox agent primeat the start of every session:From
CLAUDE.mdtop:From the ox-managed block near the bottom:
But
.claude/settings.json(installed byox init) already runs an equivalent command from the SessionStart hook:The hook fires before the agent sees the user's first message. By the time the agent reads
CLAUDE.mdand follows the "BLOCKING" instruction, priming is already done.Impact
Every Claude Code session in an ox repo performs priming twice:
AGENT_ENV=claude-code→ registersagent_type=claude.AGENT_ENVthe block hardcodes.Observed in the wild during #519 investigation — fervent-curie's
agent_instances.jsonlhad 3 entries for the same agent_id within 3 minutes:Combined with the sibling issue (
CLAUDE.md → AGENTS.mdsymlink causing Pi's block to be served), every manual re-prime mislabels the registration. Even fixing theAGENT_ENVmismatch, the duplication itself is wasted work and extra state-store churn.Why this was added (likely)
Defensive coverage for:
/clear//compactscenarios where hooks may or may not fire.But for Claude Code specifically, the hook path is reliable and covers all these cases — including
/clear(there's a SessionStart variant for resumes). The CLAUDE.md instruction is belt-and-suspenders that actively causes harm.Fix direction
For adapters with reliable hook support (Claude Code, Codex):
AGENTS.md(or Pi's equivalent) for adapters that genuinely have no hook mechanism.The
ox inittemplates incmd/ox/integrate.goand related files would need per-adapter branching.Alternative: make
ox agent primeidempotent and free when a prime already happened in this process. The--idempotentflag already exists and is used in some paths. Making the CLAUDE.md-driven prime use it would mean the duplicate call is nearly free (skips context loading) but still cheap and doesn't clutteragent_instances.jsonl.Acceptance
agent_instances.jsonl(from the hook), not three./clearand/compactflows still re-prime correctly.Related
CLAUDE.md → AGENTS.mdsymlink causes the redundant prime to also use the wrongAGENT_ENV.