Installs into .claude/skills of the current project.
Are you the author of Getty Agent Team?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/getty-getty-agent-team)
---
name: getty-agent-team
description: "Use when a repo needs subagents — setting one up, wiring briefing, adding karr, or when .claude/agents is missing or drifted from the house pattern."
---
# Setup: agent team, skill base, house rules
Installs the setup Getty projects share. Nothing here is language-specific — the
Perl repos are just where it grew up.
**This skill is user-level only.** Its home is the shared library
([Getty/skills](https://github.com/Getty/skills), group `authoring/`); it runs
user-level, changes the target project, and is
done. Never install or copy it into a project — what Step 2 installs are the *briefed*
skills the agents need at runtime, not this one. A project's `.claude/` never mentions
`getty-agent-team`.
## The architecture in four sentences
1. **Skills are the knowledge base.** Conventions, architecture, tooling. One source of
truth per skill, installed into each repo that needs it (skill `skilletor`, from
[Getty/skilletor](https://github.com/Getty/skilletor)).
2. **Agents are roles, not knowledge.** An agent file is a role sentence + a
`briefing.skills` list + whatever is genuinely repo-specific and lives in no skill.
3. **`briefing` (plugin) force-loads those skills** into the subagent's context *before*
its first turn, and **hard-fails the spawn** if a name doesn't resolve. No
"MANDATORY: load X first" pleading, no silent skips.
4. **`.claude/rules/<prefix>-rules.md` carries discipline + the delegation lock** — it is
auto-loaded for the orchestrating main agent, which gets no briefing and therefore
must delegate instead of touching internals itself.
`karr` sits underneath as the coordination layer: a git-native board per repo, tickets
as the only legal cross-repo channel.
Bundled references — read the one you need, not all four:
| File | Holds |
|---|---|
| `references/agents.md` | role catalogue, frontmatter contract, agent templates |
| `references/rules-template.md` | the house-rules file, with the delegation lock |
| `references/karr.md` | karr install, `.karr`, `karr-foundation`, board discipline |
| `references/coordination-skill-template.md` | the `<prefix>-coordination` skill (families only) |
## Step 0 — prerequisites
```bash
ls -d ~/.claude/plugins/cache/*/briefing >/dev/null 2>&1 && echo "briefing installed: ok"
command -v karr >/dev/null && echo "karr: ok"
command -v skilletor >/dev/null && echo "skilletor: ok"
```
If `briefing` is missing, ask the user to run these two slash commands (Claude cannot
run them):
```
/plugin marketplace add Getty/marketplace
/plugin install briefing@getty
```
The same marketplace ships `skilletor` (`/plugin install skilletor@getty`),
which Step 2 needs. `Getty/briefing` as its own marketplace is the old route — an
existing install from it keeps working, don't churn it.
Without briefing the whole setup degrades to prompt-stuffing — do not proceed by
inlining skill bodies into agent files as a workaround.
## Step 1 — discover the project
Before writing anything, establish:
| Question | How |
|---|---|
| Build / test / lint commands | `dist.ini`, `Makefile`, `justfile`, `package.json`, `Cargo.toml`, `pyproject.toml`, CI config |
| Recursive test gotchas | do subdirs under `t/` / `tests/` exist that the naive runner skips? |
| Single repo or family? | sibling repos with a shared prefix → family, needs cross-repo routing |
| Existing skills to brief from | `.claude/skills/`, `~/.claude/skills/`, and what `skilletor available` offers |
| Existing conventions worth encoding | `CLAUDE.md`, `CONTEXT.md`, `docs/adr/`, the code itself |
| Release path | CPAN / npm / container / deploy-only — determines whether a release role is needed |
**Prefix**: everything is named `<prefix>-<role>` where `<prefix>` is the project or
family name in kebab-case. Family repos suffix the worker:
`<prefix>-worker-postgresql`. `karr-coordinator` is the one role that keeps its own name.
## Step 2 — settle the skill base first
`briefing` hard-fails on an unresolvable name, so every skill an agent lists must exist
before the agent file does. For each skill an agent needs:
- **Already shared** (the shared library, or another project that owns it) →
install it, never copy by hand: `skilletor install <name>@<source> --project`.
Wiring, sourcing and what to commit: skills `getty-skill-library` and `skilletor`.
**Never edit an installed SKILL.md** — the next sync overwrites it; change the
skill in its source.
- **Project-owned and missing** → write it (skill `skill-authoring`). The two that most
projects end up needing:
- `<prefix>-core` — architecture, vocabulary, the invariants an implementer must know.
- `<prefix>-coordination` — only for a repo *family*: who owns what, how tickets are
routed. Template: `references/coordination-skill-template.md`.
- **Genuinely repo-specific and tiny** → put it in the agent body instead of inventing a
skill for three lines.
Verify every name resolves before moving on:
```bash
for s in <skill> <skill> …; do
ls .claude/skills/$s/SKILL.md ~/.claude/skills/$s/SKILL.md 2>/dev/null | head -1 \
|| echo "MISSING: $s"
done
```
## Step 3 — write the agents
Role catalogue, frontmatter contract, model/tool choices and full templates:
`references/agents.md`.
Minimum viable team: **worker** (always) + **release-manager** if the project ships
anything + **karr-coordinator** if it's a family. Add test-writer, doc-writer and
adr-auditor when the project has enough surface to warrant a lane.
**Only the release-manager commits.** Workers and writers leave a commit-ready tree and
a report; commit style, changelog and release skills are briefed into the
release-manager alone. Card ownership and the karr skill split: "Who writes shared
state" in `references/agents.md`.
Two rules that decide whether this setup works or rots:
- **Never restate skill content in the agent body.** The skills are already in context.
The body says who the agent is, what its lane is, and what is true about *this repo*
and written down nowhere else.
- **Every agent body ends the conventions paragraph with**: *"The conventions above are
non-negotiable — apply silently, do not restate."*
## Step 4 — house rules
Write `.claude/rules/<prefix>-rules.md` from `references/rules-template.md`. Keep it
under ~90 lines; it is loaded on every single turn. It carries engineering discipline,
the **delegation lock** (the part that makes the main agent delegate), coordination, and
the release-permission rule. It does **not** carry language conventions — those are
skills, referenced by name.
## Step 5 — settings
`.claude/settings.json` (committed, project-wide):
```json
{
"enabledPlugins": {
"briefing@getty": true
}
}
```
Add `superpowers@claude-plugins-official` / `caveman@caveman` only if the user already
uses them in sibling repos. `.claude/settings.local.json` is per-machine permission
noise — never author it, never commit decisions into it.
## Step 6 — CLAUDE.md pointer
The repo's `CLAUDE.md` gets a short delegation table naming the agents and a line saying
where the rules and skills live. It must not duplicate rule or skill content — a
duplicated rule is a rule that will drift.
```markdown
## Delegation
Delegate behavior-relevant code to the right agent instead of touching it yourself —
principle and lane are in `.claude/rules/<prefix>-rules.md`.
| Task | Agent |
|---|---|
| Implement / refactor / debug behavior-relevant code | `<prefix>-worker` (default) |
| Write/extend tests | `<prefix>-test-writer` |
| Commits, changelog, card → done, pre-release audit | `<prefix>-release-manager` |
The agents carry their skills via `briefing.skills` (see `.claude/agents/`); the main
agent delegates rather than loading them. Skill sources live under `.claude/skills/`.
```
## Step 7 — karr coordination (optional, default yes)
`karr init`, the `.karr` agent-execution file, the board conventions, cross-repo handoff
and the `karr-foundation` drain loop: `references/karr.md`.
Two hard-won operational rules go with it, and belong in the rules file of any repo that
fans work out:
- **Serialize karr mutations when fanning out.** Parallel implementation is fine;
N concurrent `karr move`/`handoff`/`sync` calls landing together have OOM-rebooted a
host. Collect results, then loop the board writes sequentially.
- **Public trackers are not a queue.** If the project has a public issue tracker
(Codeberg/GitHub), agents never read, comment on or close an issue on their own
initiative — only on explicit instruction, because every write publishes under the
maintainer's name.
## Step 8 — verify
```bash
ls .claude/agents/ .claude/rules/ .claude/skills/ 2>/dev/null
python3 - <<'EOF'
import glob, re, os, sys
missing = []
for f in glob.glob('.claude/agents/*.md'):
fm = open(f).read().split('---')[1]
if 'briefing:' not in fm: print(f'{f}: no briefing block'); continue
for name in re.findall(r'^\s*-\s*([\w:-]+)\s*$', fm.split('briefing:')[1], re.M):
if not any(os.path.exists(p) for p in (
f'.claude/skills/{name}/SKILL.md',
os.path.expanduser(f'~/.claude/skills/{name}/SKILL.md'))):
missing.append((f, name))
for f, n in missing: print(f'UNRESOLVED {n} in {f}')
print('all skills resolve' if not missing else 'FIX THESE — briefing will deny the spawn')
EOF
```
The plugin-namespaced form (`plugin:skill`) and plugin caches also resolve — the check
above only knows the two common locations, so treat its output as a first pass.
**You cannot spawn the new agents in the session that created them.** Claude Code reads
`.claude/agents/` at startup, so a fresh agent file is `not found` until the next
session. Drive the hook directly instead — it proves both halves without a restart:
```bash
HOOK=$(ls -d ~/.claude/plugins/cache/briefing/briefing/*/hooks/briefing-preload | tail -1)
printf '%s' '{"session_id":"t","cwd":"'"$PWD"'","tool_name":"Agent","tool_input":
{"subagent_type":"<prefix>-worker","description":"x","prompt":"MARKER"}}' \
| tr -d '\n' | "$HOOK" | python3 -m json.tool | head -20
```
Expect an `updatedInput.prompt` many KB long, containing each briefed skill's body and
still carrying `MARKER`. Then repeat with a throwaway agent file listing a skill that
does not exist: the hook must answer `"permissionDecision": "deny"` naming the unknown
skill. Anything else means the setup is silently unbriefed. Delete the throwaway after.
Once a later session has the agents, the live check is behavioral: a briefed agent
answers a question that is only in its skills without calling the `Skill` tool. If it
reaches for `Skill`, the hook did not fire — check `enabledPlugins` in *this* project.
## Bringing an existing setup in line
Same steps, but audit first and report before editing: agents whose bodies restate skill
content (migrate to `briefing.skills`), agents still using the plain top-level `skills:`
key (**briefing deliberately ignores it — it only reads `briefing.skills`**), a rules file
that duplicates a skill, a missing delegation lock, shared skills copied by hand or
still hardlinked instead of installed (skill `getty-skill-library`, "Old pattern").
Role drift to look for in older setups:
- `allowed-tools:` in an agent file → ignored by Claude Code, the agent has every tool.
Drop it on writing roles; on read-only roles replace it with
`disallowedTools: Edit, Write, NotebookEdit` (see the frontmatter contract);
- a read-only `<prefix>-release-checker` → replace with `<prefix>-release-manager`
(the audit becomes part of its lane; there is no third role);
- workers or writers briefed with commit-style, changelog or release skills, or whose
body tells them to commit → strip both, the release-manager owns them;
- doc-writers briefed with a whole release skill just for the doc format → brief the
doc-format skill instead;
- `kanban-issues-karr-cli` in a working role's briefing → `kanban-issues-karr-ticket`;
in the karr-coordinator → `kanban-issues-karr-coordination` + `-ticket`.