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.
@@ -31,12 +31,58 @@ run `teamai pull`).
31
31
  ```bash
32
32
  teamai mcp list # team MCP servers + per-tool install status
33
33
  teamai mcp inject # push team MCP servers into every AI tool's config
34
+ teamai mcp remove --dry-run # preview removal without changing tool configs or managed records
34
35
  teamai mcp remove # remove teamai-managed MCP servers
35
36
  ```
36
37
 
37
38
  MCP definitions travel with the team repo like skills/rules — edit, then the
38
39
  members pick them up on sync.
39
40
 
41
+ A server with a `${VAR}` the tool cannot expand itself gets the resolved value
42
+ written into its project config (`.mcp.json`, `.cursor/mcp.json`, ...). Before
43
+ that write, teamai lists the file in the clone's `.git/info/exclude`, inside a
44
+ `# [teamai:mcp-exclude:start]` block; the committed `.gitignore` is never touched.
45
+ A file under a symlinked directory is listed and checked where the write lands
46
+ (`.cursor/` linking to `config/`: `/config/mcp.json`); a symlink at the file
47
+ itself is replaced by the write.
48
+ When it cannot (git already tracks the file, a rule in the member's git ignore
49
+ files re-includes it, `.git/info` is not writable, the exclude file is held by
50
+ another teamai command, or git errors), it leaves the file as it was, warns, and
51
+ `teamai mcp list` shows `withheld: <tool> — <reason>. <fix>`. Apply the fix it
52
+ names (a tracked file: `git rm --cached <file>` and rotate the token; a
53
+ re-including rule such as `!/.mcp.json`: remove it), then run `teamai pull`. A pull or `teamai mcp remove` takes a line out
54
+ once its file no longer holds a resolved value; `teamai uninstall` does so in
55
+ every worktree. A file written under a `toolPaths.<tool>.mcpProject` the team
56
+ later changes or removes stays listed until it is deleted or holds no server;
57
+ for one an older teamai wrote, the first pull finds the path in the team repo's
58
+ history of `teamai.yaml`, or among the built-in paths teamai has since changed
59
+ (not one the same tool maps today), and lists it while it holds any server; one
60
+ git tracks is recorded instead and listed once the member runs `git rm --cached`
61
+ on it. `teamai doctor` checks those paths until that pull. A file written for a
62
+ tool the team moved elsewhere (recorded, or found in that history), that another
63
+ tool still maps, stays listed while it holds a server that tool did not write,
64
+ one of the member's own included. The built-in location of a tool the team drops
65
+ from `toolPaths` or moves elsewhere stays listed while it holds any server; one
66
+ another tool maps today (CodeBuddy's `.mcp.json`, which Claude maps) while it
67
+ holds a server that tool did not write. A file two tools map, with no pull on
68
+ this version having recorded it, needs a `managed-mcp.json` record from each of
69
+ them. While a worktree has no `managed-mcp.json` at all (lost, or before its
70
+ first pull), an untracked config holding a server no record claims is listed,
71
+ and that server noted: it keeps the line until it leaves the file. So is the
72
+ file of a tool `managed-mcp.json` has no record for, when a pull writes that
73
+ tool's first record (its record lost, or teamai's first delivery to it). While that
74
+ note cannot be written (another teamai command holds the record), the line stays
75
+ until a later pull writes it. A Copilot project config's bare top-level servers
76
+ still count once another tool writes `mcpServers` into the file. On an HTTP-backed
77
+ team the local agent's `install_mcp` lists a project config before writing a
78
+ server with any header, env value, argument or URL (only a bare stdio command is not), fails the install when it cannot, and only
79
+ `teamai uninstall` takes that line out. The next sync or `teamai pull` in the
80
+ workspace also lists a file an older local agent wrote a credential into; `teamai doctor` checks those files too.
81
+
82
+ ### Pi MCP delivery
83
+
84
+ Pi 0.99.0+ receives stdio and streamable HTTP servers through the existing MCP commands and `teamai pull`; SSE is skipped. User scope writes `~/.pi/agent/mcp.json`, project scope writes `.pi/mcp.json` (Pi requires project trust). TeamAI keeps Pi's default codemode exposure and converts timeout milliseconds to seconds. Relocated Pi agent directories (`PI_CODING_AGENT_DIR` / `PI_CONFIG_DIR`) are unsupported. Local exposure/enabled edits on managed servers survive until the team definition changes; doctor reports differences from the team entry. Extensions that replace `/mcp` must be removed to use Pi's built-in MCP.
85
+
40
86
  ## Invite a member
41
87
 
42
88
  There is **no CLI invite flag.** Inviting is done on the Git platform's website:
