Creating a team
A team is a reusable bundle of AI agents, skills, and rules that anyone can install with atl install. This page walks through it end to end — from an empty directory to a catalogued team others can pull by handle.
What a team is (and isn't)
A team is just a Git repository with a team.json file and some Markdown. When someone runs atl install <handle>/<team>, the CLI resolves the handle against the GitHub-backed catalog, fetches the repo as an ephemeral tarball, and copies the team's agents/, skills/, and rules/ into the target's .claude/ directory. That's it — no plugin system, no JavaScript runtime, no custom binaries. The whole thing is text files and copies.
A team can be:
- One agent (a single Markdown file with instructions Claude follows)
- One or more skills (slash commands that Claude can invoke)
- Rules (always-loaded instructions that shape behavior)
- Any combination of the above
A team becomes installable once it's catalogued: tag its public GitHub repo with the atl-team topic (or run atl publish from it), and the generated index picks it up. From then on anyone can atl install <handle>/<team> — where the handle is the repo's GitHub owner. There is no registry repo and no submission PR.
The full walk-through
Let's build a small real team from nothing. You'll create a my-team repo, add one agent, and get it ready to install.
Step 1 — Create the team repo
mkdir ~/projects/my-team
cd ~/projects/my-team
git init -b mainThe folder name doesn't have to match the team's catalog name — that's set in team.json below.
Step 2 — Write team.json
This is the team's manifest. Minimum viable:
{
"schemaVersion": 1,
"name": "my-team",
"version": "0.1.0",
"description": "Opinionated setup for Next.js + Tailwind projects.",
"author": { "name": "Your Name", "url": "https://github.com/you" },
"license": "MIT",
"keywords": ["nextjs", "tailwind", "typescript"],
"agents": [
{ "name": "web-agent", "description": "Reviews and builds Next.js pages." }
],
"skills": [],
"rules": []
}Full field reference: team.json.
Gotchas worth calling out:
nameis the team's short-name. Once set, don't change it — users refer to it. Must be kebab-case (lowercase letters, digits, hyphens).versionis SemVer (major.minor.patch). Bump it when you ship changes —atl updateuses this to decide whether to pull.authoris an object, not a string. At minimum{ "name": "Your Name" }. A plain string like"author": "You"isn't a parse error — the install parser models noauthorfield, so it's silently ignored — but use the object form for clarity and future compatibility.agentsis an array of metadata, not agent content. The actual agent Markdown lives underagents/<name>/agent.md(see Step 3).
Step 3 — Add your agent
Every agent the team.json declares needs a directory under agents/ using the children pattern:
my-team/
├── team.json
└── agents/
└── web-agent/
├── agent.md ← short: identity, scope, principles (<300 lines)
└── children/ ← optional: deep-dive topics
├── routing.md
├── data-fetching.md
└── testing.mdagent.md is the entry point — Claude reads it on every invocation. Keep it short. Put detailed patterns in children/*.md; the agent's ## Knowledge Base section can link to them and Claude reads them on-demand.
Minimum agent.md:
---
name: web-agent
description: "Reviews and builds Next.js pages."
---
# Web Agent
## Identity
I build and review Next.js pages for this project.
## Area of Responsibility (Positive List)
I ONLY touch:
- `app/` — Next.js App Router pages + layouts + routes
- `components/` — shared UI primitives
- `lib/` — data-fetching + utility functions
I do NOT touch:
- `api/` — that's the backend's concern
- Build config (`next.config.js`, `tsconfig.json`) without explicit approval
## Core Principles
1. Server components by default; client components only when interactive.
2. Co-locate styles with their component; no global CSS.
3. Loading UI for every async boundary.That's a functioning agent. Add more detail in children/ as the agent grows.
Deep dive
The children pattern is explained in core/rules/agent-structure.md and summarized in Children + learnings. Key idea: agent.md stays short, topic-specific detail goes in children/*.md with one topic per file.
Step 4 — Commit
Commit your work — atl installs from a committed ref, not your working tree:
git add .
git commit -m "feat: initial team"Step 5 — Publish so others can install it
atl install resolves handles against the catalog, so a team has to be catalogued before anyone (including you) can install it by handle. Push the repo to a public GitHub repo and tag it with the atl-team topic:
# Push to a public GitHub repo under your account or org:
gh repo create you/my-team --public --source=. --push
# Tag it so the catalog indexes it:
gh repo edit you/my-team --add-topic atl-teamAn hourly index job discovers public atl-team-tagged repos and opens a catalog-refresh PR against the catalog; once a maintainer merges it, your team is discoverable as you/my-team — so expect a delay for that review, not instant availability.
Step 6 — Install it
mkdir /tmp/demo-app && cd /tmp/demo-app
atl install you/my-team
# → atl: installed you/my-team@0.1.0 at project scope
atl list
# project:
# you/my-team@0.1.0
ls .claude/agents/web-agent/
# → agent.mdIf the output matches, your team is installed. The agent is now available to Claude in /tmp/demo-app/.
The team installs at whatever scope its publisher declared (project by default — see the scope field in team.json). Override per-install with --global or --project.
Step 7 — Iterate
Edit files under ~/projects/my-team/, bump the version in team.json, then commit and push. The catalog reindexes to the new version, and any project that has the team installed picks it up with atl update:
cd ~/projects/my-team
vim agents/web-agent/agent.md # or any edit
# bump "version" in team.json, then:
git commit -am "tweak web-agent guidance"
git push
cd /tmp/demo-app
atl update
# → atl re-fetches the published version, refreshes unmodified copiesatl update refreshes copies you haven't modified and leaves your local edits in place.
Releases pin installs
If your repo has GitHub Releases, the catalog pins installs to the latest release's tag — cut a new GitHub Release (not just a git tag) for each version you ship. A plain push to main only reaches installers while the repo has no releases.
Step 8 — (Optional) Add skills and rules
Skills are slash commands. Each gets a skills/<skill-name>/SKILL.md with frontmatter:
---
name: lint-page
description: "/lint-page <path> — run the project's lint config against a Next.js page file."
argument-hint: "<path-to-page>"
---
# /lint-page Skill
## Purpose
Lint a single Next.js page file using the project's ESLint + Prettier.
## Flow
1. Validate the path exists and matches `app/**/*.tsx` or `pages/**/*.tsx`.
2. Run `npm run lint -- --file <path>`.
3. Parse the output; if violations exist, print them with file:line:column citations.
4. Offer to auto-fix where safe.Declare it in team.json:
"skills": [
{ "name": "lint-page", "description": "/lint-page <path> — run lint against a page file." }
]Rules are always-loaded Markdown files that shape Claude's behavior. Put them at rules/<rule-name>.md:
# React 19 defaults
- Server components unless interactivity is needed
- Never use `"use client"` at the top of a shared lib
- `useActionState` replaces manual form-state boilerplateDeclare:
"rules": [
{ "name": "react-19-defaults", "description": "Default to server components; avoid client boundary creep." }
]After any change — agents, skills, or rules — bump the version, commit, and push, then atl update to pick it up.
Step 9 — Where to go next
- Add a scaffolder skill. If your team is meant to spin up new projects, add a
/create-new-projectskill. See Scaffolder spec. - Depend on another team. If your team builds on someone else's, declare it under
dependenciesinteam.json—atl installpulls the dependency alongside yours. - Earn the verified badge. Teams reviewed by AgentTeamLand maintainers (and everything under
agentteamland/*) show a[verified]badge inatl search. Its absence just means a team is self-published.
Team layout reference
my-team/
├── team.json ← manifest (required)
├── README.md ← team docs (strongly recommended)
├── LICENSE ← usually MIT
│
├── agents/ ← one dir per agent
│ ├── web-agent/
│ │ ├── agent.md ← short: identity + scope + principles + knowledge-base index
│ │ └── children/ ← optional: deep-dive topics
│ │ ├── routing.md
│ │ ├── data-fetching.md
│ │ └── testing.md
│ └── backend-agent/
│ ├── agent.md
│ └── children/ ...
│
├── skills/ ← one dir per skill
│ ├── lint-page/
│ │ └── SKILL.md ← frontmatter (name, description, argument-hint) + body
│ └── run-e2e/
│ └── SKILL.md
│
└── rules/ ← one .md per rule (flat, not dir)
├── react-19-defaults.md
└── file-naming.mdatl copies every file under the team's asset directories (agents/, skills/, rules/, plus knowledge/, backends/, scripts/, packs/) into the consumer's .claude/. The team.json agents[]/skills[]/rules[] arrays are catalog metadata — they describe the team in atl search, they do not decide what gets copied. Only files outside those asset directories (team.json, README, LICENSE) stay behind.
How install works under the hood
When someone runs atl install you/my-team:
- Resolve. The handle is looked up in the GitHub-backed catalog (generated from public
atl-team-tagged repos). A team published from a monorepo subpath resolves to that subpath; a standalone team resolves to its own repo root. - Fetch. The team is downloaded as a ref-pinned HTTPS tarball into a temp directory — no
gitbinary required. The temp directory is deleted after the install. - Validate.
atlparsesteam.jsonand confirms it has aname. It does not individually check declared agents/skills/rules against disk — the install only fails here if the team ships no asset files at all (team ships no installable assets). - Write. Agents, skills, and rules are copied into the scope's
.claude/—~/.claudefor a global install,<project>/.claudefor a project install. - Record. A per-team manifest at
<layer>/.atl/installed/<handle>__<name>.jsonrecords the source ref + per-file SHA-256 baselines thatatl update's auto-refresh andatl doctor's integrity check rely on.
There is no persistent clone cache and no separate ATL asset store — team assets live under .claude/; ATL's bookkeeping (catalog cache, learning queue, pins, install manifests) lives under ~/.atl and <project>/.atl.
Common pitfalls
Edited the team and ran atl update, no effect → Did you commit, bump the version, and push? atl update pulls the published version, so uncommitted (or unpushed) edits don't flow. Commit + bump + push, then atl update.
atl install says "team not found" → The handle isn't in the catalog yet. The repo must be public and tagged with the atl-team topic (or have had atl publish run against it). Try atl search to confirm what's indexed.
Want to delete a team cleanly → atl remove you/my-team removes the team's manifest-recorded files at the scope (project by default; --global for the global layer) and prunes any now-empty directories.
FAQ
Do I have to push my team anywhere to use it? Yes. atl install resolves handles against the GitHub-backed catalog, so a team needs a public repo tagged atl-team (or one atl publish has run against) before it can be installed by handle.
Can multiple teams coexist in one project? Yes — install as many as you like. Each team's items are copied into the shared .claude/ directory. If two teams declare an item with the same name, a first install lets the most recently installed team's file silently overwrite the earlier one — atl does not currently warn about the collision. On atl update (and re-installs) the fan-out discipline preserves a divergent local file at a colliding path rather than clobbering it, so the newcomer does not win there either. Prefer unique agent/skill/rule names to avoid the ambiguity.
What Markdown format does atl use? Plain Markdown with optional YAML frontmatter. Claude Code's agent and skill format is supported natively.
Can I version skills independently of the team? Not today. Versioning is team-level via team.json's version field.
Are there size limits? No hard limits. In practice team repos are under 10 MB. If you embed large binaries, mention it in the README so users know what they're pulling.
See also
- team.json field reference
- Scaffolder spec — adding
/create-new-projectskills atl install— full CLI referenceatl publish— circulate your team's accumulated gains upstream- Children + learnings — the agent/skill knowledge-base pattern