teamai-cli — a shared AI experience framework for teams
Helps teams centrally manage and share Skills, Rules, Docs, and Env resources, automatically syncing them to AI coding tools like Claude Code, CodeBuddy, Cursor, Codex, Gemini CLI, and Windsurf.
- Core Concepts
- Installation
- Admin Initialization
- Member Onboarding
- Day-to-Day Use
- Sharing Team Resources
- Knowledge Capture & Retrieval
- Team Culture
- Advanced Features
- Configuration Reference
- Uninstall
- FAQ
| Concept | Description |
|---|---|
| Team Repo | A Git repository that centrally stores a team's shared Skills / Rules / Docs / Env resources |
| Scope | Where resources are installed: user (home directory, default) or project (project directory) |
| Skills | Custom skills the AI can invoke (a directory containing a SKILL.md) |
| Rules | Markdown-formatted team conventions, automatically merged into AI tool configs |
| Docs | Shared team documentation for the AI to reference |
| Env | Shared team environment variables, automatically injected into the shell |
┌───────────────┐ teamai push (MR) ┌───────────────────┐
│ Your local │ ──────────────────────→ │ Team Repo (Git) │
│ resources │ │ skills/rules/docs │
│ skills/rules │ ←────────────────────── └───────────────────┘
└───────────────┘ teamai pull (auto)
│
▼
┌──────────────────┐
│ AI tools fetch │
│ automatically │
│ Claude / CodeBuddy│
│ Cursor / Codex │
└──────────────────┘
npm install -g teamai-cli
# Verify
teamai --versionPrerequisites: Node.js ≥ 18, Git (TGit users also need the gf CLI, and CNB users the cnb CLI — teamai init installs either automatically)
Only one admin needs to do this — other members can skip to Member Onboarding.
Create an empty repository on GitHub, TGit (Tencent's internal Git host), or CNB (cnb.cool) (suggested naming: TeamAi-<team-name>), or simply run teamai init — if the repo doesn't exist yet, you'll be prompted to create it automatically.
Resources are installed under the project directory (<project>/.claude/skills/, etc.), suited for project-specific skills and rules.
# project is the default — --scope can be omitted
cd /path/to/my-project
teamai init <group>/TeamAi-<team>
# equivalent alias: teamai init --repo <group>/TeamAi-<team>Resulting directory structure:
/path/to/my-project/
├── .teamai/ # Project-level config (with an auto-generated .gitignore)
│ ├── config.yaml
│ └── team-repo/
├── .claude/skills/ # Project-level skills (auto-synced)
├── .claude/rules/ # Project-level rules (auto-synced)
└── src/
If the repo has role-based skills enabled (i.e. manifest/roles.yaml exists), teamai init will also interactively ask you to choose:
primaryRole: the target namespace for skill sync and push by defaultadditionalRoles: additional skill namespaces to sync
You can also skip the interactive prompts via CLI flags for a fully non-interactive init (suitable for CI/CD or AI agents):
teamai init <group>/TeamAi-<team> --scope project --role hai_dev --force| Flag | Description |
|---|---|
[repo] / --repo <url> |
Team repo URL (positional preferred; --repo is a permanent alias) |
--scope <project|user> |
Install scope, defaults to project (<cwd>/.teamai). Use user for ~/ |
--role <id> |
Directly specify the primary role, skipping the interactive role prompt |
--force |
Overwrite existing config, skipping confirmation prompts |
Example local config:
repo:
localPath: /path/to/my-project/.teamai/team-repo
remote: https://github.com/group/repo.git
username: alice
scope: project
projectRoot: /path/to/my-project
primaryRole: hai
additionalRoles:
- pm
resourceProfileVersion: 1Resources are installed into your home directory (~/.claude/skills/, etc.), suited for general team conventions and cross-project skills.
teamai init <group>/TeamAi-<team> --scope userResulting directory structure:
~/.teamai/
├── config.yaml # Local config
├── team-repo/ # Clone of the team repo
│ ├── teamai.yaml # Remote team config
│ ├── skills/ rules/ docs/ env/ members/
│ ├── manifest/roles.yaml # Role definitions (when role-based skills are enabled)
│ └── learnings/ # Team knowledge base
~/.claude/skills/ # Team skills (auto-synced)
~/.claude/rules/ # Team rules (auto-synced)
| Dimension | Project Scope (default) | User Scope |
|---|---|---|
| Install location | Under the project directory | Under ~/ |
| Best for | Project-specific skills and rules | General team conventions, cross-project skills |
| Can coexist | ✅ Yes, both scopes can be active at once | ✅ Yes, both scopes can be active at once |
Local install location is decided only by
teamai init's--scope(defaultproject). Ascopefield in remoteteamai.yaml, if present, is ignored.
Once the admin shares the team repo URL with members:
Project-scoped teams (default):
npm install -g teamai-cli
cd /path/to/my-project
teamai init <group>/TeamAi-<team>
# Done! AI tools now automatically have access to team resourcesUser-scoped teams:
npm install -g teamai-cli
teamai init <group>/TeamAi-<team> --scope userHTTP mode (read-only consumer):
For users or agents that don't need git access and only consume skills/rules:
teamai init --http https://your-team-host/api --token <api-key>- Read-only mode:
push/contribute/removeare not available. - No git clone required — skills/rules are delivered via a report/sync/ack lifecycle on a per-session basis.
- Supported agents automatically report their installed skill state at session start, and pull install/update/uninstall commands managed by the server.
- The API key is stored with
0600permissions, or can be passed via theTEAMAI_API_TOKENenvironment variable.
Verify:
teamai status # View status
teamai members # View team members
teamai list # All resource types (skills|rules|docs|env|agents|hooks|mcp) + local skills
teamai list mcp # Only team MCP servers
teamai list --source repo # Team repo only
teamai list --source local # Skills under each installed agent
teamai list --agent claude --verbose
teamai list env --reveal # Show env values in plaintext (default: masked)
teamai skill # Equivalent to teamai list skills --source all
teamai skill show hai-deploy-test # View a single skill's source / contributor / install locations / description summaryteamai init already injected Hooks into your AI tools. teamai pull runs automatically every time you start an AI session — no manual action needed.
If you need to sync immediately, you can run it manually:
teamai pull # Manual pull
teamai pull --dry-run # Dry run, no actual changesIf you have both a user scope and a project scope,
pullwill pull resources for both scopes in sequence, without conflicts.
With role-based skills enabled, pull's skill sync source becomes the contents of skills/<namespace>/, expanded according to primaryRole + additionalRoles and flattened into each local AI tool's skills directory. rules/, docs/, and learnings/ keep their original global sync behavior.
If a skill shared by the team doesn't suit you, you can exclude it locally only — no need to modify the team repo, and it won't affect other members:
teamai skill exclude add using-superpowers
teamai pull # Remove it from local AI tools
teamai skill exclude list
teamai skill exclude remove using-superpowers
teamai pull # Re-syncThe exclusion list is stored in the config.yaml of the current user or project scope:
excludedSkills:
- using-superpowersExclusion rules take effect after role and tag filtering. When running teamai pull, excluded skills are not synced, and any copies previously installed by pull are cleaned up.
teamai push # Scan for new/modified resources, create an MR
teamai push --all # Skip confirmation, push directly
teamai push --role pm # Push this skill to skills/pm/<skill-name>/Namespace selection (new skills): When pushing a new skill, the CLI automatically detects available namespaces and offers an interactive choice:
Which namespace should new skills be pushed to?
1. common
2. hai
3. pm
Choose namespace [1-3] (default: 1 = common):
- If
primaryRoleis set, the list of available namespaces is expanded from the manifest - If
primaryRoleis not set, the team repo's directory structure is scanned automatically - A single namespace is auto-selected;
--silentmode uses the default - Modifying an existing skill automatically keeps its original namespace
Automatic YAML frontmatter completion: When pushing, the CLI automatically checks SKILL.md and fills in name/description if missing — no manual upkeep required.
teamai status # Current scope, last sync time, resource statsRoles control which skills each member sees. Admins define roles via manifest/roles.yaml; once a member selects their role, pull only syncs skills from the matching namespace.
Admin operations:
# Initialize (interactively create the manifest)
teamai roles init
# Add a role
teamai roles add devops --namespaces common,infra -d "Infrastructure team"
# Update a role (add/remove namespaces, change description)
teamai roles update hai --add-namespaces infra
teamai roles update hai --remove-namespaces legacy -d "New description"
# Remove a role
teamai roles remove devops
# Preview changes
teamai roles add test --namespaces common,test --dry-runThe commands above automatically push a branch and create an MR; the change takes effect team-wide once merged.
Member operations:
# View available roles
teamai roles list
# Choose your own role
teamai roles set hai
teamai roles set hai --add pm # Primary role hai + additional role pm
# Sync resources for the new role
teamai pullSafe degradation: If an admin removes a role that a member is still configured with,
pullwon't error out — it falls back to a full sync and prints a warning prompting the member to choose a new role.
# Create a skill
mkdir -p ~/.claude/skills/my-deploy-helper
cat > ~/.claude/skills/my-deploy-helper/SKILL.md << 'EOF'
# Deploy Helper
When the user requests a deployment, follow these steps:
1. Check that the current branch is master
2. Run tests `npm test`
3. Build `npm run build`
4. Deploy `./deploy.sh`
EOF
# Push to the team (YAML frontmatter is auto-completed)
teamai push
# Push to a specific role namespace
teamai push --role pmFrontmatter auto-completion: When pushing, the CLI checks the
SKILL.mdYAML frontmatter (name/description) and, if missing, derives and fills it in automatically from the directory name and content. You can also add more precise frontmatter yourself:--- name: my-deploy-helper description: Automated skill for helping the team deploy services tags: [deploy, automation] ---
With role-based skills enabled, the push target directory becomes:
- Default:
skills/<primaryRole>/<skill-name>/ - Explicit override:
skills/<role>/<skill-name>/(via--role)
# Create a rule
cat > ~/.claude/rules/code-review-guide.md << 'EOF'
# Code Review Guidelines
- All functions must have JSDoc comments
- `any` type is not allowed
- Test coverage must be at least 80%
EOF
# Push
teamai pushAdmins can set enforced rules in
teamai.yaml(sharing.rules.enforced), which members cannot delete.
teamai env add API_ENDPOINT https://api.example.com --description "Team API endpoint"
teamai env list
teamai pushPlace documentation in the team repo's docs/ directory; after pushing, team members will automatically receive it on their next pull.
Declare each server once in the team repo's mcp/mcp.yaml. On teamai pull it is written into every installed tool's own MCP config, translated into that tool's native format.
servers:
- name: gpu-analysis
description: GPU inventory and pricing queries
transport: http # stdio | http | sse
url: https://example.com/api/mcp
headers:
Authorization: Bearer ${GPU_ANALYSIS_TOKEN}
timeout: 600000
- name: local-formatter
transport: stdio
command: npx
args: ['-y', '@acme/formatter-mcp']
env:
FORMATTER_MODE: strict
requires: [npx] # skipped with a hint when npx is absent
tools: [claude, cursor] # optional; default is every capable toolWhere each tool's servers land:
| Tool | User scope | Project scope |
|---|---|---|
| claude | ~/.claude.json |
<project>/.mcp.json |
| cursor | ~/.cursor/mcp.json |
<project>/.cursor/mcp.json |
| codebuddy / workbuddy | ~/.<tool>/mcp.json |
<project>/.<tool>/mcp.json |
| codex | ~/.codex/config.toml |
not supported |
Codex supports stdio and http; sse is skipped. Ownership is tracked in ~/.teamai/managed-mcp.json — hand-added servers are left alone; name collisions skip unless --force.
Secrets. Write ${VAR}, never a literal, in mcp.yaml. Values resolve from the environment, then from env/env.yaml → ~/.teamai/env. Unresolved variables skip the server with a hint.
teamai resolves every ${VAR} to its value and writes it verbatim into each tool's config (new files are created 0600). It does not rely on any tool's own env-var expansion: that expansion is fragile — most decisively, IDEs launched from the GUI (Dock/Launchpad) never inherit your shell's exported variables, so a ${VAR} placeholder expands to empty and the server 401s. Resolving to plaintext makes the token present no matter how the tool is started.
⚠️ The resolved token lands on disk. Project-scope MCP configs (.mcp.json,.cursor/mcp.json,.codebuddy/mcp.json,.codex/config.toml) then contain the literal secret — add them to.gitignoreand never commit them.
Claude Code may show project .mcp.json servers as pending approval until you accept them once in an interactive session.
teamai mcp list # servers, secret status, and where they are installed
teamai mcp inject # apply now; --dry-run to preview, --force to override collisions
teamai mcp remove # remove every teamai-managed serverThe AI tracks your coding sessions via Hooks. When a session ends (the Stop hook), the system scores it by friction — whether you interrupted or corrected the AI, denied a tool call, or the AI had to retry failing tools. A long-but-routine session (many tool calls, no friction) won't trigger; only a session where you actually hit a problem does. If it qualifies, the AI automatically reminds you:
Recommend running /teamai-share-learnings to share your learnings
Using the built-in /teamai-share-learnings skill, the AI will automatically summarize the session's learnings and contribute them to the team knowledge base. Each session is prompted at most once.
You can also specify a file manually:
teamai contribute --file /tmp/session.md
teamai contribute --file /tmp/session.md --scope projectteamai recall "API timeout"
teamai recall "GPU out of memory"- Supports mixed-language search
- Automatically merges the knowledge bases of both user + project scope, labeling results
[user]/[project]by source - Consulted knowledge is automatically upvoted, surfacing high-quality docs to the top
- A lightweight relevance precheck is available via
teamai recall --check "<keywords>", which printsRELEVANT score=<n>orNOT_RELEVANT score=<n>without reading files or upvoting — the recall subagent uses it to skip retrieval on unrelated tasks
The Recall feature is controlled by a two-tier configuration — admins set the team default, and members can override it locally:
| Tier | Config file | Field | Description |
|---|---|---|---|
| Team default | teamai.yaml |
sharing.recall.enabled |
true / false (default false) |
| User override | ~/.teamai/config.yaml |
recallEnabled |
true / false, takes priority over the team default |
| Environment variable | shell | TEAMAI_RECALL_DISABLED=1 |
Force-disables all recall hooks (emergency kill switch) |
teamai recall enable # Enable recall, deploy the subagent and rules
teamai recall disable # Disable recall, remove the subagent and rules
teamai recall status # View the current effective status (team default + user override)When disabled, teamai pull skips deploying the recall subagent, the recall rules injection block, and the TodoWrite reminder hook. Manually running teamai recall <query> to search is not affected by this switch.
TeamAI supports injecting your team's culture into AI tools, so your AI coding assistant is aware of your team's culture, values, and coding standards in every session.
The admin creates a culture.md file at the root of the team repo:
---
company:
name: Acme Corp
mission: Build great things
vision: A world where AI helps everyone
values:
- Innovation
- Integrity
- User First
team:
name: Platform Team
mission: Enable developers to ship faster
goals:
- Ship v2.0 by Q2
- Improve test coverage to 90%
---
## Coding Standards
- All PRs must have at least one reviewer approval
- Direct pushes to master are prohibited
- Test coverage must be at least 80%
## Collaboration Norms
- Use conventional commits format
- PR descriptions must include ## Summary and ## Test Plan
- Major changes require a design doc first| Field | Type | Description |
|---|---|---|
company.name |
string (required) | Company name |
company.mission |
string | Company mission |
company.vision |
string | Company vision |
company.values |
string[] | Company core values |
team.name |
string (required) | Team name |
team.mission |
string | Team mission |
team.goals |
string[] | Team goals |
The markdown body after the frontmatter becomes the body content of the team culture guidance, injected as a whole into CLAUDE.md.
Team repo
├── culture.md ← Maintained by admin
├── skills/
├── rules/
└── ...
teamai pull
│
▼ Parse culture.md
│ ├─ frontmatter → structured company/team info
│ └─ body → team culture guidance body
│
▼ Compile into a CLAUDE.md injection block
│
▼ Inject into each AI tool's CLAUDE.md
├─ ~/.claude/CLAUDE.md
├─ ~/.cursor/CLAUDE.md
└─ ...
The injected content sits between the <!-- [teamai:culture:start] --> and <!-- [teamai:culture:end] --> markers, is automatically updated on every pull, and does not affect any other content in the file.
After pulling, you can view the AI tool's CLAUDE.md directly:
teamai pull
cat ~/.claude/CLAUDE.mdYou'll see an injection block like this:
<!-- [teamai:culture:start] -->
<!-- DO NOT EDIT: This section is auto-managed by teamai -->
## Team Culture (teamai)
## Company: Acme Corp
**Mission:** Build great things
**Vision:** A world where AI helps everyone
**Values:** Innovation, Integrity, User First
## Team: Platform Team
**Mission:** Enable developers to ship faster
**Goals:**
- Ship v2.0 by Q2
- Improve test coverage to 90%
## Coding Standards
- All PRs must have at least one reviewer approval
...
<!-- [teamai:culture:end] -->When using teamai init --http <baseUrl>, the endpoint must implement the following APIs (authenticated via Authorization: Bearer <api-key>):
| Endpoint | Method | Purpose |
|---|---|---|
{baseUrl}/api/local-agent/report |
POST | Session start: upsert agent + installed skills |
{baseUrl}/api/local-agent/sync |
POST | Report status + return pending skill commands |
{baseUrl}/api/local-agent/commands/ack |
POST | Acknowledge a single command ({ id, status, error }) |
POST /api/local-agent/sync returns pending commands:
{
"ok": true,
"commands": [{ "id": 1, "type": "install_skill", "skill_slug": "x", "skill_version": "1.0.0", "download_url": "https://signed-url/..." }]
}The backend may also push an uninstall_teamai command to remove the local agent. It carries a cmd (a single teamai subcommand) that runs once on the client, with the result reported back through the same ack channel:
{ "id": 42, "type": "uninstall_teamai", "cmd": "teamai uninstall --force --agent codebuddy" }Security boundary for the executed cmd:
- teamai subcommands only — the first token must be exactly
teamai; anything else is rejected (ackedfailed) and never executed. There is no arbitrary-shell surface. - No shell — the command is run via
execFilewith the current Node binary and teamai entry script, so shell metacharacters (;,|,&,$, …) are treated as literals and there is no PATH dependency (works inside sandboxes with a bundled Node). - On by default — like install/uninstall commands, it runs automatically. Set
TEAMAI_DISABLE_REMOTE_CMD=1on the client to reject it (ackedfailedwithremote cmd disabled by client). - Timeout — a hung command is killed after 120s and acked
failed.
The backend may also push install_hook_rule / uninstall_hook_rule commands to remotely
manage a session hook in the current reporting tool's settings, keyed by slug. The result is
reported over the same ack channel:
Rules for agent hooks:
- Current tool only — the hook is written to the tool that is reporting (e.g. under Claude ⇒
only
.claude/settings.json). Other tools are never touched. - Supported tools —
claude/codex/workbuddy/codebuddy(plus their internal variants). Cursor and OpenClaw-family tools are rejected → ackedfailed(unsupported tool). - Event whitelist —
SessionStart/UserPromptSubmit/PreToolUse/PostToolUse/Stop. Any other event → ackedfailed(unsupported event). - Optional
matcher— a tool-name filter forPreToolUse/PostToolUse; defaults to*(all tools) when omitted. - Default timeout 10s when
timeoutis omitted; the backend value is honored when present. - Idempotent — re-installing the same
slugreplaces the existing hook rather than duplicating it;uninstall_hook_rulefor a missingslugis ackedsuccess. - Isolation — agent hooks use a dedicated
[teamai:agent-hook:<slug>]marker, so a team pull never deletes them and installing one never disturbs built-in or team hooks. - Teardown — agent hooks are removed by
uninstall_hook_rule,teamai source remove, andteamai uninstall(no residue in any tool's settings). - Kill-switch — an agent hook is a backend-supplied command the tool auto-runs on its events,
so it shares the
uninstall_teamaitrust model: settingTEAMAI_DISABLE_REMOTE_CMD=1on the client rejectsinstall_hook_rule/uninstall_hook_ruletoo (ackedfailed). - Codex matching — codex settings carry no description field, so codex agent hooks are matched
by their exact command and the local-agent manifest is the authoritative record for their
teardown. Backends should use a unique
cmdper codexslugso replace/remove stay precise.
Configurable environment variables:
| Variable | Purpose |
|---|---|
TEAMAI_API_TOKEN |
API key (alternative to --token) |
TEAMAI_REPORT_ENDPOINT |
Reporter base URL (defaults to the --http address) |
TEAMAI_REPORT_PATHS |
JSON { "report", "sync", "ack" }, overrides the three paths |
TEAMAI_REPORT_AGENTS |
Comma-separated list of agents that report (default workbuddy,codebuddy) |
TEAMAI_SKILL_DOWNLOAD_HOSTS |
Allowlist of hosts for skill download_url (empty = allow all) |
TEAMAI_ALLOW_SANDBOX_REPORT |
Set to 1 to force report/sync inside a CloudStudio sandbox (see note below) |
TEAMAI_DISABLE_REMOTE_CMD |
Set to 1 to reject server-pushed uninstall_teamai, install_hook_rule, and uninstall_hook_rule commands (they are acked failed) |
Privacy: The install path and machine id are only hashed locally to derive
local_agent_id— they are never reported.
CloudStudio sandbox: When WorkBuddy runs teamai hooks inside a CloudStudio container, that container has a different machine id than the macOS host and would report a duplicate agent card. The duplicate report is therefore skipped automatically inside a CloudStudio sandbox (sync still runs, so pushed commands are still received) — detected via
X_IDE_IS_CLOUDSTUDIO=TRUEor the/var/run/cloudstudiodirectory. SetTEAMAI_ALLOW_SANDBOX_REPORT=1to opt back in if you run teamai exclusively inside CloudStudio.
teamai import parses a source code repo into a structured knowledge graph (stored under the team repo's teamwiki/ directory), enabling structure-aware knowledge retrieval:
# Extract from a local directory
teamai import --dir /path/to/project
# Import from a remote repo
teamai import --from-repo https://github.com/org/repo
# Bulk-import all repos under an organization
teamai import --from-org myorg
# Bulk-import from an allowlist
teamai import --from-repo-list repos.yaml
# Extract learnings from a merged MR/PR
teamai import --from-mr https://github.com/org/repo/pull/123
# Import docs from iWiki
teamai import --from-iwiki 12345
# Incremental mode (skip unchanged files)
teamai import --from-repo https://github.com/org/repo --incremental
# Extract structure only, skip AI enrichment
teamai import --from-repo https://github.com/org/repo --skip-enrichThe graph stores components, interfaces, configs, and cross-repo dependencies. teamai recall uses the graph for BM25 + graph-boosted ranking.
# Graph health check
teamai codebase --lintteamai dashboard # Start the web dashboard (default port 3721)
teamai dashboard --port 8080View team members' AI coding session status in real time.
Each session card shows a ⚠ N badge, counting the number of human interventions in that conversation — fewer interventions means the agent is better at getting things right on the first try. Hover to see a breakdown; each of the three signal types counts once:
| Type | Meaning | Data source |
|---|---|---|
interrupt |
User pressed ESC to interrupt the agent mid-execution | An interrupted turn in the transcript |
toolReject |
User rejected a tool call (permission deny) | A tool_result marked as rejected in the transcript |
correction |
Within 60s after the agent stops, the user submits a follow-up prompt containing a correction keyword ("not right" / "redo" / "wrong" / etc.) | The stop → prompt_submit event pattern |
Privacy: only counts are tracked — no prompt or transcript text is ever stored.
Intervention data is automatically aggregated and reported to the team's stats/<user>.yaml during teamai pull, and shown in the "Session Autonomy" leaderboard of teamai digest, with team averages and per-person intervention rate rankings — useful for verifying whether a skill/rule reduces intervention rates after rollout. Tools without a transcript (e.g. Cursor) degrade gracefully, tracking only correction.
Each session card also shows two badges:
| Badge | Meaning | Data source |
|---|---|---|
💬 N |
The number of human conversation turns in the session (how many prompts were sent) | Count of UserPromptSubmit events |
⛁ X |
The session's cumulative token usage (hover to see input / output / cache read / cache write breakdown) | Claude Code transcript's message.usage (deduplicated by message.id to avoid double counting) |
Privacy: only turn counts and token counts are tracked — no prompt or transcript text is ever stored.
These two metrics are likewise aggregated into stats/<user>.yaml (as prompts and tokens fields) during teamai pull, and shown in the "Conversation Volume & Token Usage" section of teamai digest, with team-wide totals, bucketed token totals, and per-person token usage rankings. Tools without transcript access (e.g. Cursor) degrade gracefully: turn counts are still tracked, while tokens show as 0 / N/A.
teamai session save folds the dashboard's existing per-session event stream (tool sequence, prompt turns, interventions) into a compact, privacy-scrubbed markdown summary — no LLM call, no new collection path.
teamai session save # record the most-recent session locally
teamai session save --session-id <id> # record a specific session
teamai session save --push # also push a "valuable" session to the team repo
teamai session save --push --force # push even a trivial session
teamai session save --push --include-prompt # also include the (redacted) first-ask lineLocal (always): appends to ~/.teamai/session-logs/<year-month>.md. Idempotent per session (a session already recorded that month is skipped), and logs older than 90 days are pruned automatically.
Team (--push, opt-in): commits the summary directly (no PR) to sessions/<user>/<year-month>.md in the team repo — the exact path teamai digest reads, so the session shows up under Session Highlights. Only a valuable session is pushed by default: one that shows friction (an interrupt / tool-reject / correction) or substantial tool use (≥ 3 distinct tools). Trivial sessions stay local unless you pass --force. On a read-only (HTTP-mode) team, --push fails gracefully and the local log is still kept.
Privacy: the team-pushed payload is counts + tool names only by default. The first-ask prompt line is opt-in via
--include-prompt, and even then it is run through the same secret redaction (ghp_…→<REDACTED:…>) used elsewhere. Local logs keep the redacted first-ask line since they never leave your machine.
Hooks automatically injected by teamai init:
| Hook Event | Action |
|---|---|
SessionStart |
Auto pull + report session start |
PostToolUse |
Skill tracking + knowledge contribution detection + dashboard reporting |
UserPromptSubmit |
Slash command tracking |
Stop |
CLI update check + report session end |
teamai hooks inject # Re-inject
teamai hooks remove # RemoveBoth commands only touch tools you actually have installed (i.e. whose ~/.<tool>/ root directory already exists). They never create root directories for tools listed in toolPaths but not installed.
A team can declare custom hooks in the repo's hooks/hooks.yaml; teamai pull automatically distributes them to all members' AI tools:
hooks:
- id: block-secret
description: Scan for secrets before commit
event: PreToolUse
matcher: Bash
command: 'bash -lc "~/.teamai/team-scripts/scan-secret.sh" || true'
timeout: 15
tools: [claude, cursor]
builtin:
disabled: [Hook dispatch post-tool-use TodoWrite]
overrides:
Hook dispatch stop: { timeout: 20 }| Field | Description |
|---|---|
id |
Unique identifier, ^[a-z0-9-]+$ |
event |
Claude PascalCase event name (shared across tools) |
matcher |
Optional tool matcher |
tools |
Optional list of target tools (default = all tools that support hooks) |
builtin.disabled |
List of disabled built-in hooks |
builtin.overrides |
Only the timeout of a built-in hook can be overridden |
Security governance:
sharing.hooks.autoApply: false(teamai.yaml): on pull, only prompts — requires manually confirming withteamai hooks injectsharing.hooks.requireTeamScripts: true: rejects any hook whose command isn't under~/.teamai/team-scripts/TEAMAI_HOOKS_DISABLED=1: disables all team hooks locally (built-in hooks are unaffected)
The team repo can maintain custom subagent definitions under an agents/ directory (one *.md file per agent):
team-repo/
agents/
code-reviewer.md # Team custom subagent
.removed # tombstone (auto-managed by teamai remove agents <name>)
teamai pull copies these into each Tier-1 tool's agents/ directory (e.g. ~/.claude/agents/). The CLI's built-in teamai-recall.md is deployed alongside team agents but is not uploaded by teamai push.
teamai doctor # Config diagnostics
teamai stats # Skill usage stats
teamai update # CLI update
teamai remove skills <name> # Remove a resource
teamai remove rules <name>
teamai remove wiki <name>Auto-update runs in the Stop hook and is controlled by two tiers:
| Tier | File | Field | Value |
|---|---|---|---|
| Team default | teamai.yaml |
autoUpdate |
true (default) / false |
| User override | ~/.teamai/config.yaml |
updatePolicy |
auto / prompt / skip |
The user-level updatePolicy always takes priority over the team-level autoUpdate.
teamai ci extract-mr plugs into your CI pipeline, automatically extracting knowledge from every MR/PR:
# Comment mode: post suggestions as comments (runs when the MR/PR is opened/updated)
teamai ci extract-mr --url "$MR_URL" --mode comment --individual-comments
# Write mode: after merge, write approved suggestions into the knowledge base
teamai ci extract-mr --url "$MR_URL" --mode write --team-repo ./team-repo --individual-commentsWorkflow:
- MR opened/updated → CI triggers
--mode comment, extracts knowledge suggestions and posts them as MR comments - Reviewer reviews the comments, marking unwanted suggestions as rejected (GitHub 👎 / TGit ☝️)
- MR merged → CI triggers
--mode write, writing non-rejected suggestions into the team knowledge repo
Ready-to-use templates:
examples/ci/github-actions-mr-extract.yml(GitHub Actions)examples/ci/coding-ci-mr-extract.yaml(Coding CI / TGit)
teamai source lets you subscribe to other teams' public skill repos, automatically fetching the latest skills on pull:
# Add a subscription source
teamai source add https://github.com/other-team/teamai-public.git --name other-team
# List subscriptions
teamai source list
# Browse a subscription's skills
teamai source browse other-team
# Remove a subscription (also cleans up its skills)
teamai source remove other-teamA subscription source's skills are automatically synced locally on teamai pull, coexisting with the team's own skills. Configuration is stored in the sources field of the local config.yaml.
In addition to a git subscription source, you can attach an HTTP source on top of an existing git main repo — useful for server-managed skill delivery:
# Attach an HTTP source (the git main repo is unaffected)
teamai source add-http https://your-team-host/api --token <api-key>
# View it (shown under "HTTP source")
teamai source list
# Detach and uninstall its resources
teamai source remove-httpAn HTTP source reports status and pulls skill commands via hook dispatch on every session. Only one HTTP source is supported per install. If the main repo is already in HTTP mode (init --http), add-http is unavailable (the main repo already occupies the HTTP config).
team: my-team
description: Team AI resource repo
repo: https://github.com/group/repo.git
provider: github
# scope: ignored if present — local install location is set by `teamai init --scope`
reviewers:
- reviewer1
sharing:
rules:
enforced: [code-review-guide]
docs:
localDir: ./.teamai/docs
env:
injectShellProfile: truerepo:
localPath: /path/to/.teamai/team-repo
remote: https://github.com/group/repo.git
username: your-name
updatePolicy: auto
scope: project # project (default from init) or user
projectRoot: /path/to/project # project scope onlyteamai uninstall intelligently cleans up all teamai-managed resources, preserving anything you created yourself.
# Preview what will be removed (no actual changes)
teamai uninstall --dry-run
# Interactive confirmation
teamai uninstall
# Skip confirmation and uninstall directly (for scripts/CI)
teamai uninstall --force
# Uninstall only one tool's resources (mirrors `init --agent`)
teamai uninstall --agent claudeWhat gets removed:
- teamai hooks in AI tool settings
- The teamai rules block in CLAUDE.md (your own content is preserved)
- Team-synced skills (your own skills are preserved)
- Team-synced rules
- The env block in your shell profile
- The
~/.teamai/directory
--agent <tool> removes only that tool's teamai resources (hooks, CLAUDE.md block, skills, rules, built-in agents). The tool name is a key of toolPaths (e.g. claude, codex, codebuddy) and is matched case-insensitively. An unknown tool name aborts without deleting anything, lists the available tools, and exits with a non-zero status.
Shared resources (the env block, docs directory, and ~/.teamai/) are removed only when the target itself has teamai resources AND is the last tool still using teamai — otherwise they are kept for the remaining tools. (So targeting a tool that has no teamai resources of its own is a no-op and leaves shared resources in place, even if it happens to be the only tool.)
The exclusion is durable: uninstall --agent <tool> drops the tool from enabledAgents and records it in disabledAgents, so a later pull (or another tool's session-start hook) will not resurrect its skills, rules, agents, CLAUDE.md block, or hooks. Running init --agent <tool> again clears the exclusion and re-enables sync for that tool.
To rejoin after uninstalling:
teamai init --repo <group>/TeamAi-<team> --scope user --role <role_id> --force
teamai pullQ: Can user scope and project scope coexist?
Yes. pull pulls both scopes in sequence, and recall merges search results across both scopes' knowledge bases. They don't conflict with each other.
Q: teamai init says it's already initialized?
In interactive mode, you'll be asked whether to overwrite — type y to confirm. You can also use --force to skip the confirmation:
teamai init --repo <group>/<repo> --forceQ: Hooks aren't firing automatically?
teamai doctor # Diagnose
teamai hooks inject # Re-injectQ: push says "no new resources detected"?
push only detects new or modified resources. If nothing changed, there's nothing to push.
Q: How do I delete resources that were already pushed?
teamai remove skills <name>
teamai remove rules <name>Repo: https://github.com/Tencent/teamai-cli Feedback: file an Issue in the repo