@@ -88,7 +134,9 @@ teamai projects remove <id> # remove a project
88
134
 
89
135
  A member gets the union of their role resources and their active project's
90
136
  resources. Admins declare projects in `manifest/projects.yaml` with the commands
91
- above, each of which opens a PR (`--dry-run` previews). After `projects remove`,
137
+ above, each of which opens a PR. Until #971 lands and restores the guard
138
+ classification, `roles init/add/update/remove` and `projects add/update/remove`
139
+ refuse `--dry-run` before pulling the team repo. After `projects remove`,
92
140
  keep the project's content in the team repo until members have pulled: that is
93
141
  what lets their next pull clean up the copies they deployed.
94
142
 
@@ -150,10 +198,12 @@ teamai push # share the updated teamai.yaml
150
198
 
151
199
  ```bash
152
200
  teamai env list # what reaches this directory, each with its namespace (values masked)
153
- teamai env list --reveal # show values in plaintext
201
+ teamai env list --reveal # show variable values in plaintext (never a secret's)
154
202
  teamai env add <KEY> <VALUE> # add or update in env/env.yaml
155
203
  teamai env add <KEY> <VALUE> --project <id> # or --role <ns>: in that namespace's env/<ns>/env.yaml (warns if nothing declares <ns>)
156
204
  teamai env remove <KEY> # remove (same --role / --project)
205
+ teamai env add <KEY> --secret -d "<what it is for>" --url <where to get one> # declare a secret in env/secrets.yaml, no value (same --role / --project)
206
+ teamai env remove <KEY> --secret # remove a declared secret (plain `env remove` does too when env.yaml does not set <KEY>)
157
207
  teamai remove mcp <name> # root mcp/mcp.yaml if it has the name, else the one namespace file; --role / --project pick a namespace
158
208
  ```
159
209
 
@@ -171,17 +221,38 @@ and push it with git. `teamai doctor` lists each override.
171
221
  state is kept. Fix the file the warning names. A hooks or MCP file with none of
172
222
  its top-level keys (`server:` for `servers:`) counts as one that does not parse.
173
223
  - Per-entry `projects:` (and `roles:` on env) no longer works: such an entry reaches
174
- nobody. `roles:` on hooks and MCP still filters for one more minor release. Pull
175
- and `teamai doctor` name the namespace file each entry belongs in; move it there.
224
+ nobody. `roles:` on hooks and MCP still filters for one more minor release. Pull,
225
+ the list commands (`teamai env list`, `teamai mcp list`, `teamai hooks list`,
226
+ `teamai list <env|hooks|mcp> --source repo`), `teamai status` and
227
+ `teamai doctor` name the namespace file each entry belongs in; move it there.
228
+ When `teamai env add` updates a variable carrying either removed key, it keeps
229
+ the key and warns that pull will not deliver the variable, naming that file.
176
230
  - An env, hook or MCP entry with a key its schema does not know (a mistyped `role:`)
177
- also reaches nobody. Pull and `teamai doctor` name the file, entry and key; correct
178
- the key or remove it. A key a later teamai version adds is unknown to an older one,
179
- so upgrade every member before the team uses a new entry key.
231
+ also reaches nobody. Pull, the list commands, `teamai status` and
232
+ `teamai doctor` name the file, entry and key; correct the key or remove it.
233
+ A key a later teamai version adds is unknown to an older one, so upgrade every
234
+ member before the team uses a new entry key.
180
235
  - Team model profiles work the same way: `models/<ns>/models.yaml`, declared under
181
236
  `resources.models`, replaces the root profile with the same `id` for members who
182
237
  have `<ns>` active. A member's API key is bound to the profile's gateway origin:
183
238
  when an override points at another host, their pull leaves the agent alone and
184
239
  asks them to run `teamai models switch team:<id>` to set the key for it.
240
+ - Secrets are declared with no value in `env/secrets.yaml` or `env/<ns>/secrets.yaml`
241
+ (active through `resources.env`; a namespace entry replaces the root entry with the
242
+ same key): a `secrets:` list of `key`, optional `description` and optional `url`
243
+ (where a member gets one). Never put a value there: `teamai env add <KEY> --secret`
244
+ takes none and rejects one. Declare with it or edit the file in the team repo;
245
+ `teamai push` picks it up. Each member sets their own value with `teamai env set KEY`
246
+ in their terminal (`--global` for every team on their machine; a team value still
247
+ wins). `teamai env list` shows each secret as `team`, `global`, `environment`,
248
+ `missing` or `unreadable` and never shows a value, `--reveal` included. The `description` is what
249
+ agents see: the session-start hook lists each declared key with it and tells the
250
+ agent to run the CLIs that need them through `teamai env exec --`, so say which
251
+ tool or server uses the key. As the agent, run `teamai env add <KEY> --secret`
252
+ yourself and leave the value to each member's own terminal. A key declared as a secret
253
+ and also set in `env.yaml` is a secret: its `env.yaml` value is not delivered. A
254
+ secrets file that does not parse keeps `env.sh` and MCP servers as they were, and
255
+ `teamai doctor` fails a check naming the file.
185
256
  - Have every member upgrade before declaring `env`, `hooks`, `mcp`, `models` or `docs` in a
