Skip to content

bug: CLAUDE.md-driven prime is redundant with SessionStart hook and causes duplicate registrations #529

@galexy

Description

@galexy

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:

  1. Once from the SessionStart hook with the correct AGENT_ENV=claude-code → registers agent_type=claude.
  2. 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):

  1. Remove the ox-managed prime block from CLAUDE.md entirely. Hooks cover it.
  2. Remove the top-of-file "BLOCKING: Run ox agent prime NOW" directive. Same reason.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions