teamai-cli 0.26.0 → 0.27.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -2
- package/README.ja.md +10 -7
- package/README.ko.md +10 -7
- package/README.md +10 -7
- package/README.th.md +10 -7
- package/README.zh-CN.md +10 -7
- package/agents/teamai-recall.md +9 -7
- package/dist/index.js +38718 -28148
- package/package.json +2 -1
- package/skill-data/core/SKILL.md +113 -1
- package/skill-data/core/references/commands.md +21 -10
- package/skill-data/core/references/contribute-member.md +23 -3
- package/skill-data/core/references/troubleshooting.md +165 -18
- package/skill-data/setup/SKILL.md +10 -6
- package/skill-data/setup/references/join-member.md +23 -10
- package/skill-data/setup/references/manage-admin.md +78 -7
- package/skill-data/setup/references/setup-admin.md +18 -5
- package/skill-data/setup/references/uninstall.md +64 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teamai-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0-beta.1",
|
|
4
4
|
"description": "TeamAI — Make Every Team AI Native (skill sync + shared knowledge base, powered by Git)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
"@types/node": "^20.17.0",
|
|
82
82
|
"@types/semver": "^7.8.0",
|
|
83
83
|
"@vitest/coverage-v8": "^3.2.7",
|
|
84
|
+
"esbuild": "^0.27.3",
|
|
84
85
|
"fast-check": "^4.10.2",
|
|
85
86
|
"opencode-ai": "1.18.23",
|
|
86
87
|
"oxlint": "1.85.0",
|
package/skill-data/core/SKILL.md
CHANGED
|
@@ -90,6 +90,16 @@ says so and why.)
|
|
|
90
90
|
session, use the name of **this** tool — do not assume Claude Code or Cursor.
|
|
91
91
|
Some hosts need extra manual steps for hooks — see the troubleshooting
|
|
92
92
|
reference ("Agent-specific caveats").
|
|
93
|
+
5. **Team secrets: the user types the value, you run the CLI.** When the team
|
|
94
|
+
declares secrets (the session-start context lists them; `teamai env list`
|
|
95
|
+
shows them), run the CLIs that use them through `teamai env exec -- <command>`,
|
|
96
|
+
`--` first, so they get this team's value. It is for CLIs, not for starting
|
|
97
|
+
an agent: a secret named like a model profile's (`ANTHROPIC_*`) overrides it.
|
|
98
|
+
When a secret is missing, ask the user to run `teamai env set KEY` in their
|
|
99
|
+
own terminal. Never ask for a value in chat, pass one to `--stdin` or
|
|
100
|
+
`--secret`, read the files under `~/.teamai/secrets/`, or print one
|
|
101
|
+
(`teamai env exec -- env` and `printenv` do). Declaring a secret with
|
|
102
|
+
`teamai env add KEY --secret` takes no value, so you can run it.
|
|
93
103
|
|
|
94
104
|
## Daily commands
|
|
95
105
|
|
|
@@ -100,6 +110,7 @@ teamai status # Show local vs team differences
|
|
|
100
110
|
teamai doctor # Diagnose configuration and hook problems
|
|
101
111
|
teamai list # List resources (skills|rules|docs|env|agents|hooks|mcp)
|
|
102
112
|
teamai recall <q> # Search what the team has already learned
|
|
113
|
+
teamai env exec -- <cmd> # Run a CLI with this directory's team env and secrets
|
|
103
114
|
```
|
|
104
115
|
|
|
105
116
|
Every other command, every flag, and the flags `--help` hides live in the
|
|
@@ -109,6 +120,107 @@ generated reference below. Read it instead of guessing a flag.
|
|
|
109
120
|
removing stale and local-only documents; an edited doc of a docs namespace you left
|
|
110
121
|
is kept and named. Use a dedicated directory; preview with `--dry-run`.
|
|
111
122
|
|
|
123
|
+
`teamai pull` keeps a skill, rule or agent copy the user changed since teamai
|
|
124
|
+
delivered it, `--force` included, and names it (`Kept <path>: ...`). To share
|
|
125
|
+
the change, `teamai push`; when pull says the version teamai would deploy has
|
|
126
|
+
changed since, or push says so for that copy, merge that change into the copy first, or the push replaces it. To take the team version instead, delete
|
|
127
|
+
the copy and run `teamai pull --force`. The first pull after upgrading, and a
|
|
128
|
+
new worktree's first pull, still overwrite: nothing is recorded yet.
|
|
129
|
+
|
|
130
|
+
In project scope, `init` and `pull` also install a git hook in the repository's
|
|
131
|
+
local git config (`hook.teamai-post-checkout`, `hook.teamai-post-merge`; Git
|
|
132
|
+
2.54+; older Git without `core.hooksPath` gets a marked block in `.git/hooks/`
|
|
133
|
+
scripts, and with it `teamai doctor` advises), beside any `core.hooksPath` manager or `.git/hooks` script. When a
|
|
134
|
+
worktree is created by `git worktree add` or an app that runs checkout hooks, it creates the project roots
|
|
135
|
+
of `enabledAgents` (else the ones the main checkout has) and pulls into it before
|
|
136
|
+
the command returns, from the team clone as last fetched when that was within
|
|
137
|
+
24 h; a full pull then runs in the background. A branch switch does nothing.
|
|
138
|
+
After `git pull` it fetches the team repo (5 s cap, then the background pull) and
|
|
139
|
+
delivers; in single-repo mode it delivers what `git pull` brought, offline. It prints nothing and always
|
|
140
|
+
exits 0; a failure inside it is recorded, and `teamai doctor` names it (`Last git
|
|
141
|
+
hook run failed: ...`) with its fix, as does the next interactive `teamai pull`, once.
|
|
142
|
+
`teamai doctor` also reports whether the hook is installed, and why not.
|
|
143
|
+
`pull --dry-run` says when it would install or update the hook, writing nothing;
|
|
144
|
+
`teamai uninstall` removes only teamai's hook entries and blocks. For hosts that
|
|
145
|
+
skip checkout hooks, prepare the worktree before launch; see the new-worktree
|
|
146
|
+
section in `references/troubleshooting.md`.
|
|
147
|
+
|
|
148
|
+
A team agent (`agents/<name>.yaml`) can set `model: strong`, `model: fast`, or an
|
|
149
|
+
alias the team defines, instead of one tool's model. The team maps each alias per
|
|
150
|
+
tool in `models/aliases.yaml`, in that tool's own model value, with an optional effort:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
aliases:
|
|
154
|
+
strong:
|
|
155
|
+
claude: { model: opus, effort: high }
|
|
156
|
+
codex: { model: gpt-6-sol, effort: high }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`teamai pull` writes the mapped model into each tool's agent file, with the effort
|
|
160
|
+
in that tool's own field: `effort` for the Claude family, CodeBuddy, Qoder and Qoder CN,
|
|
161
|
+
`model_reasoning_effort` for the Codex family, `variant` for OpenCode. Cursor takes
|
|
162
|
+
effort inside its model string (`claude-opus-5[effort=high]`); Copilot, Kiro, WorkBuddy,
|
|
163
|
+
JoyCode, ZCode and OMP take none, and pull warns and drops an effort mapped for them.
|
|
164
|
+
Qoder CN uses the `qoder` entry; only the Claude and Codex variants and Qoder CN inherit
|
|
165
|
+
an entry, so never expect a `claude` model in Qoder or ZCode. A tool the alias does
|
|
166
|
+
not map gets no `model` and uses its default; a concrete model such as `opus` is
|
|
167
|
+
written as is; `tool_extras.<tool>.model` pins one tool and skips the alias. Suggest
|
|
168
|
+
YAML agents: a legacy `agents/<name>.md` is copied as is, so its alias is not resolved.
|
|
169
|
+
Before a team adds its first alias, every member updates teamai: an older CLI writes
|
|
170
|
+
`model: strong` literally, and its push can replace the alias with a concrete model.
|
|
171
|
+
|
|
172
|
+
A member overrides an entry on their machine in `~/.teamai/models/aliases.yaml`
|
|
173
|
+
(same `aliases:` shape). For one tool it replaces the team's whole entry, effort
|
|
174
|
+
included, and `~` or `default` gives that tool no model and no effort. Order per
|
|
175
|
+
tool: extras model, local entry, team entry, no model. Keys must be `strong`, `fast`
|
|
176
|
+
or a team alias; other names do nothing. One file serves every scope and every team
|
|
177
|
+
with that alias name. An ordinary `teamai pull` applies an edit. In the team file,
|
|
178
|
+
`default` is a literal model value and `~` is an error.
|
|
179
|
+
|
|
180
|
+
A role or project redefines an alias in `models/<ns>/aliases.yaml`, read where `<ns>`
|
|
181
|
+
is in `resources.models`, like `models/<ns>/models.yaml`. The namespace alias replaces
|
|
182
|
+
the root alias whole (a tool it does not map gets no `model`); the same alias in two
|
|
183
|
+
active namespaces holds alias agents, as a structural error does. A name defined in any
|
|
184
|
+
aliases file of the team repo, active or not, is an alias: with no active definition it
|
|
185
|
+
gives no `model`, and pull warns once per such alias. `teamai doctor` notes an agent's
|
|
186
|
+
alias defined in an inactive namespace; to use it, add `models: [<ns>]` to the role's or
|
|
187
|
+
project's resources, or rename the alias if it was meant as a concrete model id.
|
|
188
|
+
|
|
189
|
+
A structural error in any aliases file, active or not (bad YAML, a wrong type, a bad alias
|
|
190
|
+
name, an effort without a model, `~` in a team file, keys but no top-level `aliases:`)
|
|
191
|
+
holds every agent with a `model`; one
|
|
192
|
+
in the local file holds only agents whose `model` is an alias. Pull keeps
|
|
193
|
+
their copies and push skips them until the file its warning names is fixed; then an
|
|
194
|
+
ordinary `teamai pull` delivers them. An unknown
|
|
195
|
+
tool key, an unknown option field, or an alias named like `opus` or `inherit` is only
|
|
196
|
+
dropped, with a warning when an agent uses that alias; `gateways` is ignored.
|
|
197
|
+
|
|
198
|
+
On a tool switched with `teamai models switch`, alias agents get no effort (not even a
|
|
199
|
+
`tool_extras.<tool>` one, unless the extras also pin a `model`), and
|
|
200
|
+
Claude keeps only `opus`, `sonnet` or `haiku` (the switch routes those to the gateway)
|
|
201
|
+
while Codex, OpenCode, CodeBuddy and WorkBuddy get no `model`. No `model` means the
|
|
202
|
+
tool's native inheritance (for Codex, `[agents].default_subagent_model` or the parent's
|
|
203
|
+
model), not the profile's model. Variants such as tclaude are never switched. An ordinary
|
|
204
|
+
`teamai pull` after `models switch` or `models restore` rewrites the affected agents.
|
|
205
|
+
|
|
206
|
+
On push, an alias agent's model and alias effort are never read as edits: a copy that
|
|
207
|
+
matches the last pull or the current mapping is unedited, and a hand-edited model or
|
|
208
|
+
effort is reported as drift and not pushed (other edits still push), with where to change
|
|
209
|
+
it: the member's override file, the team aliases file the alias comes from, or `teamai models
|
|
210
|
+
restore --agent <tool>` for a switched tool. Writing an alias name in a deployed copy (`model: fast`)
|
|
211
|
+
and pushing proposes `model: <alias>`, except in a tool whose `tool_extras.<tool>.model` pins it,
|
|
212
|
+
where a changed value is drift on that pin. Never tell a user to push a concrete model over an alias.
|
|
213
|
+
|
|
214
|
+
To answer "why does this tool run this model", run `teamai doctor`. Each alias agent gets
|
|
215
|
+
a note with one line per tool: the model and effort it receives, then `[step: source]`.
|
|
216
|
+
`extras` = `tool_extras.<tool>.model`; `switched` = the tool runs a model profile;
|
|
217
|
+
`local` = the member's override (`tool default (chosen in <path>)` is their `~`/`default`);
|
|
218
|
+
`team` = the team file named; `default` = no model field (alias unmapped for that tool, or
|
|
219
|
+
no active file defines it). A Codex line with no effort means the session's effort carries
|
|
220
|
+
over. A line naming what "the last pull deployed" is fixed by an ordinary `teamai pull`.
|
|
221
|
+
The failing check `Agent model aliases can be resolved` names why agents are held (broken
|
|
222
|
+
aliases file, namespace conflict, unreadable switched-tool settings) and which file to fix.
|
|
223
|
+
|
|
112
224
|
## References
|
|
113
225
|
|
|
114
226
|
In the files below, `{SKILL_DIR}` is the directory `teamai skill path core` prints; a reference file you open on its own writes that directory as `SKILL_DIR` in braces.
|
|
@@ -116,7 +228,7 @@ In the files below, `{SKILL_DIR}` is the directory `teamai skill path core` prin
|
|
|
116
228
|
| File | When to load it |
|
|
117
229
|
|---|---|
|
|
118
230
|
| `{SKILL_DIR}/references/commands.md` | Before using any command not in the daily list, or any flag. Generated from the CLI's own command table, so it cannot drift. |
|
|
119
|
-
| `{SKILL_DIR}/references/troubleshooting.md` | A command fails, a hook does not fire,
|
|
231
|
+
| `{SKILL_DIR}/references/troubleshooting.md` | A command fails, a hook does not fire, a host needs manual steps, or a recalled doc got no upvote. |
|
|
120
232
|
| `{SKILL_DIR}/references/contribute-member.md` | A member wants to publish a skill, rule or doc they already have. Any member can, not just admins. |
|
|
121
233
|
|
|
122
234
|
`teamai skill get core --full` prints this skill with all three references
|
|
@@ -12,7 +12,7 @@ Generated: do not edit by hand. Regenerate with
|
|
|
12
12
|
## Global options
|
|
13
13
|
|
|
14
14
|
- `-V, --version` — output the version number
|
|
15
|
-
- `--dry-run` — Preview mode, no changes made
|
|
15
|
+
- `--dry-run` — Preview mode, no changes made; a command with no preview exits 1 without running
|
|
16
16
|
- `-v, --verbose` — Verbose output
|
|
17
17
|
|
|
18
18
|
## init
|
|
@@ -28,7 +28,7 @@ Generated: do not edit by hand. Regenerate with
|
|
|
28
28
|
- `--no-inherit-user-scope` — Disable user-scope inheritance for this project
|
|
29
29
|
- `--role <id>` — Primary role ID (e.g. hai_dev) for non-interactive setup
|
|
30
30
|
- `--project <ids>` — Active logical project(s) from manifest/projects.yaml (comma-separated); scopes which project resources and learnings this directory syncs. Pass "all" to activate every project the manifest declares (a snapshot taken now)
|
|
31
|
-
- `--agent <name>` — AI tools to set up (e.g. claude, codex, cursor, codebuddy, workbuddy, dsh). Repeatable or comma-separated. In single-repo mode, selects which tool dirs to create;
|
|
31
|
+
- `--agent <name>` — AI tools to set up (e.g. claude, codex, cursor, codebuddy, workbuddy, dsh). Repeatable or comma-separated. In single-repo mode, selects which tool dirs to create; a custom agent defined only in teamai.yaml's toolPaths also gets its root created here (git-backed init only — an HTTP init has no local teamai.yaml to read custom paths from). Omit for an interactive picker. Additive on repeated runs.
|
|
32
32
|
- `--force` — Overwrite existing config without confirmation
|
|
33
33
|
|
|
34
34
|
## push
|
|
@@ -193,13 +193,23 @@ Generated: do not edit by hand. Regenerate with
|
|
|
193
193
|
- `--reveal` — Show env variable values in plaintext (default: masked)
|
|
194
194
|
- `teamai env list` — List team environment variables
|
|
195
195
|
- `--reveal` — Show env variable values in plaintext (default: masked)
|
|
196
|
-
- `teamai env add <key>
|
|
197
|
-
- `-d, --description <desc>` — Description for the variable
|
|
198
|
-
- `--
|
|
196
|
+
- `teamai env add <key> [value]` — Add or update a team environment variable, or declare a secret with --secret
|
|
197
|
+
- `-d, --description <desc>` — Description for the variable or secret
|
|
198
|
+
- `--secret` — Declare a secret in env/secrets.yaml: no value, each member sets their own
|
|
199
|
+
- `--url <url>` — Where a member gets a value for the secret (with --secret)
|
|
200
|
+
- `--role <ns>` — Write to env/<ns>/ instead of env/ (env.yaml, or secrets.yaml with --secret)
|
|
199
201
|
- `--project <id>` — Write to the project's env namespace (resources.env in manifest/projects.yaml)
|
|
200
|
-
- `teamai env remove <key>` — Remove a team environment variable
|
|
201
|
-
- `--
|
|
202
|
+
- `teamai env remove <key>` — Remove a team environment variable or declared secret
|
|
203
|
+
- `--secret` — Remove the declared secret only (env/secrets.yaml), for a key env.yaml also sets
|
|
204
|
+
- `--role <ns>` — Remove from env/<ns>/ instead of env/
|
|
202
205
|
- `--project <id>` — Remove from the project's env namespace (resources.env in manifest/projects.yaml)
|
|
206
|
+
- `teamai env set <key>` — Set your value for a secret the team declares, or an env variable it sets, for this directory's team, on this machine (prompts without echo)
|
|
207
|
+
- `--stdin` — Read the value from piped stdin
|
|
208
|
+
- `--from-env <var>` — Read the value from this environment variable each time it is used; no copy is stored
|
|
209
|
+
- `--global` — Set a secret for every team on this machine; a value set for a team still wins
|
|
210
|
+
- `teamai env unset <key>` — Remove your value for a secret or env variable, for this directory's team, from this machine
|
|
211
|
+
- `--global` — Remove the value set for every team on this machine instead
|
|
212
|
+
- `teamai env exec <command...>` — Run a command with this directory's team env variables and secrets (put -- before the command)
|
|
203
213
|
|
|
204
214
|
## hooks
|
|
205
215
|
|
|
@@ -243,7 +253,7 @@ Generated: do not edit by hand. Regenerate with
|
|
|
243
253
|
- `--base-url <url>` — Personal profiles: new gateway root URL
|
|
244
254
|
- `--protocol <protocols>` — Personal profiles: serve models over these protocols too
|
|
245
255
|
- `--model <ids>` — Personal profiles: add model IDs
|
|
246
|
-
- `teamai models switch
|
|
256
|
+
- `teamai models switch [profile]` — Point agents at a model profile (every compatible agent by default); omit the profile to pick one
|
|
247
257
|
- `--agent <name>` — Only switch this agent. Repeatable or comma-separated.
|
|
248
258
|
- `--model <id>` — Default model to select (defaults to the first in the profile)
|
|
249
259
|
- `--dry-run` — Show what would change without writing
|
|
@@ -296,6 +306,7 @@ Generated: do not edit by hand. Regenerate with
|
|
|
296
306
|
- `teamai recall [query...]` — Search team learnings knowledge base
|
|
297
307
|
- `--depth <level>` — Recall depth: route (entry-points only) | context (module-level, default) | lookup (full graph traversal)
|
|
298
308
|
- `--check` — Relevance precheck only: print RELEVANT/NOT_RELEVANT + top score; no file reads, no upvote
|
|
309
|
+
- `--caller <name>` (hidden) — Internal, set by the teamai-recall subagent to mark its own runs; do not pass it yourself
|
|
299
310
|
- `teamai recall disable` — Disable automatic knowledge-base recall
|
|
300
311
|
- `teamai recall enable` — Enable automatic knowledge-base recall
|
|
301
312
|
- `teamai recall status` — Show recall feature status
|
|
@@ -363,13 +374,13 @@ Generated: do not edit by hand. Regenerate with
|
|
|
363
374
|
|
|
364
375
|
## review
|
|
365
376
|
|
|
366
|
-
- `teamai review [id]` — Inspect and process .teamai/pending-review.jsonl items
|
|
377
|
+
- `teamai review [id]` — Inspect and process .teamai/pending-review.jsonl items; --dry-run validates apply decisions and previews rejections without writing documents or removing pending items
|
|
367
378
|
- `--apply` — Apply the change for the given id (only for codebase-section)
|
|
368
379
|
- `--reject` — Reject the given id without applying
|
|
369
380
|
- `--reason <msg>` — Reason for reject
|
|
370
381
|
- `--all-apply` — Apply all items at or below --max-risk
|
|
371
382
|
- `--max-risk <level>` — Risk ceiling for --all-apply: high|medium|low (default medium)
|
|
372
|
-
- `--json` — Machine-readable output
|
|
383
|
+
- `--json` — Machine-readable output (dry-run decisions include dryRun: true; ok reports validation only)
|
|
373
384
|
|
|
374
385
|
## ci
|
|
375
386
|
|
|
@@ -117,12 +117,32 @@ The doc lands in the team's `learnings/` and appears for teammates on their next
|
|
|
117
117
|
- Teammates receive it automatically on their next session, or via `teamai pull`.
|
|
118
118
|
|
|
119
119
|
Before listing rules, `push` refreshes copies whose bodies still match a recorded
|
|
120
|
-
sync revision.
|
|
121
|
-
|
|
122
|
-
`
|
|
120
|
+
sync revision. The header teamai generates for a tool's own rules format
|
|
121
|
+
(Cursor `.mdc`, JoyCode's own `.mdc`, Copilot `applyTo`, Kiro `inclusion`, Qoder
|
|
122
|
+
`trigger`, CodeBuddy and WorkBuddy `alwaysApply`, Oh My Pi `alwaysApply`/`globs`) does not count as a local edit: unedited old copies update in that
|
|
123
|
+
format, including under `COPILOT_HOME` in user scope. Genuine local body edits remain push candidates.
|
|
123
124
|
Rule pre-sync leaves tools excluded by `enabledAgents` or `disabledAgents` untouched.
|
|
124
125
|
When only team `paths` change, `applyTo` refreshes if the local file still matches
|
|
125
126
|
a recorded version's generated copy; locally edited headers are kept.
|
|
127
|
+
The copies push refreshes are recorded, so a later `teamai pull` still updates them.
|
|
128
|
+
Oh My Pi and Kiro read only the top of their rules directories, so a namespaced
|
|
129
|
+
rule is written flat there (`rules/fe/style.md` as `fe.style.md`); an edit of that file
|
|
130
|
+
pushes back to `rules/fe/style.md`. Push requires a delivery record for the flat copy.
|
|
131
|
+
A personal file with that name is neither refreshed before push nor offered as
|
|
132
|
+
an edit of the team rule.
|
|
133
|
+
If two namespaced rules flatten to the same name, neither is written; `teamai doctor`
|
|
134
|
+
reports the collision even when no other rule reaches that tool. Rename one in the
|
|
135
|
+
team repo, then run `teamai pull`. Doctor also reports team-owned OpenCode globs
|
|
136
|
+
or inline blocks left after the last rule is removed.
|
|
137
|
+
|
|
138
|
+
A new file in the rules directory of a tool with a rules format of its own
|
|
139
|
+
(Cursor, JoyCode, Copilot, Kiro, Qoder, CodeBuddy, WorkBuddy, Oh My Pi) is the
|
|
140
|
+
member's own rule in that tool's format: push never offers it, and pull leaves
|
|
141
|
+
it. To author a new team rule, write it as a plain `.md` in `.claude/rules/`
|
|
142
|
+
(scope it with `paths:` frontmatter, which teamai renders into each tool's
|
|
143
|
+
format), then run `teamai push`. A YAML comment after an unquoted glob stays
|
|
144
|
+
outside its scope: `paths: **/*.ts # TypeScript files` matches `**/*.ts`, including
|
|
145
|
+
when written as a block-list entry under `paths:`.
|
|
126
146
|
|
|
127
147
|
## If push is denied
|
|
128
148
|
|
|
@@ -16,8 +16,11 @@ reports before anything else.
|
|
|
16
16
|
|
|
17
17
|
This is the #1 onboarding issue. In order:
|
|
18
18
|
|
|
19
|
-
1. **
|
|
20
|
-
|
|
19
|
+
1. **Did init pick this tool?** `teamai init` ends with a pull, but a project-scope
|
|
20
|
+
init creates only the directories of tools named with `--agent` or picked in
|
|
21
|
+
its interactive tool picker. Run without a terminal and without `--agent`, it
|
|
22
|
+
creates none, and a tool's project directory appears when that tool opens a session there. Re-run
|
|
23
|
+
`teamai init <repo> --agent <tool>` to add the tool and fill it now.
|
|
21
24
|
2. **Sync manually to confirm:**
|
|
22
25
|
```bash
|
|
23
26
|
teamai pull
|
|
@@ -28,15 +31,30 @@ This is the #1 onboarding issue. In order:
|
|
|
28
31
|
```bash
|
|
29
32
|
teamai hooks inject
|
|
30
33
|
```
|
|
31
|
-
4. **Wrong scope?** Project-scope hooks are written to your HOME tool
|
|
32
|
-
(e.g. `~/.claude/settings.json`), not the project folder
|
|
34
|
+
4. **Wrong scope?** Project-scope built-in hooks are written to your HOME tool
|
|
35
|
+
settings (e.g. `~/.claude/settings.json`), not the project folder; the team's own
|
|
36
|
+
hooks for Claude Code and Codex go to the main checkout
|
|
37
|
+
(`.claude/settings.local.json`, `.codex/hooks.json`). That is intentional.
|
|
38
|
+
Existing Claude/Codex main-checkout hook files count as installed targets
|
|
39
|
+
even when HOME and current worktree tool roots are missing. Injection and
|
|
40
|
+
pull update team hooks and restore HOME built-ins; removal clears managed
|
|
41
|
+
main-checkout hooks without recreating HOME roots.
|
|
42
|
+
If Git-hook installation fails after writing agent hooks, `hooks inject`,
|
|
43
|
+
`init` and self-repo bootstrap still attempt Codex trust. Injection preserves
|
|
44
|
+
the installation error without reporting overall success. Init reports the
|
|
45
|
+
error and retains exit code 1 while completing local setup, including HTTP
|
|
46
|
+
initialization. Bootstrap records the error in the debug log and continues
|
|
47
|
+
local setup.
|
|
48
|
+
In project scope, `teamai hooks remove` preserves other projects' gated team
|
|
49
|
+
hooks in HOME, while removing the shared built-in hooks.
|
|
33
50
|
If you initialized project scope but expected machine-wide resources, re-run
|
|
34
51
|
with `--scope user`.
|
|
35
52
|
5. **Tool has no hook surface** (e.g. Gemini CLI, JoyCode): there is no auto-sync;
|
|
36
53
|
run `teamai pull` manually each time.
|
|
37
|
-
6. **Claude Code reads a different directory** (`CLAUDE_CONFIG_DIR`
|
|
38
|
-
`teamai doctor` reports `Claude Code root matches
|
|
39
|
-
|
|
54
|
+
6. **Claude Code or Codex reads a different directory** (`CLAUDE_CONFIG_DIR` or
|
|
55
|
+
`CODEX_HOME` is set). `teamai doctor` reports `Claude Code root matches
|
|
56
|
+
CLAUDE_CONFIG_DIR` / `Codex root matches CODEX_HOME` when the directory the
|
|
57
|
+
variable names is not the one this config syncs to. Re-run
|
|
40
58
|
`teamai init` from a shell that has the variable exported; it records the root
|
|
41
59
|
and moves the install. If the check says the value cannot be synced to (outside
|
|
42
60
|
your home, or nested deeper than `~/.config/<name>`), fix the variable first.
|
|
@@ -64,6 +82,66 @@ This is the #1 onboarding issue. In order:
|
|
|
64
82
|
`recall` refuses the same way with `Nothing was searched: <file>: <reason>`:
|
|
65
83
|
no team knowledge was searched, so do not report that the team has none.
|
|
66
84
|
|
|
85
|
+
## "Last git hook run failed: ..." / a new worktree lacks team resources
|
|
86
|
+
|
|
87
|
+
In project scope, teamai's git hook syncs on `git worktree add` and `git pull`
|
|
88
|
+
silently and always exits 0, so its failures surface only here: `teamai doctor`
|
|
89
|
+
names the last one with its fix, and the next interactive `teamai pull` says it
|
|
90
|
+
once. The causes are a team repo fetch that failed or hit the 5 s post-merge
|
|
91
|
+
cap without the background pull finishing it, and another teamai process
|
|
92
|
+
holding the project's sync lock longer than the hook waits, or incomplete resource,
|
|
93
|
+
hook or MCP delivery. Only a complete startup sync clears the recorded failure.
|
|
94
|
+
Run `teamai pull`
|
|
95
|
+
in the checkout (after a stuck pull ends, or once the team repo is reachable);
|
|
96
|
+
`~/.teamai/debug.log` has the details. If doctor reports `Git hook syncs new
|
|
97
|
+
worktrees and git pull` as failing, follow its fix: `teamai pull` installs it.
|
|
98
|
+
Git older than 2.54 has no config hooks: teamai then adds a marked block to
|
|
99
|
+
`.git/hooks/post-checkout` and `post-merge`, unless `core.hooksPath` is set (or a
|
|
100
|
+
hook there is a symlink or not an executable shell script), in which case doctor's fix says to upgrade Git
|
|
101
|
+
or, if the team agrees, to commit its guarded `command -v teamai ... || true`
|
|
102
|
+
line into the manager's post-checkout and post-merge hooks.
|
|
103
|
+
Existing hook contents and permissions stay unchanged; read/write errors propagate
|
|
104
|
+
from `init` and `hooks inject`, and Git-started pulls record them. An unreadable
|
|
105
|
+
project config prevents sync and keeps its reason in `~/.teamai/debug.log`.
|
|
106
|
+
|
|
107
|
+
Hosts that skip checkout hooks need `teamai pull` in the new checkout before the AI
|
|
108
|
+
tool starts. For Codex CLI 0.160.0, use `git worktree add`, run `teamai pull` there, then
|
|
109
|
+
launch `codex exec -C <worktree>`. Its native `codex exec --worktree` path creates
|
|
110
|
+
the checkout without `post-checkout`, so SessionStart sync arrives after startup
|
|
111
|
+
discovery.
|
|
112
|
+
|
|
113
|
+
## "KEY is not set. Run `teamai env set KEY`"
|
|
114
|
+
|
|
115
|
+
`pull`, `teamai mcp list`, `teamai env list`, `teamai doctor` and
|
|
116
|
+
`teamai env exec` (on stderr) print this for a secret the team declares in
|
|
117
|
+
`env/secrets.yaml` that has no value on this machine, naming the MCP servers
|
|
118
|
+
that need it and where to get one. It is a note, not a failure: `doctor` exits
|
|
119
|
+
as it would without it. The value is the user's: ask them to run
|
|
120
|
+
`teamai env set KEY` in their own terminal (it prompts without echo), then
|
|
121
|
+
`teamai pull` to update the MCP servers; a CLI run through `teamai env exec`
|
|
122
|
+
gets it on its next run. Never ask for the value in chat or pipe one to
|
|
123
|
+
`teamai env set --stdin`. A note that an entry "may hold an old" value means an earlier pull wrote
|
|
124
|
+
it and it stays until a pull finds the value.
|
|
125
|
+
|
|
126
|
+
`KEY reads VAR, which is not set` means the user's value for KEY is a
|
|
127
|
+
reference to VAR (`--from-env`) and VAR is unset in this environment. Ask the
|
|
128
|
+
user whether to set VAR in their shell or replace the reference with the
|
|
129
|
+
command in the line; do not choose for them.
|
|
130
|
+
|
|
131
|
+
## "Did not write <tool>'s MCP servers to <file>" / `withheld:`
|
|
132
|
+
|
|
133
|
+
`pull` prints this, and `teamai mcp list` (`withheld:`) and `teamai doctor`
|
|
134
|
+
report it, when a project MCP config would get a resolved `${VAR}` value that
|
|
135
|
+
git would commit: the file could not be kept out of git first. It is left as
|
|
136
|
+
it was, and an entry an earlier pull wrote stays. The line names the reason and the
|
|
137
|
+
fix. For `git already tracks <file>`, tell the user: `git rm --cached <file>`
|
|
138
|
+
(the file stays on disk), commit that, and rotate the token if the file was
|
|
139
|
+
ever committed with it; then `teamai pull`. Do not run `git rm` or commit for
|
|
140
|
+
them. For an exclude file that is not writable, one another teamai command
|
|
141
|
+
held, or a git error, relay the fix the line gives.
|
|
142
|
+
|
|
143
|
+
For new HTTP local-agent MCP installs, a failed initial ownership-manifest write leaves the MCP config and Git exclusions unchanged. Retry the install after fixing the manifest write error. A bare Copilot entry beside `mcpServers` is removed only with a matching ownership record proving a completed bare write. Older records without that evidence preserve the bare entry. A bare ownership record cannot claim a same-named member entry under `mcpServers`: updates skip the collision, and removal leaves that keyed entry alone. An unmarked Copilot record needs a matching keyed hash that does not also match the bare entry. Completed writes record `bare: true` or `bare: false`; missing placement remains unproven, including after a failed placement-record write. Existing JSON MCP updates keep the old ownership until the config write completes; a later manifest failure restores the config. `uninstall_mcp` keeps ownership if reading or writing the config fails, and restores the entry if removing its manifest record fails. MCP reconcile also restores all configs written before an ownership-save failure. If restoration fails too, repair the named configs and ownership records before retrying; the error reports both failures, and configs still carrying credentials stay excluded from Git.
|
|
144
|
+
|
|
67
145
|
## Permission / access denied
|
|
68
146
|
|
|
69
147
|
`init`, `pull`, or `push` failing with a permission error usually means the user
|
|
@@ -109,9 +187,10 @@ broken machine):
|
|
|
109
187
|
| Tool | Hooks status | Why |
|
|
110
188
|
|-----------------------|---------------------------|---------------------------------------------------------------------|
|
|
111
189
|
| Claude Code (`claude`)| Installed | Fully supported — this is the main, working path |
|
|
112
|
-
| Codex |
|
|
113
|
-
| Cursor |
|
|
114
|
-
|
|
|
190
|
+
| Codex | Installed and trusted | Codex runs only trusted hooks; teamai trusts the ones it writes through `codex app-server`, and `teamai doctor` names any Codex will not run |
|
|
191
|
+
| Cursor | Installed | Also runs `~/.claude/settings.json`. That copy exits only when `~/.cursor/hooks.json` or the project `.cursor/hooks.json` contains `--tool cursor` |
|
|
192
|
+
| Copilot CLI | Installed in self mode | Also runs a trusted project's `.claude/settings.json`. That copy exits only when `.github/hooks/teamai.json` contains `--tool copilot`. `COPILOT_CLI` alone does not skip |
|
|
193
|
+
| CodeBuddy / WorkBuddy | Installed | Claude-format hooks in their own `settings.json` |
|
|
115
194
|
|
|
116
195
|
Practical rule: if you set up with `--agent claude`, expect **only** Claude to show
|
|
117
196
|
hooks installed. A tool you are not using, or one that is not a supported hook
|
|
@@ -127,17 +206,31 @@ step — do not assume auto-sync just works.
|
|
|
127
206
|
|
|
128
207
|
### Codex
|
|
129
208
|
|
|
130
|
-
Codex
|
|
131
|
-
`teamai hooks inject`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`teamai pull`
|
|
209
|
+
Codex runs a non-managed hook only once it is **trusted**. `teamai init`, `pull`
|
|
210
|
+
and `teamai hooks inject` trust the hooks they write (and, in a project, the main
|
|
211
|
+
checkout, or the current worktree for a bare repository) through `codex app-server`.
|
|
212
|
+
Trust written by a session-start pull applies from the next Codex session. `teamai doctor` names any teamai hook Codex will not
|
|
213
|
+
run. Then: run `teamai pull`; if `codex` is not on PATH or `codexTrustEnabled: false`
|
|
214
|
+
is set in `config.yaml`, guide the user to trust the teamai hooks in Codex `/hooks`,
|
|
215
|
+
then reopen a session. A new linked worktree gets the team hooks from its second
|
|
216
|
+
Codex session (the first creates its `.codex/`). Member hooks with the same command
|
|
217
|
+
are preserved and remain untouched by automatic trust. Codex ownership uses the
|
|
218
|
+
recorded event, position and complete entry. A moved entry is recovered only by a
|
|
219
|
+
unique full-definition match. Legacy records recover only a unique event, matcher
|
|
220
|
+
and command match; `timeout` and `additionalContextLimit` were not recorded.
|
|
221
|
+
Pre-#370 project Codex ownership is imported from the main checkout's
|
|
222
|
+
`.teamai/managed-hooks.json` before reconciliation or direct removal.
|
|
223
|
+
Unrecorded or ambiguous legacy team-hook copies are preserved. Project hook paths follow `toolPaths`;
|
|
224
|
+
Claude uses `settings.local.json` beside its configured settings file. A custom
|
|
225
|
+
Codex path that Codex does not load is reported as `not loaded` by doctor.
|
|
135
226
|
|
|
136
227
|
### Cursor
|
|
137
228
|
|
|
138
|
-
Cursor
|
|
139
|
-
|
|
140
|
-
|
|
229
|
+
Cursor writes hooks to `~/.cursor/hooks.json` and also runs `~/.claude/settings.json`. `hook-dispatch --tool claude` and team hook commands written for `claude` exit only when `CURSOR_VERSION` is set and `~/.cursor/hooks.json` or `$CURSOR_PROJECT_DIR/.cursor/hooks.json` contains `--tool cursor`. A setup with only Claude has no second copy, so those hooks still run inside Cursor. Claude Code does not set `CURSOR_VERSION`. An already installed team hook picks up the guard on the next `teamai pull` or `teamai hooks inject`. If `teamai hooks list` shows Cursor without hooks, run `teamai pull` at the start of the session.
|
|
230
|
+
|
|
231
|
+
### Copilot CLI
|
|
232
|
+
|
|
233
|
+
In self mode, teamai writes hooks into the project, and Copilot CLI runs a trusted project's `.claude/settings.json` as well as its own `.github/hooks/teamai.json`. `hook-dispatch --tool claude` and team hook commands written for `claude` exit only when `COPILOT_PROJECT_DIR` is set and that file contains `--tool copilot`. `COPILOT_CLI` is not a signal: Copilot sets it on every subprocess, including a Claude session started from its shell. Copilot does not run `~/.claude/settings.json`, so this duplicate does not happen outside self mode. Re-run `teamai pull` or `teamai hooks inject` so an already installed team hook picks up the guard.
|
|
141
234
|
|
|
142
235
|
### ChatGPT App
|
|
143
236
|
|
|
@@ -161,9 +254,63 @@ Gemini CLI, JoyCode, and similar tools have no TeamAI-writable hook surface —
|
|
|
161
254
|
there is no auto-sync. Tell the user to run `teamai pull` manually at the start of
|
|
162
255
|
each session.
|
|
163
256
|
|
|
257
|
+
## "A recalled doc got no upvote"
|
|
258
|
+
|
|
259
|
+
A recalled doc is upvoted once per session when the session that ran the recall
|
|
260
|
+
opens it within 24 hours: a file read, a reader command (`cat`, `sed -n`, …), or
|
|
261
|
+
a search whose output shows its lines. Listing the doc does not count, and
|
|
262
|
+
neither does working from the recall subagent's summary alone; only the opt-in
|
|
263
|
+
judge (`TEAMAI_UPVOTE_JUDGE=1`) credits that. `teamai stats` shows each recent
|
|
264
|
+
session's runs, recalled docs and adopted docs. Per agent:
|
|
265
|
+
|
|
266
|
+
- **Claude Code, Codex (0.134+), CodeBuddy (2.103.1+), WorkBuddy, Qoder,
|
|
267
|
+
OpenCode, OMP**: both a recall the main agent runs and one the
|
|
268
|
+
`teamai-recall` subagent runs are credited when the main agent opens the doc.
|
|
269
|
+
On OMP the subagent's recall needs the main session's file on disk, so a
|
|
270
|
+
`--no-session` run credits only the main agent's own recalls.
|
|
271
|
+
- **Cursor, Copilot CLI, ZCode, Pi**: only a recall the main agent runs
|
|
272
|
+
itself. A subagent's recall is not linked to the main session, and Pi has no
|
|
273
|
+
TeamAI subagent.
|
|
274
|
+
- **OpenClaw, Hermes, Kiro, JoyCode**: no PostToolUse hook, so recalls never
|
|
275
|
+
vote.
|
|
276
|
+
|
|
277
|
+
A read after the session's last Stop is credited at SubagentStop, at Copilot CLI's
|
|
278
|
+
SessionEnd, or at the next `teamai pull`.
|
|
279
|
+
|
|
164
280
|
## Still stuck
|
|
165
281
|
|
|
166
282
|
- Re-run the failing command with `-v` / `--verbose` for detail.
|
|
167
283
|
- `teamai status` shows exactly how local differs from the team repo.
|
|
168
284
|
- Report unexpected behavior at https://github.com/Tencent/teamai-cli/issues
|
|
169
285
|
with the agent name, platform, and the step that failed.
|
|
286
|
+
|
|
287
|
+
## "Pull left an instruction file unchanged"
|
|
288
|
+
|
|
289
|
+
If pull reports incomplete TeamAI markers, it keeps the entire file unchanged.
|
|
290
|
+
Fix the named block so it has exactly one start marker followed by one end
|
|
291
|
+
marker, then run `teamai pull` again. Other files can still sync successfully.
|
|
292
|
+
|
|
293
|
+
Pull keeps retired instruction blocks until every installed tool that wrote the
|
|
294
|
+
file has a working replacement. Repair the named target, extension or plugin
|
|
295
|
+
and run `teamai pull` again. Excluded tools' current and retired files stay
|
|
296
|
+
unchanged and are excluded from doctor's stale-instruction check.
|
|
297
|
+
When a native project file retains a TeamAI block, the session hook skips that
|
|
298
|
+
block, including cached HTTP prompts, until cleanup succeeds. Other blocks
|
|
299
|
+
still reach the hook. Doctor reports malformed markers in retired files;
|
|
300
|
+
repair them before retrying pull.
|
|
301
|
+
If a block's source cannot be resolved, its old block stays even when other
|
|
302
|
+
blocks sync. Repair the source and pull again to complete its migration.
|
|
303
|
+
HTTP prompt commands verify earlier deliveries against the current prompt
|
|
304
|
+
before cleaning shared instructions. Older destination contents do not count;
|
|
305
|
+
culture and recall stay because HTTP prompt commands do not replace them.
|
|
306
|
+
An HTTP prompt sync that cannot clean retired blocks reports a failed ACK and
|
|
307
|
+
keeps its previous cache and manifest for the server's retry.
|
|
308
|
+
OpenClaw HTTP prompts require an existing resolved user workspace, but not an
|
|
309
|
+
existing `AGENTS.md`: the prompt sync creates that file and preserves personal
|
|
310
|
+
text already in it.
|
|
311
|
+
|
|
312
|
+
OpenCode registration saves ownership before activating a new config entry.
|
|
313
|
+
If the state write fails, repair the state directory's permissions and retry
|
|
314
|
+
`teamai pull`; the entry is not activated without its removal ownership.
|
|
315
|
+
If the config write fails, ownership stays available for retry. Entries the
|
|
316
|
+
member already listed are never claimed.
|
|
@@ -46,13 +46,17 @@ and create-repo URLs, and the per-provider caveats, and points at
|
|
|
46
46
|
install. Let `teamai init` set up every AI tool already installed (omitting
|
|
47
47
|
`--agent` gives an interactive picker; select all detected tools). **After init,
|
|
48
48
|
report which agents were set up** — in the user's language, which tools now
|
|
49
|
-
auto-start TeamAI,
|
|
50
|
-
|
|
49
|
+
auto-start TeamAI, which detected tools were skipped and why (e.g. CodeBuddy
|
|
50
|
+
design), and any installed hooks that still need trust (e.g. Codex with
|
|
51
|
+
automatic trust disabled or unavailable). Verify the real per-tool result with
|
|
51
52
|
`teamai doctor` and `teamai hooks list`.
|
|
52
|
-
3.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
3. **`teamai init` ends with a pull.** In user scope, and in project scope for each
|
|
54
|
+
tool named with `--agent` (or picked in init's tool picker when a person runs it
|
|
55
|
+
in a terminal), the team's skills, rules and MCP servers are in place when init
|
|
56
|
+
exits; there is no need to run `teamai pull` after it. Run from an agent shell
|
|
57
|
+
(no terminal), a project-scope init without `--agent` creates no tool directory: a tool's directory appears and
|
|
58
|
+
fills when the user opens that tool in the project. Init also injects a
|
|
59
|
+
session-start hook that keeps resources synced from then on.
|
|
56
60
|
4. **Finish with `teamai doctor`.** Every setup or onboarding flow ends by running
|
|
57
61
|
it and resolving what it reports before you call the job done.
|
|
58
62
|
|
|
@@ -69,6 +69,15 @@ to add them to the repo.
|
|
|
69
69
|
|
|
70
70
|
## Step 4 — Initialize with the URL (you run it)
|
|
71
71
|
|
|
72
|
+
Before running `init`, ask whether the user wants to activate any logical
|
|
73
|
+
projects this team repo declares. If `init` lists **Available projects**, show
|
|
74
|
+
the names/IDs and ask which belong to this setup; enter the corresponding
|
|
75
|
+
comma-separated numbers. Press Enter for none only when the user explicitly
|
|
76
|
+
chooses no project. If the IDs are already known, pass `--project id1,id2` to
|
|
77
|
+
skip the picker. For a non-interactive run, ask first and pass `--project`:
|
|
78
|
+
without it, init keeps `projects: []` and prints a `teamai projects set <id>`
|
|
79
|
+
follow-up instead of waiting for a choice.
|
|
80
|
+
|
|
72
81
|
```bash
|
|
73
82
|
# this project only (run from inside the project)
|
|
74
83
|
teamai init https://<platform>/<org>/<repo>
|
|
@@ -93,13 +102,14 @@ teamai init --http https://your-team-host/api --token <api-key>
|
|
|
93
102
|
This is a read-only consumer mode — `push` / `contribute` are not available, but
|
|
94
103
|
skills and rules still sync.
|
|
95
104
|
|
|
96
|
-
**Claude Code kept in a different directory (`CLAUDE_CONFIG_DIR
|
|
97
|
-
that directory (as `toolRoots.claude`
|
|
98
|
-
|
|
99
|
-
`init`
|
|
100
|
-
|
|
101
|
-
and
|
|
102
|
-
|
|
105
|
+
**Claude Code or Codex kept in a different directory (`CLAUDE_CONFIG_DIR`,
|
|
106
|
+
`CODEX_HOME`):** `init` records that directory (as `toolRoots.claude` /
|
|
107
|
+
`toolRoots.codex` in the local config) and syncs every path of that tool there,
|
|
108
|
+
so run `init` from a shell that has the variable exported. Re-running `init` after
|
|
109
|
+
changing it moves the install (the old root's hooks and managed MCP servers are
|
|
110
|
+
removed, and for Claude Code its delivered model credentials; its skills and rules
|
|
111
|
+
are left and named in the output). To end the relocation, run `init` once with the
|
|
112
|
+
variable set but blank: `CLAUDE_CONFIG_DIR= teamai init …` or `CODEX_HOME= teamai init …`.
|
|
103
113
|
|
|
104
114
|
## Step 5 — Verify with doctor
|
|
105
115
|
|
|
@@ -116,11 +126,14 @@ section "Which tools actually get hooks".
|
|
|
116
126
|
|
|
117
127
|
## Step 6 — Confirm the skills actually arrived
|
|
118
128
|
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
`teamai init` ends with a pull, so the team's skills, rules and MCP servers are
|
|
130
|
+
already in place in user scope, and in project scope for each tool named with
|
|
131
|
+
`--agent` or picked in init's interactive tool picker. A project-scope init run
|
|
132
|
+
without a terminal and without `--agent` creates no tool directory; a
|
|
133
|
+
tool's directory fills when the user first opens that tool in the project. To
|
|
134
|
+
confirm:
|
|
121
135
|
|
|
122
136
|
```bash
|
|
123
|
-
teamai pull # sync immediately
|
|
124
137
|
teamai list # see the team skills / rules / docs you now have
|
|
125
138
|
```
|
|
126
139
|
|