186
257
  manifest: teamai 0.25.0 and the 0.26.0 betas reject those keys and their pull stops.
187
258
 
@@ -165,6 +165,15 @@ suggested form `TeamAi-<team-name>`.)
165
165
 
166
166
  Use the **full URL**, never `owner/repo`:
167
167
 
168
+ Ask whether the user wants to activate any logical projects this team repo
169
+ declares. If `init` lists **Available projects**, show the names/IDs and ask
170
+ which belong to this setup; enter the corresponding comma-separated numbers.
171
+ Press Enter for none only when the user explicitly chooses no project. If the
172
+ IDs are already known, pass `--project id1,id2` to skip the picker. For a
173
+ non-interactive run, ask first and pass `--project`: without it, init keeps
174
+ `projects: []` and prints a `teamai projects set <id>` follow-up instead of
175
+ waiting for a choice.
176
+
168
177
  ```bash
169
178
  # project scope (default) — run from inside the project directory
170
179
  teamai init https://<platform>/<org>/<repo-name>
@@ -204,8 +213,9 @@ login` run in an interactive shell (see Step 3).
204
213
  Claude Code"). Omitting `--agent` gives an interactive picker — select **every AI
205
214
  tool already installed** on the machine. Then **report back which agents were set
206
215
  up**, in the user's language: name the tools that will now auto-start TeamAI, and
207
- any detected tool that was skipped and why (e.g. Codex trust-gate,
208
- CodeBuddy/WorkBuddy by design — see the troubleshooting reference, `"$(teamai skill path core)/references/troubleshooting.md"`).
216
+ any detected tool that was skipped and why (e.g. CodeBuddy/WorkBuddy by design),
217
+ and any installed hooks that still need trust (e.g. Codex with automatic trust
218
+ disabled or unavailable). See the troubleshooting reference, `"$(teamai skill path core)/references/troubleshooting.md"`.
209
219
 
210
220
  ## Step 6 — Verify with doctor
211
221
 
@@ -257,9 +267,12 @@ carries counts + tool names only, on a separate branch of that same repo.)
257
267
  URL filled in. The `/teamai` prefix stays as-is; translate the rest:
258
268
  `/teamai Help me join my team's TeamAI, repo URL is <URL>`
259
269
  Tell them to send the URL + this line to each member.
260
- 3. Remind them (in their language): **new resources appear only after opening a
261
- fresh session** in the AI tool. Right after init the skills folder may look
262
- empty — that is expected. To sync now, run `teamai pull`.
270
+ 3. Remind them (in their language): a member's `teamai init` ends with a pull, so
271
+ the team's resources are in place when it exits (in project scope, for each
272
+ tool named with `--agent` or picked in init's tool picker; otherwise a tool's
273
+ directory fills when the
274
+ member first opens that tool in the project). Resources the team adds later
275
+ arrive at the next session start.
263
276
 
264
277
  ## Step 9 — What's next (guide them, don't just list commands)
265
278
 
@@ -14,7 +14,14 @@ machine** (all tools)?"*
14
14
 
15
15
  - **Just this tool** → `--agent <tool>` (use the tool this conversation runs in,
16
16
  e.g. `claude`). Shared resources are removed only if it is the last tool using
17
- them.
17
+ them. An instructions file several tools read (CodeBuddy and WorkBuddy share
18
+ `.codebuddy/rules/teamai-context.md`) is cleaned block by block: a teamai
19
+ block stays while a remaining tool on that file still writes it, so
20
+ `--agent workbuddy` keeps that file while CodeBuddy is installed. The team
21
+ rules in a project's `.codebuddy/rules` are shared the same way. A file an
22
+ earlier release wrote the blocks to, such as the project `AGENTS.md`, loses
23
+ its teamai blocks, since no tool reads them there now. A file teamai created
24
+ goes with its last block; one the user had before stays, even if empty.
18
25
  - **Whole machine** → no `--agent` flag.
19
26
 
20
27
  Reassure them (in their language): *"This only removes things from your computer.
@@ -23,6 +30,8 @@ Your team's repo on the website is untouched — you can rejoin any time with
23
30
 
