Pages · Claude Agents Team
Contributing to agents-team
The plugin is a small set of templates + a Python toolchain. Most contributions land in one of three places:
- A new archetype (agent or skill template).
- A new rubric line-item (rule the linter or judge should fire).
- A workflow tweak (rule template, hook, scaffold behavior).
This guide covers all three.
Project layout
gh-pms workflow
Issues are tracked under github.com/fadymondy/agents-team/issues. The repo uses gh-pms labels (type:*, status:*, severity:*, effort:*, svc:*).
Standard flow:
- Pick an open
status:todoissue (or file a newtype:feature/type:bug). - Move it to
status:in-progress(/gh-pms:gh-currentorgh issue edit ... --add-label status:in-progress). - Work on a feature branch. Commit messages reference the issue (
Closes #N). - Push and open a PR.
- After merge, the issue auto-closes.
Plan-first: any change touching 2+ files or crossing a service boundary needs a plan in .plans/YYYY-MM-DD-{slug}.md before code lands. See rule 01.
Add a new archetype
Steps:
- Add the template under
plugins/agents-team/templates/agents/<name>.md.template(ortemplates/skills/). - Use
{{placeholders}}for values the generator will fill — seerender.py. - Add a filled-in fixture under
templates/fixtures/example-<name>.md. - Run the static linter on the fixture:
python3 plugins/agents-team/lib/eval/lint.py templates/fixtures/example-<name>.md. The fixture must produce 0 critical findings. - Update
docs/team-gen.md's archetype catalog table. - Update
skills/team-gen/SKILL.md— add a one-liner under "Available agent archetypes". - Open a PR with
Closes #Nreferencing the issue you started from.
Add a new rubric line-item
Every rule has to cite a source. No exceptions for the canonical rubric — unsourced rules go in experimental/ and are off by default.
Steps:
-
Pick the dimension (
frontmatter,description,tool_hygiene,model_fit,body_structure,anti_patterns). -
Decide the phase:
static(deterministic, regex / structure check) orjudge(LLM nuance). -
Write the rule entry in
lib/eval/rubric.md— stable ID (<dim>.<rule>), severity, phase, prompt for the judge / lint check, citation URL. -
If
static: implement the rule function inlib/eval/lint.pyunder the matching@rule("<dim>")decorator. Each function yields zero or moreFindingobjects. -
If
judge: it's automatically picked up byjudge.pyfrom the rubric — no code change needed. -
Add a known-bad fixture at
templates/eval-fixtures/known-bad/<rule>.mdthat exercises the rule. The linter must produce a finding with the matching ID. -
Run the full smoke test:
bash -
Update the calibration set if you've changed how an existing rule fires (Galileo 0.80 Spearman target).
Add a new rule template
These are the per-team rules /team-gen drops into .claude/rules/. They are not the same as evaluator rubric items.
Steps:
- Pick a slot. Numbers go up; reuse an existing number only if you're replacing it. Current span:
01..13. - Add
templates/rules/NN-<kebab>.mdwith frontmatterdescription+ the body. Open with**When this applies:**so the generator can pick a subset by domain. - Update
docs/team-gen.md→ "Pick rules" if the rule is part of a default set. - Reference any new placeholders (
{{services}},{{primary_locale}}, …) so the scaffolder can fill them.
Add a new hook
Hooks fire from Claude Code on events like SessionStart, Notification, Stop, TaskCompleted, TeammateIdle.
Steps:
- Add
templates/hooks/<name>.sh. Use{{TEAM_NAME}}for placeholders. - Make it executable (
chmod +x). - Wire it in
templates/hooks/settings.json.partialso the scaffolder merges it into the generated team'ssettings.json. - Run a syntax check:
bash -n templates/hooks/<name>.sh.
Run the test suite
There isn't a formal test suite yet — instead, the contract is:
python3 lib/eval/lint.py templates/fixtures/<any>.mdpasses.python3 lib/eval/lint.py templates/eval-fixtures/known-bad/<any>.mdproduces the expected critical / warning rule.python3 lib/gen/scaffold.py /tmp/spec.json --target /tmp/test-outputexits 0 with all generated agents at A-grade.bash -npasses on every shell script undertemplates/hooks/andlib/eval/.
A formal pytest layer is a v0.2 issue.
Style
- Python — stdlib only; no
pyyaml, norequests, noclick. The frontmatter parser is deliberately a regex sub. - Bash — works under bash 3.2 (macOS default) and bash 5+ (Linux). No
set -uif you can avoid it; tests have shown it bites with empty arrays. - Markdown — third-person descriptions in skills; numbered procedures in agents; cite sources for any rule.
- Comments — only when the why is non-obvious. The code's what should be obvious from naming and structure.
Release ritual
Releases are tagged v<MAJOR>.<MINOR>.<PATCH> and follow Semantic Versioning. The plugin.json version is the source of truth: a release commit bumps it from <X.Y.Z>-dev to <X.Y.Z>, the commit is tagged, and a follow-up commit bumps to <X.Y+1.0>-dev so "is this a release build?" is answerable from the manifest alone.
Procedure:
Tag style is vX.Y.Z (with the v), matching git-cliff's default tag pattern in cliff.toml.
License
MIT. By submitting a PR you agree your contribution is licensed under the same terms.