teamai-cli 0.26.0-beta.1 → 0.26.0-beta.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamai-cli",
3
- "version": "0.26.0-beta.1",
3
+ "version": "0.26.0-beta.3",
4
4
  "description": "TeamAI — Make Every Team AI Native (skill sync + shared knowledge base, powered by Git)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,11 @@ do not skip, reorder, or invent commands.
15
15
 
16
16
  Look at what the user typed after `/teamai`.
17
17
 
18
- **If they gave NO scenario** (bare `/teamai`, or only greetings/no task):
18
+ **If they gave NO scenario right after a TeamAI friction reminder** (the
19
+ `[teamai]` line that suggests `/teamai share what this session taught me`),
20
+ that reminder is the scenario: load `teamai skill get share` and follow it.
21
+
22
+ **If they gave NO scenario otherwise** (bare `/teamai`, or only greetings/no task):
19
23
  print the menu below **exactly**, then **STOP and wait**. Take no other action —
20
24
  do not run any command, do not load another skill yet.
21
25
 
@@ -62,7 +66,8 @@ Sharing a session's learnings needs no menu choice: TeamAI prompts on its own at
62
66
  the end of a session that produced something worth sharing, and that prompt means
63
67
  `teamai skill get share`. (Only when recall is on; it is off by default. The team turns it on with
64
68
  `sharing.recall.enabled: true` in `teamai.yaml`, a member with `teamai recall enable`;
65
- while it is off, `teamai skill get share` says so.)
69
+ while it is off, or while the teamai config cannot be loaded, `teamai skill get share`
70
+ says so and why.)
66
71
 
67
72
  ## Global rules
68
73
 
@@ -37,6 +37,7 @@ Generated: do not edit by hand. Regenerate with
37
37
  - `--skill <path>` — Push a specific skill by path (e.g., ~/.claude/skills/hai/my-skill or skills/hai_dev/my-skill)
38
38
  - `--role <id>` — Namespace for new skills, rules and agents (skills/<id>/, rules/<id>/, agents/<id>/)
39
39
  - `--project <id>` — Target a project: each new resource goes to that project's namespace for its own type — skills, knowledge for rules, agents (from manifest/projects.yaml)
40
+ - `--branch <name>` — Push to this destination branch instead of a generated teamai/push branch
40
41
 
41
42
  ## pull
42
43
 
@@ -120,6 +121,16 @@ Generated: do not edit by hand. Regenerate with
120
121
  - `teamai projects` — Manage multi-project resource distribution (orthogonal to roles)
121
122
  - `teamai projects list` — List defined projects and the ones active in this directory
122
123
  - `teamai projects set [ids...]` — Set the projects active in this directory (comma-separated or repeated; empty to clear)
124
+ - `teamai projects add <id>` — Add a project to manifest/projects.yaml, creating the file if needed (admin)
125
+ - `--namespaces <ns>` — Comma-separated namespaces for every project resource type (e.g. common,checkout)
126
+ - `--name <name>` — Display name for the project
127
+ - `-d, --description <desc>` — Description for the project
128
+ - `teamai projects update <id>` — Update a project in manifest/projects.yaml (admin)
129
+ - `--add-namespaces <ns>` — Comma-separated namespaces to add to every resource type
130
+ - `--remove-namespaces <ns>` — Comma-separated namespaces to remove from every resource type
131
+ - `--name <name>` — New display name for the project
132
+ - `-d, --description <desc>` — New description for the project
133
+ - `teamai projects remove <id>` — Remove a project from manifest/projects.yaml (admin)
123
134
  - `teamai projects members <id>` — List members registered for a project
124
135
 
125
136
  ## tags
@@ -207,11 +218,38 @@ Generated: do not edit by hand. Regenerate with
207
218
  - `teamai webhook test` — Send test event to webhook endpoints
208
219
  - `--url <url>` — Test specific endpoint URL
209
220
 