24
31
  ## Step 2 — Run it (you run it)
25
32
 
33
+ A targeted project exclusion needs the same confirmation even when there are no local files to remove. `--dry-run` and declining confirmation leave the project config unchanged.
34
+
26
35
  Whole machine:
27
36
 
28
37
  ```bash
@@ -51,7 +60,61 @@ and give it your team repo URL."*
51
60
 
52
61
  ## Notes
53
62
 
63
+ - For OpenCode, uninstall also removes the rules globs teamai added to
64
+ `instructions` in `opencode.json`, including the relative `rules/*.md` an
65
+ earlier release wrote in user scope. In a project it removes
66
+ `.opencode/rules/**/*.md` from `.opencode/opencode.json` and the
67
+ `.opencode/rules/*.md` an earlier release wrote to the root `opencode.json`,
68
+ and deletes `.opencode/opencode.json` when nothing else is left in it.
69
+ The user's own entries stay.
70
+ - Uninstall removes the team-rules block from the file a tool with no rules
71
+ format reads in user scope (`~/.codex/AGENTS.md`, `~/.zcode/AGENTS.md`,
72
+ `$DSH_HOME/AGENTS.md`, the OpenClaw workspace `AGENTS.md`,
73
+ `~/.pi/agent/AGENTS.md`, `~/.joycode/rules.txt`), and the file when teamai
74
+ created it for the block alone.
75
+ - Uninstall cleans legacy Codex rule copies at the recorded `toolRoots`
76
+ location, including publishers' bare local filenames, and the copies earlier
77
+ releases left in a project's `.workbuddy/rules` and `.pi/rules`, in
78
+ `.openclaw/rules`, `~/.pi/agent/rules` and `~/.joycode/rules`. It keeps
79
+ edited copies and names them.
80
+ For a rule the team has
81
+ removed, it deletes the copy only if its hash matches the recorded delivery.
82
+ Without that record, it keeps the copy and names it in a warning. Save any
83
+ changes you need, then delete the copy manually.
84
+ - If an OpenCode config entry cannot be removed, repair its config or permissions
85
+ and retry the same uninstall command. Uninstall reports failure and keeps
86
+ its ownership record and shared data directory, even for the last tool.
87
+ - Project uninstall keeps the global Pi and Oh My Pi extensions, Hermes
88
+ plugin and config, and the Codex family's user-level hooks, which the user
89
+ scope, the HTTP agent or another project may use, and names them. If none
90
+ does, run `teamai hooks remove` in the project first: it removes them.
91
+ Targeted project Codex uninstall keeps project config and records its
92
+ exclusion, even without local resources. Legacy project hook copies go.
93
+ User-scope uninstall removes these global channels.
94
+ The retained adapters respect project exclusions, including cached HTTP
95
+ prompt injection and HTTP sync. An excluded tool does not download its
96
+ resources again on the next session start.
97
+ - An enabled, installed Pi, Oh My Pi, Hermes or project Codex also keeps the
98
+ project's shared state in use without a local tool directory. Uninstalling
99
+ another tool preserves that state and the remaining tool's instructions.
54
100
  - Do **not** delete the team repo on the Git platform — uninstall never touches it,
55
101
  and neither should you.
56
102
  - If the user only wants to stop auto-sync for one tool but keep TeamAI otherwise,
57
103
  that is the `--agent <tool>` form, not a full uninstall.
104
+ - In a project, uninstall also removes teamai's git hook: the
105
+ `hook.teamai-post-checkout` / `hook.teamai-post-merge` entries in the repo's git
106
+ config and the `# >>> teamai git hook` block in `.git/hooks/post-checkout` and
107
+ `post-merge`. Other hooks stay; a script left with only its shebang is deleted.
108
+ - In a project, uninstall also takes teamai's lines out of `.git/info/exclude`
109
+ (the `# [teamai:mcp-exclude:start]` block) for MCP configs it proves hold no
110
+ resolved `${VAR}` value. A line names the path a write lands in: for a config
111
+ under a symlinked directory, the link's target (`/config/mcp.json` for
112
+ `.cursor/` linking to `config/`). For one it cannot prove clean (including one written
113
+ under a `toolPaths` mapping since changed, at the built-in location of a tool
114
+ the team dropped or moved that no other tool maps, or in a nested repository's
115
+ linked worktree, that still holds servers, and one written for a tool since moved
116
+ (or at its built-in location) that another tool maps, holding a server that tool
117
+ did not write) it keeps the line
118
+ and warns, naming the file and why: have the user remove teamai's servers from
119
+ that file, then delete the line (with the last one, the block's markers). Do not
120
+ delete a kept line while its file still holds a token.