You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
teamai copies a rule to a directory the tool never reads,
or the tool reads the copy but ignores paths:,
or teamai delivers nothing,
or teamai writes them to the wrong place. A project pull rewrites the global Hermes SOUL.md block, and OpenCode's user-scope glob loads the project's rules/*.md instead of the user rules.
doctor still reports ✔ Rules delivered. It compares the copy with what teamai renders, not with what the tool reads.
The evidence comes from real runs of codex exec 0.159.2, OpenCode 1.18.21 against a mock model, and Copilot CLI 1.0.90 with the request captured. The rule parsers of Cursor CLI 2026.09.22, CodeBuddy 2.160.0, the JoyCode plugin 3.8.71 and Oh My Pi 18.2.1 were copied out of their bundles and run on teamai's output. Pi 0.99.2, ZCode 3.14.3, DeepSeek Harness, Hermes, OpenClaw and the WorkBuddy engine in CodeBuddy 2.160.0 come from their source, and Kiro and Qoder from their docs. Qoder Desktop's rule format comes from the rule files in alibaba/tron-one-agent, since its docs publish none.
Proposal
tool has its own rules format → write each rule in that format, project and user scope
user scope, no rules format → a file only that tool reads, in its home
project scope, no rules format → the session-start hook or extension adds the project's rules
no channel reaches the model → nothing, and init/doctor say why
never → the shared AGENTS.md or another tool's file
User scope uses a file, not the hook, as #945 does for the instruction blocks. The tool reads the file in every session and again after compaction, resume does not duplicate it, it needs no hook trust, and doctor can compare its bytes. With the hook instead, Codex skips an untrusted hook without a warning, and passes output over about 2,500 tokens only as a preview unless the entry raises its limit. ZCode and DeepSeek Harness lose the hook text at compaction.
With the user rules in files, the hook carries only the project's rules, and adds nothing when the cwd resolves to user scope. hook-dispatch resolves one scope per cwd, so it needs no second config.
The hook path already exists. #940 added teamRulesHandler, which gives Codex the project's rules at session-start and subagent-start, and nothing on resume or outside a project. ZCode and DeepSeek Harness join it through getsRulesFromSessionHook (rule-format.ts). Why Codex has no project file of its own: #938. Shared AGENTS.md: why not.
teamai parses paths: once, and each renderer writes the tool's form. The channels with no path scoping (Pi, ZCode, DeepSeek Harness, OpenClaw, JoyCode's rules.txt) reuse inlinedRulesText from #940, which Codex and Hermes already get: frontmatter dropped, and a scoped rule led by Applies to files matching: <globs> (a path hint for the model, not automatic filtering). Kiro, Qoder, CodeBuddy and Oh My Pi get the team file verbatim today. CodeBuddy's parser reads lines, not YAML, so an inline paths: ["a", "b"] turns into globs with the brackets in them.
Per tool
✓ works today · ◐ partly (rules lost or paths: ignored) · ✗ never
Tool
Today
Change, project scope
Change, user scope
Claude Code
✓
none
none
Copilot CLI
✓
none
none
Cursor
✓
none. Its parser removes the quotes teamai writes around globs, and Cursor writes them the same way
none. Cursor CLI reads ~/.cursor/rules only by walking up from a cwd under $HOME (loadRulesFromDirAndAncestors, 2026.09.22); the IDE is not checked
Kiro
◐
inclusion: fileMatch + fileMatchPattern as a list; inclusion: always when unscoped
same, ~/.kiro/steering
Qoder, Qoder CN
✓ CLI
trigger: glob + one-line glob: with {a,b} expanded, the form Qoder Desktop writes; trigger: always_on when unscoped. The CLI docs say it reads Desktop's rules
same, ~/.qoder/rules, ~/.qoder-cn/rules
CodeBuddy
◐
alwaysApply: false and paths: as a block list when scoped
same, ~/.codebuddy/rules
WorkBuddy
✗ project · ◐ user
rules into .codebuddy/rules, CodeBuddy's format, one copy when both tools are enabled. Removing one tool keeps the copy while the other still uses it, as #945 does for its blocks
CodeBuddy's format, ~/.workbuddy/rules. WorkBuddy reads user rules and skills from one home, ~/.workbuddy
JoyCode
◐ project · ✗ user
its own render: globs unquoted and {a,b} expanded. It keeps the quotes and splits on every comma
a block in ~/.joycode/rules.txt, no path scoping
Oh My Pi
✗
alwaysApply: true when unscoped; globs + a generated description when scoped (it drops rules with neither); namespaced rules flat, since it reads one level. Its own rules, not teamai's extension, so paths: keeps its scoping
same, ~/.omp/agent/rules
OpenCode
◐ project · ✗ user
glob .opencode/rules/**/*.md, so namespaced rules load, registered in .opencode/opencode.json as #945 does; the glob in the root opencode.json is reclaimed. It applies every rule always
glob ~/.config/opencode/rules/*.md and one per namespace directory. Today's rules/*.md resolves from the session cwd
the rules join the context teamai's Pi extension already fetches through teamai hook-dispatch instructions (#952), added to event.systemPrompt from before_agent_start. Pi rebuilds the prompt for each turn, so they do not pile up
a block in ~/.pi/agent/AGENTS.md, which only Pi reads, beside #952's blocks
ZCode
✗
user-level SessionStart hook. Its CLI does not run project hooks
a block in ~/.zcode/AGENTS.md
DeepSeek Harness
✗
session-start hook, when dsh runs with teamai's --patch
a block in $DSH_HOME/AGENTS.md
Hermes
✓
nothing, and init/doctor say why. A project pull rewrites the global SOUL.md block today, and a project with no rules erases it (rules.ts:454-459)
keep the $HERMES_HOME/SOUL.md block, written only by a user-scope pull
OpenClaw
✗
nothing. Its project file is the shared AGENTS.md
a block in the workspace AGENTS.md, resolved the way the hooks resolve it (profile, OPENCLAW_WORKSPACE_DIR)
claude-internal and tclaude follow Claude Code's layout, and codex-internal and tcodex follow Codex's. They were not checked.
Known limits:
ZCode and DeepSeek Harness drop the hook text at compaction, so the project rules come back in the next session. DeepSeek Harness runs the hook detached, so the first request can miss it.
Codex runs the teamai hooks only once they are trusted in /hooks, and skips them silently otherwise. init/doctor say so.
Copilot CLI reads user rules from 0.0.412. From 1.0.89 it also reads .claude/rules in a project, so with Claude enabled each rule reaches it twice. teamai still writes both copies, as it does for every tool that also reads another tool's files.
Also in this change:
teamai's OpenClaw hook does nothing, so OpenClaw gets no report or sync either. The handler teamai generates reads ctx.event (openclaw-hooks.ts:84), but OpenClaw passes an event with type and action and no event field. It also subscribes to session:start, which OpenClaw does not emit. The handler should key on ${type}:${action} and subscribe to events OpenClaw emits (docs/automation/hooks/event-types.md).
README, rules column
✓ Claude Code, Cursor, Copilot CLI, Kiro, Qoder, Qoder CN, CodeBuddy, WorkBuddy, JoyCode (new row), Oh My Pi, Hermes, OpenClaw
✓* Codex, Pi, ZCode, DeepSeek Harness, OpenCode
✓* The rules reach the tool, but always on: it does not scope them by path (scoped inline rules include path hints for the model).
Codex, Pi and OpenCode change from ✓ to ✓*. DeepSeek Harness and ZCode change from — to ✓*. Hermes changes from — to ✓, and OpenClaw keeps ✓: user scope is their normal rules channel, so both get full ticks. All 5 README*.md change.
Done when
Each tool gets its rules as in the table, in each scope.
With teamai installed in both scopes, a tool gets the user rules and the project rules, each once.
A project-scope pull leaves the Hermes SOUL.md block as the user-scope pull wrote it.
OpenCode loads the user rules from ~/.config/opencode/rules and no project rules/*.md.
A pull reclaims the unedited team rules that WorkBuddy's one-time migration copied from ~/.codebuddy/rules into ~/.workbuddy/rules.
Each render has a test that runs the tool's own parser where it ships one. rules.test.ts:1115-1120 locks JoyCode to Cursor's quoted output and changes.
OpenClaw's hook runs teamai hook-dispatch on the events it maps.
doctor checks what each tool reads.
Codex: fixed by #940 (#938). Instruction blocks: #945, implemented by #952, whose Pi extension, ~/.pi/agent/AGENTS.md, Hermes plugin, OpenCode .opencode/opencode.json and shared .codebuddy/rules this issue reuses.
Problem
Most tools do not get the team rules as intended:
paths:,SOUL.mdblock, and OpenCode's user-scope glob loads the project'srules/*.mdinstead of the user rules.doctorstill reports✔ Rules delivered. It compares the copy with what teamai renders, not with what the tool reads.The evidence comes from real runs of
codex exec0.159.2, OpenCode 1.18.21 against a mock model, and Copilot CLI 1.0.90 with the request captured. The rule parsers of Cursor CLI 2026.09.22, CodeBuddy 2.160.0, the JoyCode plugin 3.8.71 and Oh My Pi 18.2.1 were copied out of their bundles and run on teamai's output. Pi 0.99.2, ZCode 3.14.3, DeepSeek Harness, Hermes, OpenClaw and the WorkBuddy engine in CodeBuddy 2.160.0 come from their source, and Kiro and Qoder from their docs. Qoder Desktop's rule format comes from the rule files inalibaba/tron-one-agent, since its docs publish none.Proposal
User scope uses a file, not the hook, as #945 does for the instruction blocks. The tool reads the file in every session and again after compaction, resume does not duplicate it, it needs no hook trust, and
doctorcan compare its bytes. With the hook instead, Codex skips an untrusted hook without a warning, and passes output over about 2,500 tokens only as a preview unless the entry raises its limit. ZCode and DeepSeek Harness lose the hook text at compaction.With the user rules in files, the hook carries only the project's rules, and adds nothing when the cwd resolves to user scope.
hook-dispatchresolves one scope per cwd, so it needs no second config.The hook path already exists. #940 added
teamRulesHandler, which gives Codex the project's rules atsession-startandsubagent-start, and nothing on resume or outside a project. ZCode and DeepSeek Harness join it throughgetsRulesFromSessionHook(rule-format.ts). Why Codex has no project file of its own: #938. SharedAGENTS.md: why not.teamai parses
paths:once, and each renderer writes the tool's form. The channels with no path scoping (Pi, ZCode, DeepSeek Harness, OpenClaw, JoyCode'srules.txt) reuseinlinedRulesTextfrom #940, which Codex and Hermes already get: frontmatter dropped, and a scoped rule led byApplies to files matching: <globs>(a path hint for the model, not automatic filtering). Kiro, Qoder, CodeBuddy and Oh My Pi get the team file verbatim today. CodeBuddy's parser reads lines, not YAML, so an inlinepaths: ["a", "b"]turns into globs with the brackets in them.Per tool
✓ works today · ◐ partly (rules lost or
paths:ignored) · ✗ neverglobs, and Cursor writes them the same way~/.cursor/rulesonly by walking up from a cwd under$HOME(loadRulesFromDirAndAncestors, 2026.09.22); the IDE is not checkedinclusion: fileMatch+fileMatchPatternas a list;inclusion: alwayswhen unscoped~/.kiro/steeringtrigger: glob+ one-lineglob:with{a,b}expanded, the form Qoder Desktop writes;trigger: always_onwhen unscoped. The CLI docs say it reads Desktop's rules~/.qoder/rules,~/.qoder-cn/rulesalwaysApply: falseandpaths:as a block list when scoped~/.codebuddy/rules.codebuddy/rules, CodeBuddy's format, one copy when both tools are enabled. Removing one tool keeps the copy while the other still uses it, as #945 does for its blocks~/.workbuddy/rules. WorkBuddy reads user rules and skills from one home,~/.workbuddyglobsunquoted and{a,b}expanded. It keeps the quotes and splits on every comma~/.joycode/rules.txt, no path scopingalwaysApply: truewhen unscoped;globs+ a generateddescriptionwhen scoped (it drops rules with neither); namespaced rules flat, since it reads one level. Its own rules, not teamai's extension, sopaths:keeps its scoping~/.omp/agent/rules.opencode/rules/**/*.md, so namespaced rules load, registered in.opencode/opencode.jsonas #945 does; the glob in the rootopencode.jsonis reclaimed. It applies every rule always~/.config/opencode/rules/*.mdand one per namespace directory. Today'srules/*.mdresolves from the session cwdSubagentStarthooks$CODEX_HOME/AGENTS.mdteamai hook-dispatch instructions(#952), added toevent.systemPromptfrombefore_agent_start. Pi rebuilds the prompt for each turn, so they do not pile up~/.pi/agent/AGENTS.md, which only Pi reads, beside #952's blocksSessionStarthook. Its CLI does not run project hooks~/.zcode/AGENTS.md--patch$DSH_HOME/AGENTS.mdSOUL.mdblock today, and a project with no rules erases it (rules.ts:454-459)$HERMES_HOME/SOUL.mdblock, written only by a user-scope pullAGENTS.mdAGENTS.md, resolved the way the hooks resolve it (profile,OPENCLAW_WORKSPACE_DIR)claude-internalandtclaudefollow Claude Code's layout, andcodex-internalandtcodexfollow Codex's. They were not checked.Known limits:
/hooks, and skips them silently otherwise. init/doctor say so.inclusion(Regression in 2.2.0: agents ignores inclusion: manual front matter on workspace steering files kirodotdev/Kiro#7950), so a scoped rule is always on there. The IDE once ignoredfileMatchin~/.kiro/steering(fileMatch inclusion mode does not work for global steering (~/.kiro/steering/) kirodotdev/Kiro#9176, Kiro 0.12). A maintainer reported fixes since, and the report closed without a retest.paths:scoping, so this limit stays; fix(pull): deliver each member's team instructions without the shared AGENTS.md (#945) #952's extension carries only the instruction blocks..hermes.mdhides the projectAGENTS.md, andpre_llm_calladds the text to every turn. A plugin prompt section holds at most 4,000 characters, within 8,000 shared by every plugin, and is dropped whole when over, sodoctorcould not vouch for it. fix(pull): deliver each member's team instructions without the shared AGENTS.md (#945) #952's Hermes plugin already spends one section on the instruction blocks..claude/rulesin a project, so with Claude enabled each rule reaches it twice. teamai still writes both copies, as it does for every tool that also reads another tool's files.Also in this change:
ctx.event(openclaw-hooks.ts:84), but OpenClaw passes an event withtypeandactionand noeventfield. It also subscribes tosession:start, which OpenClaw does not emit. The handler should key on${type}:${action}and subscribe to events OpenClaw emits (docs/automation/hooks/event-types.md).README, rules column
✓ Claude Code, Cursor, Copilot CLI, Kiro, Qoder, Qoder CN, CodeBuddy, WorkBuddy, JoyCode (new row), Oh My Pi, Hermes, OpenClaw
✓* Codex, Pi, ZCode, DeepSeek Harness, OpenCode
Codex, Pi and OpenCode change from ✓ to ✓*. DeepSeek Harness and ZCode change from
—to ✓*. Hermes changes from—to ✓, and OpenClaw keeps ✓: user scope is their normal rules channel, so both get full ticks. All 5README*.mdchange.Done when
SOUL.mdblock as the user-scope pull wrote it.~/.config/opencode/rulesand no projectrules/*.md..openclaw/rules,.pi/rules,~/.pi/agent/rules, a project's.workbuddy/rules,~/.joycode/rules) are reclaimed, unedited ones only, as fix(rules): give Codex the team rules: session hooks in a project, its own AGENTS.md in user scope #940 does for.codex/rules. Pi gets its rules through the extension and~/.pi/agent/AGENTS.md.~/.codebuddy/rulesinto~/.workbuddy/rules.rules.test.ts:1115-1120locks JoyCode to Cursor's quoted output and changes.teamai hook-dispatchon the events it maps.doctorchecks what each tool reads.Codex: fixed by #940 (#938). Instruction blocks: #945, implemented by #952, whose Pi extension,
~/.pi/agent/AGENTS.md, Hermes plugin, OpenCode.opencode/opencode.jsonand shared.codebuddy/rulesthis issue reuses.