[bug] Codex never gets the team rules: session-start hook in project scope, $CODEX_HOME/AGENTS.md in user scope
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- git, node.js, typescript
- Domain
- cli, developer-experience, devtools
Research direction
Start with the Codex tool paths in src/types.ts and rule delivery in src/resources/rules.ts, then trace pull, uninstall, and doctor handling in src/pull.ts, src/uninstall.ts, and src/doctor-delivery.ts. Run the named rules.test.ts, uninstall.test.ts, doctor-delivery tests, types.test.ts, and tclaude-tcodex.test.ts; done means the acceptance criteria pass for Codex-family tools, cleanup, diagnostics, and documentation.
Written by the indexing model from the issue text.
Description
Description
Codex never receives the team rules. pull copies each rule to .codex/rules/<name>.md, and doctor then reports ✔ Rules delivered to codex. But Codex uses .codex/rules/ for command-policy files (*.rules), and it ignores the .md files there. It reads instructions from AGENTS.md. Asked for a rule's content, codex exec answers that it has none. This happens in first sessions, later sessions and subagents alike. codex-internal and tcodex have the same tool paths.
Claude, pulled in the same run, gets the rule.
pull src/pull.ts:1290
RulesHandler.pullAllRules src/resources/rules.ts:433
Hermes: rules inlined into SOUL.md src/resources/rules.ts:442 the only tool that gets rules in an instruction file
pullItem → deliveryTargets src/resources/rules.ts:312, :246
every tool with toolPaths.rules
codex → .codex/rules/<name>.md, verbatim src/types.ts:326 (codex-internal :327, tcodex :335)
legacy: strip [teamai:rules] from every claudemd src/resources/rules.ts:584
syncManagedInstructions (culture, claudemd/) src/pull.ts:1833 needs toolPaths.claudemd, which codex lacks
injectRecallBlockIntoTools src/pull.ts:1930 needs claudemd + agents, which codex lacks
doctor: "Rules delivered to <tool>" src/doctor-delivery.ts:282 checks the file exists, not that the tool reads it
With no claudemd path, Codex also misses the team culture and the shared claudemd/ instructions (verified), and the recall block that every other tool with claudemd + agents gets.
It never worked for Codex. v0.1.0 (8cb1fbac) inlined rules into CLAUDE.md for tools with a claudemd path, and Codex had only skills. 573a54cf ("distribute rule files instead of inlining into CLAUDE.md") added rules: '.codex/rules', and since then Codex has received copies it does not read. No tool gets team rules into AGENTS.md today: Pi, OMP, WorkBuddy and OpenClaw get them in their own rules directories, and their AGENTS.md carries culture, shared instructions and recall only.
Today and expected
| # | Area | Today (0.22.0) | Expected |
|---|---|---|---|
| 1 | Team rules, project scope | Copied to .codex/rules/<name>.md. Codex ignores it, and codex exec answers NONE |
Inlined in a [teamai:team-rules] block in <project>/AGENTS.md, and codex exec returns the rule |
| 2 | Team rules, user scope | Copied to ~/.codex/rules/<name>.md |
Block in ~/.codex/AGENTS.md |
| 3 | Path-scoped rules (paths:) |
Codex gets a raw copy. Hermes SOUL.md inlines the frontmatter verbatim |
Frontmatter stripped, with a leading Applies to files matching: <globs> line, for Codex and Hermes (one renderer) |
| 4 | Culture, shared claudemd/ |
Never reach Codex | Blocks in the same AGENTS.md |
| 5 | Recall | No block. With recall on, the built-in teamai-recall.md is written to .codex/rules, where Codex does not read it |
Recall block injected as for every tool with claudemd + agents, and removed when recall is turned off |
| 6 | Copies left by earlier pulls | — | Pull removes the .codex/rules/*.md copies that still match what teamai delivered (incl. teamai-recall.md). An edited copy is kept, and the pull names it. *.rules and files teamai did not deliver are never touched. The dir is removed only when empty |
| 7 | Project AGENTS.md shared with Pi / Hermes / WorkBuddy |
— | One team-rules block per file. The legacy [teamai:rules] strip does not remove it |
| 8 | Codex disabled or not installed | — | The next pull removes the block when no active Codex-family tool maps the file. No AGENTS.md or ~/.codex is created on a machine without Codex |
| 9 | uninstall |
Removes the .codex/rules copies |
Full uninstall removes the block and the old copies. --agent codex removes only the blocks that no remaining tool on that file writes |
| 10 | doctor |
✔ Rules delivered to codex, a false positive |
Team rules are inlined in Codex AGENTS.md compares the block with the team rules. It fails when an AGENTS.override.md shadows the file, and when a team toolPaths gives Codex no instructions file |
| 11 | codex-internal, tcodex |
Same as codex | Same as codex. Their user-scope files (~/.codex-internal/AGENTS.md, ~/.tcodex/AGENTS.md) are assumed, not verified, and the code comment says so |
| 12 | Docs | Say nothing about where Codex reads rules | docs/usage-guide.md and .zh-CN.md updated: rules, namespace replacement, doctor, uninstall --agent, and the toolPaths override note |
Acceptance criteria
- 1: A pull with Codex enabled in project scope writes the team rules into a
[teamai:team-rules]block in<project>/AGENTS.mdand writes nothing to.codex/rules. User content outside the markers is kept. - 1: When the team has no rules, the block is removed, and so is an
AGENTS.mdthat held nothing else. - 2: In user scope the block is written to
~/.codex/AGENTS.md. - 3: A rule with
paths:is inlined without frontmatter, after anApplies to files matching: <globs>line, in Codex's block and in Hermes'SOUL.mdblock. Doctor's Hermes check compares against the same render. - 4: The culture and shared
claudemd/blocks are written to Codex'sAGENTS.md. - 5: With recall on, the recall block is in Codex's
AGENTS.md.teamai recall offremoves it. - 6: A pull removes an unchanged
.codex/rules/<rule>.mdandteamai-recall.md. It keeps an edited copy and names it in an English warning. It leavesdefault.rulesalone, and removes the directory only when it is empty. - 7: With Codex and Pi enabled, the project
AGENTS.mdholds exactly one team-rules block after two pulls. - 8: Disabling Codex and pulling removes the block. A pull where Codex is not installed creates no
AGENTS.mdand no~/.codex. - 9: A full
uninstallremoves the block and the old copies.uninstall --agent codexwith Pi still enabled removes the team-rules block and keeps the blocks Pi writes. - 10:
doctorpasses on a current block, and fails with an English, actionable message on a stale block, on anAGENTS.override.mdbeside the file, and on a Codex entry with noclaudemdpath.Rules delivered to codexis no longer reported. - 11:
codex-internalandtcodexbehave as in 1–10. - 12: Both usage guides are updated, and a grep for
.codex/rulesindocs/andskill-data/finds no stale wording. - Closing: the PR body maps every row above to the test that covers it, and pastes a real-CLI run (
npm run build,node dist/index.js) wherecodex execreturns the rule in project scope and in user scope.
Proposed fix
# src/types.ts, toolPaths defaults (codex-internal and tcodex get the same shape)
-codex: { skills: '.codex/skills', rules: '.codex/rules', settings: '.codex/hooks.json', agents: '.codex/agents', mcp: '.codex/config.toml' },
+codex: { skills: '.codex/skills', settings: '.codex/hooks.json', agents: '.codex/agents', mcp: '.codex/config.toml',
+ claudemd: 'AGENTS.md', userScope: { claudemd: '.codex/AGENTS.md' } },
+TEAMAI_TEAM_RULES_START = '<!-- [teamai:team-rules:start] -->' # not [teamai:rules]: the legacy strip at rules.ts:584 would delete it
pullAllRules
Hermes: upsertSoulRules(inlinedRulesText(rules)) # hermesRulesText renamed, strips frontmatter, adds "Applies to"
+ Codex family: sync the team-rules block in each claudemd file, once per path
+ written while a Codex-family tool mapping the file is enabled and installed, removed otherwise
+ reclaim the old .codex/rules/*.md copies (isDeliveredRender, as reclaimUnselectedTeamRules does)
…
syncManagedInstructions
- if (toolPath.rules && !installed(toolPath.rules)) continue
+ probe = toolPath.rules ?? toolPath.settings # unchanged for every existing tool; gives Codex a real probe
rulesis dropped rather than special-cased. Push scanning, the stale sweep,deployBuiltinRules, pre-push sync and doctor's per-file check all readrulesas "a directory the tool loads".uninstall: add the new marker toCLAUDEMD_MARKER_PAIRS(src/uninstall.ts:169), and scan the old rules directory.retainedInstructionFiles(src/uninstall.ts:635) keeps whole files today, so it has to decide per block.- Doctor: a check next to the Hermes one in
buildRulesActivationChecks. - Tests: new cases in
rules.test.ts,uninstall.test.tsand the doctor-delivery tests. Update the default-path assertions intypes.test.tsandtclaude-tcodex.test.ts. The other.codex/rulesfixtures set their owntoolPathsand keep passing.
Non-goals
CODEX_HOME: teamai writes every Codex path under~/.codexand ignoresCODEX_HOME(onlysrc/models/switch.ts:88reads it). That affects skills, hooks and agents too, so it is a separate issue: #939.- A tracked or newly created project
AGENTS.mdshows up ingit status. Pi, WorkBuddy and Hermes already write there, and #915 covers keeping delivered files out of git. - Merging built-in defaults into a team's own
toolPaths. A team that overridestoolPathsreplaces the defaults wholesale, so it has to addclaudemdfor Codex itself. Doctor names that case (row 10) and the docs say so (row 12). - Warning when the inlined rules push
AGENTS.mdpast Codex's project-doc size limit.
Reproduction
A throwaway sandbox with its own HOME and CODEX_HOME, and a local bare team repo.
- Seed the team repo, then bridge its URL:
# seed: teamai.yaml (team, repo: https://example.invalid/x/team.git, provider: git) and # rules/sbx-rule.md = "The team codeword is PELICAN-42." git clone --bare seed team.git HOME=$SBX/home git config --global url.$SBX/team.git.insteadOf https://example.invalid/x/team.git - In a git repo
project/, withHOME=$SBX/home:
Result:node dist/index.js init https://example.invalid/x/team.git --provider git --scope project --agent claude,codex --force mkdir .claude .codex node dist/index.js pull --force --verbose.claude/rules/sbx-rule.mdand.codex/rules/sbx-rule.mdare written. NoAGENTS.mdis created. - Ask Codex:
Result:CODEX_HOME=$SBX/codex-home codex exec --skip-git-repo-check -s read-only \ "Without reading any files or running any commands, answer from your instructions only: what is the team codeword? If your instructions do not state one, reply exactly NONE."NONE. node dist/index.js doctorreports✔ Rules delivered to codex.
Controls, run with the same codex exec and a different codeword in each file:
| File | Codex read it |
|---|---|
<project>/AGENTS.md, text inside <!-- [teamai:…:start/end] --> markers |
yes |
<project>/.codex/AGENTS.md |
no |
$CODEX_HOME/AGENTS.md |
yes |
<project>/AGENTS.md with <project>/AGENTS.override.md beside it |
only the override |
Adding claudemd/shared.md to the team repo and pulling again writes the shared-instructions block to .claude/CLAUDE.md only.
Environment
- OS: macOS 27.0
- Node.js: v24.21.0
- teamai: 0.22.0 (
origin/maindf940cdd) - Provider:
git(the bug does not depend on the provider) - AI tool(s): Codex (
codex-cli 0.159.2), Claude Code
Logs
pull --force --verbose (excerpt) and doctor
✔ [project] Team repo: already up to date
[debug] Synced rule sbx-rule → claude
[debug] Synced rule sbx-rule → codex
✔ [project] Synced 1 rule(s)
…
✔ Updated teamai hooks in <sandbox>/home/.claude/settings.json
✔ Updated teamai hooks in <sandbox>/home/.codex/hooks.json
✔ claude is installed
✔ codex is installed
✔ teamai hooks in claude settings
✔ teamai hooks in codex settings
✔ Rules delivered to claude
✔ Rules delivered to codex
…
✔ All checks passed!
I'll open a PR that covers every row in the table.
- Dominant language
- TypeScript
- Stars
- 5.6k
- Forks
- 471
- Avg merge
- 20h 16m
- Merged PRs (30d)
- 399
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Tencent/teamai-cli
-
bug help wanted
Difficulty 3/5 1-2 days Newbie friendliness 64/100
Tencent/teamai-cli#1539 ·
Maintainers usually reply within 1 day
-
[bug] codebase --deep-enrich in a team repo reports success but never publishes, and leaves the team clone dirtyPossibly taken @Kiddo4993 claimed this today. Openbug help wanted
Difficulty 4/5 1-2 days Newbie friendliness 35/100
Tencent/teamai-cli#1537 ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 70/100
Tencent/teamai-cli#1523 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Tencent/teamai-cli#1516 ·
Maintainers usually reply within 1 day
-
bug help wanted
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Tencent/teamai-cli#1504 · 2 comments ·
Maintainers usually reply within 1 day
All issues in Tencent/teamai-cli
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Graphify-Labs/graphify#4860 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
sveltejs/eslint-plugin-svelte#1615 ·
Maintainers usually reply within 7 days
-
Parallel reticle_verify opens per-flow leases without the source lease's ignoreHTTPSErrorsPossibly taken @as992949791 claimed this today. Opengood first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
reticlehq/reticle#2033 · 1 comment ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day