221
+ ## models
222
+
223
+ - `teamai models` — Share gateway model profiles and switch agents to them
224
+ - `teamai models list [profile]` — Show team and personal model profiles, or one profile, and the agents using them
225
+ - `teamai models add <id>` — Add a personal model profile stored only on this machine
226
+ - `--name <name>` — Display name
227
+ - `--protocol <protocols>` — Comma-separated: anthropic, openai-chat-completions, openai-responses
228
+ - `--base-url <url>` — Gateway root URL (without /v1)
229
+ - `--model <ids>` — Comma-separated model IDs; the first is the default
230
+ - `--from-env <name>` — Read the API key from this environment variable
231
+ - `--api-key-stdin` — Read the API key from stdin without placing it in shell history
232
+ - `teamai models configure <profile>` — Set the API key of a profile, or edit a personal profile
233
+ - `--from-env <name>` — Read the API key from this environment variable
234
+ - `--api-key-stdin` — Read the API key from stdin without placing it in shell history
235
+ - `--name <name>` — Personal profiles: new display name
236
+ - `--base-url <url>` — Personal profiles: new gateway root URL
237
+ - `--protocol <protocols>` — Personal profiles: serve models over these protocols too
238
+ - `--model <ids>` — Personal profiles: add model IDs
239
+ - `teamai models switch <profile>` — Point agents at a model profile (every compatible agent by default)
240
+ - `--agent <name>` — Only switch this agent. Repeatable or comma-separated.
241
+ - `--model <id>` — Default model to select (defaults to the first in the profile)
242
+ - `--dry-run` — Show what would change without writing
243
+ - `teamai models restore` — Restore agent model settings captured before the first TeamAI switch
244
+ - `--agent <name>` — Only restore this agent. Repeatable or comma-separated.
245
+ - `--dry-run` — Show what would change without writing
246
+ - `teamai models remove <profile>` — Remove a personal model profile without changing agent settings
247
+
210
248
  ## stats
211
249
 
212
250
  - `teamai stats` — Show local skill usage statistics
213
- - `--by-repo` — Break usage down per repository
214
- - `--by-time` — Show activity by hour of day
251
+ - `--by-repo` — Break the local event log down per repository
252
+ - `--by-time` — Show local event log activity by hour of day
215
253
 
216
254
  ## session
217
255
 
@@ -272,7 +310,7 @@ Generated: do not edit by hand. Regenerate with
272
310
 
273
311
  - `teamai import` — Import knowledge from local directories, remote repos, organizations, MRs, or iWiki
274
312
  - `--dir <path>` — Extract code knowledge from a local directory (same as --from-repo but no clone)
