The `.team/` folder
A repo with a teamctl team carries a .team/ directory at its root, the same way a git repo carries .git/. teamctl walks up from the current working directory looking for the nearest .team/team-compose.yaml, so every subcommand “just works” wherever you are inside the tree.
Layout
my-repo/├── .team/│ ├── team-compose.yaml # global: broker, supervisor, hitl, …│ ├── projects/│ │ └── <id>.yaml # one or more│ ├── roles/│ │ └── <agent>.md # role prompts referenced by agents│ ├── runtimes/ # optional overrides for shipped runtimes│ ├── .env # gitignored — secrets and chat-ids│ ├── .env.example # checked-in template│ ├── .gitignore # auto-generated│ └── state/ # gitignored — mailbox + rendered artifacts└── … rest of the repoDiscovery
$ pwd/Users/me/work/my-repo/src/deep/nested$ teamctl status…shows agents, even though we're four levels deepResolution order:
--root <path>flag.TEAMCTL_ROOTenv var.- Active context (see
teamctl context). - Walk up from CWD looking for
.team/team-compose.yaml. - Walk up looking for a flat
team-compose.yaml(legacy fallback; prints a deprecation warning).
Multiple teams on one machine
Use teamctl context:
$ teamctl context ls* newsroom /Users/me/work/news/.team startup /Users/me/work/startup/.team
$ teamctl context use startup$ teamctl status # now shows the startup teamteamctl up auto-registers the current root as a context the first time it runs.
Bootstrapping a new team
teamctl init # interactive (default: Guided)teamctl init --template essentials --yesteamctl init --template blank --yes --project my-thingTemplates are baked into the binary — init works offline.
Env / secrets
.team/.env is the only place secrets live. .env.example lists every variable the compose tree references with placeholder values; commit it. .env itself is gitignored.
$ teamctl envVAR STATE REFERENCED FROMTEAMCTL_TG_PM_TOKEN set managers.pm.interfaces.telegram.bot_token_envTEAMCTL_TG_PM_CHATS UNSET managers.pm.interfaces.telegram.chat_ids_env
$ teamctl env --doctor1 required env var(s) unsetteamctl up invokes --doctor implicitly and refuses to start when anything required is missing.
Inspection
teamctl status # table: agent, runtime, state, inbox, last activityteamctl mail <agent> # this agent's inboxteamctl mail --all # every agent's inbox depth + sampleteamctl tail <agent> -f # live message streamteamctl inspect <agent> # full snapshot of one agentteamctl logs <agent> # tmux pane scrollbackteamctl attach <agent> # tmux attach (read-write — keystrokes reach the agent)teamctl attach <agent> --ro # read-only: observe without sending inputteamctl exec <agent> -- ls # run a command in the agent's CWD with its envteamctl shell <agent> # interactive shell with the agent's env loadedteamctl approvals # pending HITL requeststeamctl bridge ls # cross-project bridgesThe old status, pending, bridge list, etc. commands still work — they’re aliases.
Migrating from a flat layout
mkdir .teamgit mv team-compose.yaml projects roles runtimes .team/ # whatever existsAnything that used to live alongside team-compose.yaml moves into .team/. State directories (state/) and .env files should already be gitignored at the repo root — recreate the gitignore inside .team/ (teamctl init provides one).