275
- - `--from-claude` (hidden) — Scan Claude/Cursor rule directories (~/.claude/rules, ~/.cursor/rules)
313
+ - `--from-claude` (hidden) — Scan Claude/Cursor rule directories (the Claude root's rules/ — ~/.claude or the recorded toolRoots.claude — and ~/.cursor/rules)
276
314
  - `--from-mr <url>` — Extract learning from merged MR/PR and trigger incremental teamwiki update
277
315
  - `--from-iwiki <space-id-or-url>` — Import documents from iWiki Space ID or page URL (requires TAI_PAT_TOKEN)
278
316
  - `--resume` (hidden) — Resume an interrupted import session
@@ -3,12 +3,20 @@
3
3
  Goal: the user turns something they built into team knowledge everyone can pull.
4
4
  **Any member can do this — you do not need to be an admin.** The usual entry point
5
5
  is the user just asking in plain language, e.g. *"share this xxx skill with my
6
- team"*, in whatever language they work in — then you run the publish for them.
6
+ team"*, in whatever language they work in.
7
+
8
+ **Publishing is a team-visible action — confirm before you run it.** A plain
9
+ worded request tells you *what* the user wants, not that they are ready to push
10
+ it to everyone. Before `teamai push` / `teamai contribute`, show exactly what
11
+ will be shared (which skill or file, and that it goes to the whole team) and get
12
+ an explicit go-ahead. Do not publish from an offhand mention of "sharing" in
13
+ ordinary conversation — only when the user has clearly asked to publish *this*
14
+ thing now.
7
15
 
8
16
  ## Which kind of contribution?
9
17
 
10
18
  - **A learning** (a lesson, a gotcha, how you solved something) → this is
11
- **automatic** once recall is on (off by default): TeamAI prompts at the end of a session worth sharing and the
19
+ **automatic** once recall is on (off by default) and the teamai config loads: TeamAI prompts at the end of a session worth sharing and the
12
20
  dedicated `share` workflow (`teamai skill get share`) takes over (it summarizes the
13
21
  session and runs `teamai contribute`). The user does not come through this flow
14
22
  for it. (Step A below is only a manual fallback for while recall is off.)
@@ -89,7 +97,10 @@ The doc lands in the team's `learnings/` and appears for teammates on their next
89
97
  new rule and a new agent land in that namespace too (a project resolves each
90
98
  from its own axis — `knowledge` for rules, `agents` for agents). Without one,
91
99
  a new resource whose namespace cannot be resolved stays at the shared root and
92
- reaches the whole team.
100
+ reaches the whole team. Use `--branch <name>` when a new push must target a
101
+ specific branch; an existing open PR keeps its recorded branch. TeamAI refuses
102
+ to reset a team-repo clone with user changes, so commit or stash unrelated
103
+ modified, staged, untracked, or conflicted files before retrying.
93
104
 
94
105
  ## After contributing
95
106
 
@@ -34,6 +34,12 @@ This is the #1 onboarding issue. In order:
34
34
  with `--scope user`.
35
35
  5. **Tool has no hook surface** (e.g. Gemini CLI, JoyCode): there is no auto-sync;
36
36
  run `teamai pull` manually each time.
37
+ 6. **Claude Code reads a different directory** (`CLAUDE_CONFIG_DIR` is set).
38
+ `teamai doctor` reports `Claude Code root matches CLAUDE_CONFIG_DIR` when the
39
+ directory the variable names is not the one this config syncs to. Re-run
40
+ `teamai init` from a shell that has the variable exported; it records the root
41
+ and moves the install. If the check says the value cannot be synced to (outside
42
+ your home, or nested deeper than `~/.config/<name>`), fix the variable first.
37
43
  6. **A command reports a broken manifest** (`Invalid roles manifest…`,
38
44
  `Invalid projects manifest…`, `Invalid manifests…`, or `…manifest … could not
39
45
  be read`). `pull` skips that scope on purpose, since syncing without the
@@ -56,11 +62,13 @@ default is a common cause.
56
62
 
57
63
  ## GitLab host not detected
58
64
 
59
- If `init` can't confirm a self-hosted GitLab instance, set both and retry:
65
+ If `init` can't confirm a self-hosted GitLab instance, set both and retry. Use a
66
+ short-lived `api`-scope token via a no-echo prompt (not a literal `export`, which
67
+ lands in shell history), and `unset GITLAB_TOKEN` afterward:
60
68
 
61
69
  ```bash
62
70
  export GITLAB_URL=https://git.example.com
63
- export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxx # api scope
71
+ read -rs GITLAB_TOKEN && export GITLAB_TOKEN # paste when prompted; api scope
64
72
  teamai init https://git.example.com/yourgroup/yourrepo
65
73
  ```
66
74
 
@@ -39,12 +39,13 @@ If it fails, Node.js ≥ 20 is missing — have them install Node 20+ first.
39
39
 
40
40
  Match the login to the URL's host (do NOT create a second repo):
41
41
 
42
- - **`git.woa.com/...`** (Tencent TGit) → **you run both the `gf` install and
43
- the `gf … auth login`** (never tell the user to run them). Follow
44
- `{SKILL_DIR}/references/provider-tgit.md` ("Log in"); the user's only action is
45
- approving the login URL in their browser / iOA. No `GITLAB_URL` needed. (No headless
46
- shortcut: `TGIT_TOKEN` is REST-API-only and cannot clone, so the login has to be run
47
- once on the machine.)
42
+ - **`git.woa.com/...`** (Tencent TGit) → after telling the user this installs the
43
+ `gf` binary and stores a credential, and getting their OK, **you may run the
44
+ `gf` install and `gf … auth login` for them** (or show the commands if they
45
+ prefer to run them). Follow `{SKILL_DIR}/references/provider-tgit.md` ("Log in");
46
+ the user's only action is approving the login URL in their browser / iOA. No
47
+ `GITLAB_URL` needed. (No headless shortcut: `TGIT_TOKEN` is REST-API-only and
48
+ cannot clone, so the login has to be run once on the machine.)
48
49
  - **`cnb.cool/...`** → install the CNB CLI, then authorize, in this order:
49
50
  1. `npm install -g @cnbcool/cnb-cli`
50
51
  2. `cnb login` — have the user approve it in the browser (OAuth2 device flow);
@@ -88,6 +89,14 @@ teamai init --http https://your-team-host/api --token <api-key>
88
89
  This is a read-only consumer mode — `push` / `contribute` are not available, but
89
90
  skills and rules still sync.
90
91
 
92
+ **Claude Code kept in a different directory (`CLAUDE_CONFIG_DIR`):** `init` records
93
+ that directory (as `toolRoots.claude` in the local config) and syncs every Claude
94
+ path there, so run `init` from a shell that has the variable exported. Re-running
95
+ `init` after changing it moves the install (the old root's hooks, managed MCP
96
+ servers and delivered model credentials are removed; its skills and rules are left
97
+ and named in the output). To end the relocation, run `init` once with the variable
98
+ set but blank: `CLAUDE_CONFIG_DIR= teamai init …`.
99
+
91
100
  ## Step 5 — Verify with doctor
92
101
 
93
102
  ```bash
@@ -143,7 +152,8 @@ Summarize the outcome **in the user's own language** (global rule 1). Cover:
143
152
  summarize and contribute it. They do **not** invoke `/teamai` for this. (This
144
153
  prompt only appears when recall is on — it is off by default; the admin turns it
145
154
  on in `teamai.yaml` (`sharing.recall.enabled`), a member with `teamai recall enable` — and the admin has not switched the
146
- reminder off in `teamai.yaml`.)
155
+ reminder off in `teamai.yaml`. It also stays silent while their teamai config
156
+ cannot be loaded; `teamai skill get share` then names the file and the error.)
147
157
  3. **They can also contribute a skill — just ask in plain language.** A member does
148
158
  not need to be an admin to publish a skill. They tell TeamAI something like
149
159
  *"share this xxx skill with my team"*, in their own language, and you
@@ -16,8 +16,13 @@ existing ones:
16
16
  teamai push # review the diff, then confirm
17
17
  teamai push --all # push everything without per-item confirmation
18
18
  teamai push --skill <path> # push one specific skill
19
+ teamai push --branch <name> # use an explicit branch for a new push
19
20
  ```
20
21
 
22
+ An existing open PR is updated on its recorded branch. TeamAI refuses to reset a
23
+ team-repo clone with unrelated modified, staged, untracked, or conflicted files;
24
+ commit or stash those changes before retrying.
25
+
21
26
  Members receive it automatically the next time they open a session (or when they
22
27
  run `teamai pull`).
23
28
 
@@ -76,10 +81,16 @@ repo per project:
76
81
  teamai projects list # projects defined + the ones active in this directory
77
82
  teamai projects set [ids...] # set the active project(s) for this directory
78
83
  teamai projects members <id> # who is registered on a project
84
+ teamai projects add <id> --namespaces common,<id> # add a project (creates projects.yaml if needed)
85
+ teamai projects update <id> --add-namespaces <ns> # or --remove-namespaces / --name / --description
86
+ teamai projects remove <id> # remove a project
79
87
  ```
80
88
 
81
89
  A member gets the union of their role resources and their active project's
82
- resources. Admins declare projects in `manifest/projects.yaml`, then `teamai push`.
90
+ 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`,
92
+ keep the project's content in the team repo until members have pulled: that is
93
+ what lets their next pull clean up the copies they deployed.
83
94
 
84
95
  Every namespace that names a directory — `knowledge`, `skills` and `agents` in
85
96
  either manifest, and `learnings` in `projects.yaml` (a role's `learnings:` is
@@ -133,14 +144,16 @@ the team (`sharing.recall.enabled: true` in `teamai.yaml`, then `teamai push`; i
133
144
  off by default, and `teamai recall enable` turns it on for one machine only): at the end of a session
134
145
  worth sharing, TeamAI prompts the member and the dedicated
135
146
  `share` workflow (`teamai skill get share`) summarizes the session and runs
136
- `teamai contribute`. Nobody has to invoke it by hand.
147
+ `teamai contribute`. Nobody has to invoke it by hand. (A member whose teamai config
148
+ cannot be loaded gets no prompt; `teamai skill get share` names the file and the error.)
137
149
  (Publishing a **reusable skill** someone authored is a different task — any member
138
150
  can do it, see `"$(teamai skill path core)/references/contribute-member.md"`.)
139
151
 
140
152
  ### Turn the sharing prompt on or off (admin)
141
153
 
142
154
  The auto-share prompt is **on by default once recall is on**, and only shows in directories set up
143
- with teamai. To disable it team-wide, set this in
155
+ with teamai (never on a read-only HTTP source, or while a member's teamai config cannot be loaded).
156
+ To disable it team-wide, set this in
144
157
  `teamai.yaml` and `teamai push`:
145
158
 
146
159
  ```yaml
@@ -22,12 +22,15 @@ is the Tencent-internal default. Choose by account + reachability only, never by
22
22
  region. (A member joining an existing `git.woa.com` URL skips the probe — the URL
23
23
  already fixes the platform.)
24
24
 
25
- ## Log in: install `gf`, then `gf auth login` — YOU run both
25
+ ## Log in: install `gf`, then `gf auth login`
26
26
 
27
- TeamAI drives the TGit CLI (`gf`) on the user's behalf. **Run every command in this
28
- section yourself — both the install and the login. Never tell the user to run a
29
- `gf` command.** The user's only action is approving the login in their browser /
30
- iOA when it opens.
27
+ TeamAI can drive the TGit CLI (`gf`) on the user's behalf. Before the first
28
+ command, **tell the user what this does** — it downloads and installs the `gf`
29
+ binary and, after login, stores an auth credential on their machine — and **get
30
+ their OK to proceed**. Once they agree, you may run the install and login steps
31
+ for them so they don't have to type `gf` commands; their remaining action is
32
+ approving the login in their browser / iOA when it opens. If the user prefers to
33
+ run the commands themselves, show them the exact commands instead.
31
34
 
32
35
  ### 1. Install `gf` (you run this)
33
36
 
@@ -35,17 +38,37 @@ Use the **same source, path, and check teamai uses** — do not invent your own
35
38
  `${TEAMAI_HOME}` is `~/.teamai` unless overridden:
36
39
 
37
40
  ```bash
41
+ set -eu # abort on any failure — never fall through to `gf auth login` on a bad install
42
+
38
43
  # pick the tarball for this machine's OS/arch (darwin|linux × x64|arm64)
39
44
  os=$(uname -s | tr '[:upper:]' '[:lower:]') # darwin | linux
40
45
  arch=$(uname -m); [ "$arch" = "x86_64" ] && arch=x64; [ "$arch" = "aarch64" ] && arch=arm64
41
46
  dir="${TEAMAI_HOME:-$HOME/.teamai}/gf"
47
+ url="https://mirrors.tencent.com/repository/generic/gongfeng-cli/files/channels/stable/gf-${os}-${arch}.tar.gz"
42
48
 
43
- # download + extract from the Tencent-internal mirror (same URL teamai uses)
49
+ # unique temp files per attempt so concurrent/interrupted runs never collide,
50
+ # cleaned up on any exit
44
51
  mkdir -p "$dir"
45
- curl -fsSL "http://mirrors.tencent.com/repository/generic/gongfeng-cli/files/channels/stable/gf-${os}-${arch}.tar.gz" | tar xz -C "$dir"
46
-
52
+ tmp="$dir/gf-download.$$-$RANDOM"
53
+ trap 'rm -f "$tmp.tar.gz" "$tmp.headers"' EXIT
54
+
55
+ # download over HTTPS, verify sha256, THEN extract (the same safe path teamai
56
+ # uses). Fail closed: no advertised digest, or a mismatch, aborts the install.
57
+ curl -fsSL -D "$tmp.headers" -o "$tmp.tar.gz" "$url"
58
+ # The mirror 302-redirects to a content-addressed backend whose URL path is the
59
+ # artifact's sha256; fall back to the x-checksum-sha256 header for direct serves.
60
+ expected=$(grep -i '^location:' "$tmp.headers" | grep -oiE '[0-9a-f]{64}' | tail -1 || true)
61
+ [ -n "$expected" ] || expected=$(grep -i '^x-checksum-sha256:' "$tmp.headers" | tr -d '\r' | awk '{print $2}' || true)
62
+ actual=$( (command -v sha256sum >/dev/null && sha256sum "$tmp.tar.gz" || shasum -a 256 "$tmp.tar.gz") | awk '{print $1}')
63
+ if [ -z "$expected" ] || [ "$expected" != "$actual" ]; then
64
+ echo "gf download integrity check FAILED (expected=$expected actual=$actual)" >&2
65
+ exit 1
66
+ fi
67
+
68
+ tar xz -f "$tmp.tar.gz" -C "$dir"
47
69
  # verify exactly as teamai does: the binary exists and is executable
48
- test -x "$dir/gf/bin/gf" && echo "gf installed OK" || echo "gf install FAILED"
70
+ test -x "$dir/gf/bin/gf"
71
+ echo "gf installed OK"
49
72
  ```
50
73
 
51
74
  Only macOS and Linux, on x64 or arm64, are supported.
@@ -138,12 +138,15 @@ with `repo` scope — instead.)
138
138
 
139
139
  ### GitLab (gitlab.com)
140
140
 
141
- Set a Personal Access Token with `api` scope:
141
+ Set a Personal Access Token with `api` scope. Prefer a **short-lived** token and
142
+ pull it from a secret manager or a no-echo prompt rather than typing the literal
143
+ value (a pasted `export` lands in shell history and process listings):
142
144
  ```bash
143
- export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxx
145
+ read -rs GITLAB_TOKEN && export GITLAB_TOKEN # paste when prompted; not echoed
144
146
  ```
145
147
  Self-hosted GitLab: also set the instance URL first —
146
- `export GITLAB_URL=https://git.example.com`.
148
+ `export GITLAB_URL=https://git.example.com`. Run `unset GITLAB_TOKEN` when
149
+ `teamai init` is done.
147
150
 
148
151
  For GitHub/GitLab, `teamai init` installs any helper CLI it needs automatically.
149
152
 
@@ -187,9 +190,11 @@ If the repo does not exist yet, `init` offers to create it — accept the prompt
187
190
  - If `init` detects an unknown GitLab host, it stops and asks you to set
188
191
  `GITLAB_URL` + `GITLAB_TOKEN`, then retry.
189
192
 
190
- If the repo has roles enabled, `init` may ask for a primary role — pick one with
191
- the user, or pass `--role <id>` for a non-interactive run. Without a terminal
192
- (or with `CI` / `TEAMAI_NONINTERACTIVE` set) `init` never waits: a provider that
193
+ If the repo has roles enabled, `init` asks for one or more comma-separated role
194
+ numbers when running interactively. The first number is the primary role and the
195
+ remaining numbers become additional roles; pass `--role <id>` for a
196
+ non-interactive run when only a primary role is needed. Without a terminal (or
197
+ with `CI` / `TEAMAI_NONINTERACTIVE` set) `init` never waits: a provider that
193
198
  would need a browser login fails at once and names the credential to prepare —
194
199
  a token for GitHub / CNB / GitLab / GitCode, and for TGit a prior `gf auth
195
200
  login` run in an interactive shell (see Step 3).
@@ -275,7 +280,8 @@ day-to-day work — they can keep letting the AI run things for them:
275
280
  its own at the end of a session worth sharing, and the `share` workflow
276
281
  (`teamai skill get share`) takes over. (Only once recall is on — off by default;
277
282
  turn it on team-wide with `sharing.recall.enabled: true` in `teamai.yaml`, then
278
- `teamai push`.)
283
+ `teamai push`. Never on a read-only HTTP source, or while a member's teamai
284
+ config cannot be loaded.)
279
285
 
280
286
  Mention the underlying commands (`teamai push`, `teamai roles`, …) only as a note
281
287
  for users who *do* want them — the primary path is re-invoking `/teamai`.