named-subagents 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- named_subagents-0.3.0/LICENSE +21 -0
- named_subagents-0.3.0/PKG-INFO +301 -0
- named_subagents-0.3.0/README.md +272 -0
- named_subagents-0.3.0/named_subagents/__init__.py +1144 -0
- named_subagents-0.3.0/named_subagents/cli.py +539 -0
- named_subagents-0.3.0/named_subagents/py.typed +0 -0
- named_subagents-0.3.0/named_subagents/registry.json +1197 -0
- named_subagents-0.3.0/named_subagents.egg-info/PKG-INFO +301 -0
- named_subagents-0.3.0/named_subagents.egg-info/SOURCES.txt +12 -0
- named_subagents-0.3.0/named_subagents.egg-info/dependency_links.txt +1 -0
- named_subagents-0.3.0/named_subagents.egg-info/entry_points.txt +2 -0
- named_subagents-0.3.0/named_subagents.egg-info/top_level.txt +1 -0
- named_subagents-0.3.0/pyproject.toml +54 -0
- named_subagents-0.3.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bobby-cell-commits
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: named-subagents
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Themed, non-repeating nicknames for Claude Code subagents β a userspace port of Codex's nickname_candidates
|
|
5
|
+
Author: Bobby-cell-commits
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Bobby-cell-commits/named-subagents
|
|
8
|
+
Project-URL: Repository, https://github.com/Bobby-cell-commits/named-subagents
|
|
9
|
+
Project-URL: Issues, https://github.com/Bobby-cell-commits/named-subagents/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Bobby-cell-commits/named-subagents/blob/master/CHANGELOG.md
|
|
11
|
+
Keywords: claude-code,subagents,agents,nicknames,fan-out,orchestration,multi-agent
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# named-subagents
|
|
31
|
+
|
|
32
|
+
**Themed, non-repeating nicknames for Claude Code subagents** β a userspace port
|
|
33
|
+
of [Codex's per-instance `nickname_candidates`](https://developers.openai.com/codex/subagents),
|
|
34
|
+
grown into a full identity layer.
|
|
35
|
+
|
|
36
|
+
[](https://github.com/Bobby-cell-commits/named-subagents/actions/workflows/ci.yml)
|
|
37
|
+
  
|
|
38
|
+
|
|
39
|
+
When you fan out several Claude Code subagents, parallel instances of one role
|
|
40
|
+
are three identical `Explore` labels. Codex instead gives every spawned instance
|
|
41
|
+
a distinct human-legible **nickname**. Claude Code has no such field β requested
|
|
42
|
+
in [anthropics/claude-code#9206](https://github.com/anthropics/claude-code/issues/9206),
|
|
43
|
+
closed *"not planned"* β so this library emulates it, and goes further:
|
|
44
|
+
nicknames are **themed to the kind of task**, **never repeat across runs**, and
|
|
45
|
+
each one knows **who it's named after**.
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
π§ Hudson [Explore] map the auth module β explorers explore
|
|
49
|
+
π€ Plato [architect] why was event-sourcing chosen β philosophers ponder
|
|
50
|
+
π Bosch [debugger] root-cause the flaky test β detectives debug
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## The idea in one line
|
|
54
|
+
|
|
55
|
+
A subagent has two names: its **role** (what it *is* β `Explore`, `worker`, β¦,
|
|
56
|
+
native via `subagent_type` / `.claude/agents/*.md`) and its **nickname** (which
|
|
57
|
+
*instance* β `Hudson`, `Nansen`, β¦). This library adds the second.
|
|
58
|
+
|
|
59
|
+
| Codex | Claude Code native | This library |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| agent `name` (identity + routing) | `subagent_type` | β (unchanged) |
|
|
62
|
+
| `nickname_candidates` (per-instance display) | *(none)* | β
themed pools |
|
|
63
|
+
| β | β | β
non-repeat across runs (ledger) |
|
|
64
|
+
| β | β | β
task β theme auto-matching |
|
|
65
|
+
| β | β | β
pins, bios, custom themes, stats, doctor |
|
|
66
|
+
|
|
67
|
+
## Install
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install named-subagents # Python 3.8+, zero dependencies
|
|
71
|
+
npm i named-subagents # Node β₯ 16, ESM, zero dependencies, types shipped
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Both ship the same 395-name registry and a `named-subagents` CLI. Or vendor it:
|
|
75
|
+
drop the `named_subagents/` folder (Python) or `js/named_subagents.mjs` +
|
|
76
|
+
`registry.json` (JS) into your repo β stdlib/`node:` builtins only.
|
|
77
|
+
|
|
78
|
+
## Themes
|
|
79
|
+
|
|
80
|
+
395 names across 14 categories, each globally unique, each with a one-line bio:
|
|
81
|
+
|
|
82
|
+
| Category | Task shape | Name theme | e.g. |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| `explore` | map / search a codebase | Explorers & navigators | Magellan, Shackleton |
|
|
85
|
+
| `code` | implement features | Programmers & computing pioneers | Turing, Hopper, Ada |
|
|
86
|
+
| `research` | external info gathering | Scientists & researchers | Curie, Feynman |
|
|
87
|
+
| `reflect` | design rationale, inner workings | Philosophers | Socrates, Kant |
|
|
88
|
+
| `debug` | root-cause hunting | Detectives | Holmes, Poirot |
|
|
89
|
+
| `test` | edge cases, fuzz, adversarial | Tricksters | Loki, Anansi |
|
|
90
|
+
| `review` | critique, verdict | Judges & jurists | Solomon, Ginsburg |
|
|
91
|
+
| `security` | audit, threat model | Guardians & sentinels | Argus, Heimdall |
|
|
92
|
+
| `design` | UI / UX / visual | Artists & designers | DaVinci, Rams |
|
|
93
|
+
| `data` | analysis, stats, ML | Mathematicians & statisticians | Gauss, Noether |
|
|
94
|
+
| `orchestrate` | plan, coordinate | Strategists & generals | SunTzu, Napoleon |
|
|
95
|
+
| `docs` | technical writing | Writers & authors | Orwell, Borges |
|
|
96
|
+
| `build` | infra / refactor / perf | Engineers & inventors | Tesla, Brunel |
|
|
97
|
+
| `default` | catch-all | Celestial (stars) | Orion, Vega |
|
|
98
|
+
|
|
99
|
+
Pools are deliberately diverse (Ibn Battuta, Zheng He, Ada Lovelace, Ramanujan,
|
|
100
|
+
Confucius, Hypatia, Murasaki, β¦) β good practice, and larger pools mean rarer
|
|
101
|
+
generation cycling.
|
|
102
|
+
|
|
103
|
+
## Usage
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from named_subagents import Registry, Ledger, plan_fanout
|
|
107
|
+
|
|
108
|
+
reg = Registry.load()
|
|
109
|
+
ledger = Ledger(".named-subagents-ledger.json") # non-repeat across runs
|
|
110
|
+
|
|
111
|
+
plan = plan_fanout(
|
|
112
|
+
["map the auth module", "map the billing module", "map the search module"],
|
|
113
|
+
reg, ledger=ledger, role="Explore",
|
|
114
|
+
)
|
|
115
|
+
for a in plan:
|
|
116
|
+
# a.agent_kwargs() -> {subagent_type, description, prompt}, Agent-tool-ready
|
|
117
|
+
print(a.emoji, a.nickname, a.subagent_type, "β", a.bio)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
import { Registry, Ledger, planFanout } from "named-subagents";
|
|
122
|
+
|
|
123
|
+
const reg = Registry.load();
|
|
124
|
+
const ledger = new Ledger(".named-subagents-ledger.json");
|
|
125
|
+
const plan = planFanout(["map auth", "map billing", "map search"],
|
|
126
|
+
reg, { ledger, role: "Explore" });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Cross-language parity is CI-enforced**: same md5-seeded ordering, same
|
|
130
|
+
registry, same ledger format β identical inputs give byte-identical outputs,
|
|
131
|
+
and either language can continue a ledger the other wrote.
|
|
132
|
+
|
|
133
|
+
The generated `prompt` prepends a persona preamble telling the agent to begin
|
|
134
|
+
its report with `[Hudson]`, so parallel results come back **attributed by
|
|
135
|
+
nickname**. Add `with_bio=True` / `withBio: true` (CLI: `--bio-in-prompt`) and
|
|
136
|
+
each agent also learns who it's named after.
|
|
137
|
+
|
|
138
|
+
**Attribution never depended on the agent complying.** The nickname is already
|
|
139
|
+
in the dispatch metadata β it *is* the display label your runner shows β so it
|
|
140
|
+
is deterministic regardless of what the agent writes. The `[Hudson]` self-tag is
|
|
141
|
+
only for the case where you have the raw report *text* and nothing else; for
|
|
142
|
+
that path, `attribute(nickname, report)` / `attribute()` verifies the prefix and
|
|
143
|
+
repairs it (missing β prepended, wrong nickname β replaced; idempotent).
|
|
144
|
+
|
|
145
|
+
### CLI
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
named-subagents categories # the 14 themes
|
|
149
|
+
named-subagents resolve --task "audit auth for injection" # -> security
|
|
150
|
+
named-subagents resolve --task "audit auth" --explain # ...+ why (keywords, scores)
|
|
151
|
+
named-subagents allocate --category reflect --count 3
|
|
152
|
+
named-subagents assign --role Explore --task "map the router" \
|
|
153
|
+
--count 4 --ledger .ledger.json # Agent payloads
|
|
154
|
+
named-subagents bio Heimdall # who is this figure?
|
|
155
|
+
named-subagents stats --ledger .ledger.json # pool burn-down, generations
|
|
156
|
+
named-subagents doctor # self-checks (see below)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
> **Recording a demo?** `scripts/record-demo.sh` runs a short, narrated
|
|
160
|
+
> walkthrough suitable for `asciinema rec` (or pipe the cast to a GIF) β see its
|
|
161
|
+
> header for the exact commands.
|
|
162
|
+
|
|
163
|
+
### Stable identities: pins
|
|
164
|
+
|
|
165
|
+
Always call the security agent **Argus**:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
named-subagents assign --task "audit the release" --category security --pin security=Argus
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Pinned names bypass the ledger (a stable identity *recurs* by design) and are
|
|
172
|
+
reserved out of normal draws, so nobody else can be issued `Argus`.
|
|
173
|
+
|
|
174
|
+
### Recycle or burn names
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
named-subagents release --category explore --name Hudson --ledger .ledger.json # recycle
|
|
178
|
+
named-subagents retire --category explore --name Columbus --ledger .ledger.json # never again
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`release` returns a short-lived agent's name to the pool; `retire` removes a
|
|
182
|
+
name permanently (every generation). If retire/pins empty a pool entirely you
|
|
183
|
+
get a clear `PoolExhaustedError` up front.
|
|
184
|
+
|
|
185
|
+
### Custom themes & config
|
|
186
|
+
|
|
187
|
+
`--config PATH`, `$NAMED_SUBAGENTS_CONFIG`, or
|
|
188
|
+
`~/.config/named-subagents/config.json` (and, **opt-in**, a project-local
|
|
189
|
+
`./.named-subagents.json` β see the security note below):
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{ "pins": { "security": "Argus" },
|
|
193
|
+
"categories": { "starships": { "theme": "Star systems", "emoji": "π",
|
|
194
|
+
"keywords": ["fleet"], "names": ["Enterprise", "Rocinante"] } },
|
|
195
|
+
"extend": { "explore": { "names": ["Kupe"] } } }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
New categories are added, same-key categories replace the bundled one, `extend`
|
|
199
|
+
appends to an existing pool. Everything is re-validated on load β global
|
|
200
|
+
uniqueness and a strict name pattern (see [SECURITY.md](SECURITY.md); custom
|
|
201
|
+
names are untrusted input that ends up inside agent prompts).
|
|
202
|
+
|
|
203
|
+
Since 0.3 the project-local **`./.named-subagents.json` is opt-in** β it is the
|
|
204
|
+
one untrusted-input surface (a repo you cloned controls it), so it is *not*
|
|
205
|
+
auto-loaded unless you pass `--cwd-config` or set `NAMED_SUBAGENTS_CWD_CONFIG=1`.
|
|
206
|
+
`--no-cwd-config` (or `NAMED_SUBAGENTS_NO_CWD_CONFIG=1`) forces it off and wins
|
|
207
|
+
over any opt-in. Explicit `--config PATH`, `$NAMED_SUBAGENTS_CONFIG`, and the
|
|
208
|
+
home config are always honored (deliberate or user-owned).
|
|
209
|
+
|
|
210
|
+
### Collision-avoidance against real agents
|
|
211
|
+
|
|
212
|
+
`--avoid-installed` (or `plan_fanout(..., avoid_installed=True)`) scans
|
|
213
|
+
`.claude/agents/` + `~/.claude/agents/` frontmatter and guarantees nicknames
|
|
214
|
+
are disjoint from your installed agent names β case-insensitive, at the base-name
|
|
215
|
+
level, enforced at draw time.
|
|
216
|
+
|
|
217
|
+
### Orchestrator adapters
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
named-subagents assign --task "β¦" --count 4 --format workflow # Workflow snippet
|
|
221
|
+
named-subagents assign --task "β¦" --count 4 --format swarm # swarm YAML fragment
|
|
222
|
+
named-subagents assign --task "β¦" --count 4 --format labels # generic JSON
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Doctor (self-awareness)
|
|
226
|
+
|
|
227
|
+
`named-subagents doctor` checks: registry integrity (uniqueness, sanitization,
|
|
228
|
+
bios coverage), ledger health, pin validity, installed-agent collisions,
|
|
229
|
+
version consistency across `__init__.py`/`pyproject.toml`/`package.json`, and β
|
|
230
|
+
when both runtimes are present β a live PythonβJS parity probe. Non-zero exit
|
|
231
|
+
on failure; `--json` for machines.
|
|
232
|
+
|
|
233
|
+
### `/named-fanout` skill
|
|
234
|
+
|
|
235
|
+
A ready-made Claude Code skill wrapping the CLI lives in
|
|
236
|
+
[`skill/named-fanout/`](skill/named-fanout/SKILL.md):
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
cp -r skill/named-fanout ~/.claude/skills/
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## How non-repeat works
|
|
243
|
+
|
|
244
|
+
`allocate()` draws from the category pool in a deterministic md5-seeded order,
|
|
245
|
+
records used names in the **ledger**, and skips them next time. When a pool is
|
|
246
|
+
exhausted it advances a **generation** and suffixes names (`Magellan`,
|
|
247
|
+
`MagellanΒ·2`, β¦). A display name is never issued to two concurrently-live
|
|
248
|
+
holders, and is never reused at all *unless you explicitly `release` it*.
|
|
249
|
+
Allocation is deterministic given `(category, ledger-state)` β resume- and
|
|
250
|
+
re-run-safe (the same reason Claude Code Workflows ban `Math.random`).
|
|
251
|
+
|
|
252
|
+
## Routing is best-effort
|
|
253
|
+
|
|
254
|
+
Category resolution is `explicit category > subagent_type match > task-keyword
|
|
255
|
+
match > default`. The keyword layer is a **heuristic, not a classifier** β for
|
|
256
|
+
guaranteed themes pass `category=` or `role=` explicitly.
|
|
257
|
+
|
|
258
|
+
## Where this sits (community landscape)
|
|
259
|
+
|
|
260
|
+
[`COMMUNITY.md`](COMMUNITY.md) surveys 11 community Claude Code agent projects.
|
|
261
|
+
The whole ecosystem names agents by **functional role**; none provide
|
|
262
|
+
per-instance nicknames, task-themed names, or a non-repeating ledger. This is
|
|
263
|
+
an **identity layer that composes _under_** orchestrators like `claude-swarm`,
|
|
264
|
+
`metaswarm`, or `claude-flow` rather than competing with them β that's what the
|
|
265
|
+
`--format` adapters are for.
|
|
266
|
+
|
|
267
|
+
## Tests
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
python3 test_named_subagents.py # 266 checks incl. state-machine campaigns
|
|
271
|
+
node js/test_named_subagents.mjs # 279 checks (mirror suite)
|
|
272
|
+
scripts/parity_check.sh # cross-language gate (both runtimes)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
CI runs Python 3.8/3.12/3.13, Node 18/20/22, install smokes for both package
|
|
276
|
+
managers, and the parity gate.
|
|
277
|
+
|
|
278
|
+
## Files
|
|
279
|
+
|
|
280
|
+
| Path | Role |
|
|
281
|
+
|---|---|
|
|
282
|
+
| `named_subagents/` | Python package (reference impl) + **canonical `registry.json`** |
|
|
283
|
+
| `js/` | JS/ESM npm package (twin port; `js/registry.json` is generated at pack time) |
|
|
284
|
+
| `skill/named-fanout/` | Claude Code skill wrapping the CLI |
|
|
285
|
+
| `FINDINGS.md` / `COMMUNITY.md` | research record + ecosystem survey |
|
|
286
|
+
| `SECURITY.md` / `CONTRIBUTING.md` | threat model / parity discipline |
|
|
287
|
+
| `ROADMAP.md` | candidate improvements for future releases |
|
|
288
|
+
|
|
289
|
+
## Roadmap
|
|
290
|
+
|
|
291
|
+
0.3.0 shipped most of the backlog β release automation with supply-chain
|
|
292
|
+
provenance, cwd-config opt-in, type-surface verification + `py.typed`,
|
|
293
|
+
attribution + ledger session/lock helpers, and `resolve --explain` backed by a
|
|
294
|
+
measured accuracy eval (see [`CHANGELOG.md`](CHANGELOG.md)). What's left β
|
|
295
|
+
adoption media, the actual npm/PyPI publish, lint/coverage CI, and the
|
|
296
|
+
probe-gated auto-namer β is tracked in [`ROADMAP.md`](ROADMAP.md). Contributions
|
|
297
|
+
welcome (see [`CONTRIBUTING.md`](CONTRIBUTING.md)).
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# named-subagents
|
|
2
|
+
|
|
3
|
+
**Themed, non-repeating nicknames for Claude Code subagents** β a userspace port
|
|
4
|
+
of [Codex's per-instance `nickname_candidates`](https://developers.openai.com/codex/subagents),
|
|
5
|
+
grown into a full identity layer.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/Bobby-cell-commits/named-subagents/actions/workflows/ci.yml)
|
|
8
|
+
  
|
|
9
|
+
|
|
10
|
+
When you fan out several Claude Code subagents, parallel instances of one role
|
|
11
|
+
are three identical `Explore` labels. Codex instead gives every spawned instance
|
|
12
|
+
a distinct human-legible **nickname**. Claude Code has no such field β requested
|
|
13
|
+
in [anthropics/claude-code#9206](https://github.com/anthropics/claude-code/issues/9206),
|
|
14
|
+
closed *"not planned"* β so this library emulates it, and goes further:
|
|
15
|
+
nicknames are **themed to the kind of task**, **never repeat across runs**, and
|
|
16
|
+
each one knows **who it's named after**.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
π§ Hudson [Explore] map the auth module β explorers explore
|
|
20
|
+
π€ Plato [architect] why was event-sourcing chosen β philosophers ponder
|
|
21
|
+
π Bosch [debugger] root-cause the flaky test β detectives debug
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## The idea in one line
|
|
25
|
+
|
|
26
|
+
A subagent has two names: its **role** (what it *is* β `Explore`, `worker`, β¦,
|
|
27
|
+
native via `subagent_type` / `.claude/agents/*.md`) and its **nickname** (which
|
|
28
|
+
*instance* β `Hudson`, `Nansen`, β¦). This library adds the second.
|
|
29
|
+
|
|
30
|
+
| Codex | Claude Code native | This library |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| agent `name` (identity + routing) | `subagent_type` | β (unchanged) |
|
|
33
|
+
| `nickname_candidates` (per-instance display) | *(none)* | β
themed pools |
|
|
34
|
+
| β | β | β
non-repeat across runs (ledger) |
|
|
35
|
+
| β | β | β
task β theme auto-matching |
|
|
36
|
+
| β | β | β
pins, bios, custom themes, stats, doctor |
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install named-subagents # Python 3.8+, zero dependencies
|
|
42
|
+
npm i named-subagents # Node β₯ 16, ESM, zero dependencies, types shipped
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Both ship the same 395-name registry and a `named-subagents` CLI. Or vendor it:
|
|
46
|
+
drop the `named_subagents/` folder (Python) or `js/named_subagents.mjs` +
|
|
47
|
+
`registry.json` (JS) into your repo β stdlib/`node:` builtins only.
|
|
48
|
+
|
|
49
|
+
## Themes
|
|
50
|
+
|
|
51
|
+
395 names across 14 categories, each globally unique, each with a one-line bio:
|
|
52
|
+
|
|
53
|
+
| Category | Task shape | Name theme | e.g. |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| `explore` | map / search a codebase | Explorers & navigators | Magellan, Shackleton |
|
|
56
|
+
| `code` | implement features | Programmers & computing pioneers | Turing, Hopper, Ada |
|
|
57
|
+
| `research` | external info gathering | Scientists & researchers | Curie, Feynman |
|
|
58
|
+
| `reflect` | design rationale, inner workings | Philosophers | Socrates, Kant |
|
|
59
|
+
| `debug` | root-cause hunting | Detectives | Holmes, Poirot |
|
|
60
|
+
| `test` | edge cases, fuzz, adversarial | Tricksters | Loki, Anansi |
|
|
61
|
+
| `review` | critique, verdict | Judges & jurists | Solomon, Ginsburg |
|
|
62
|
+
| `security` | audit, threat model | Guardians & sentinels | Argus, Heimdall |
|
|
63
|
+
| `design` | UI / UX / visual | Artists & designers | DaVinci, Rams |
|
|
64
|
+
| `data` | analysis, stats, ML | Mathematicians & statisticians | Gauss, Noether |
|
|
65
|
+
| `orchestrate` | plan, coordinate | Strategists & generals | SunTzu, Napoleon |
|
|
66
|
+
| `docs` | technical writing | Writers & authors | Orwell, Borges |
|
|
67
|
+
| `build` | infra / refactor / perf | Engineers & inventors | Tesla, Brunel |
|
|
68
|
+
| `default` | catch-all | Celestial (stars) | Orion, Vega |
|
|
69
|
+
|
|
70
|
+
Pools are deliberately diverse (Ibn Battuta, Zheng He, Ada Lovelace, Ramanujan,
|
|
71
|
+
Confucius, Hypatia, Murasaki, β¦) β good practice, and larger pools mean rarer
|
|
72
|
+
generation cycling.
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from named_subagents import Registry, Ledger, plan_fanout
|
|
78
|
+
|
|
79
|
+
reg = Registry.load()
|
|
80
|
+
ledger = Ledger(".named-subagents-ledger.json") # non-repeat across runs
|
|
81
|
+
|
|
82
|
+
plan = plan_fanout(
|
|
83
|
+
["map the auth module", "map the billing module", "map the search module"],
|
|
84
|
+
reg, ledger=ledger, role="Explore",
|
|
85
|
+
)
|
|
86
|
+
for a in plan:
|
|
87
|
+
# a.agent_kwargs() -> {subagent_type, description, prompt}, Agent-tool-ready
|
|
88
|
+
print(a.emoji, a.nickname, a.subagent_type, "β", a.bio)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { Registry, Ledger, planFanout } from "named-subagents";
|
|
93
|
+
|
|
94
|
+
const reg = Registry.load();
|
|
95
|
+
const ledger = new Ledger(".named-subagents-ledger.json");
|
|
96
|
+
const plan = planFanout(["map auth", "map billing", "map search"],
|
|
97
|
+
reg, { ledger, role: "Explore" });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Cross-language parity is CI-enforced**: same md5-seeded ordering, same
|
|
101
|
+
registry, same ledger format β identical inputs give byte-identical outputs,
|
|
102
|
+
and either language can continue a ledger the other wrote.
|
|
103
|
+
|
|
104
|
+
The generated `prompt` prepends a persona preamble telling the agent to begin
|
|
105
|
+
its report with `[Hudson]`, so parallel results come back **attributed by
|
|
106
|
+
nickname**. Add `with_bio=True` / `withBio: true` (CLI: `--bio-in-prompt`) and
|
|
107
|
+
each agent also learns who it's named after.
|
|
108
|
+
|
|
109
|
+
**Attribution never depended on the agent complying.** The nickname is already
|
|
110
|
+
in the dispatch metadata β it *is* the display label your runner shows β so it
|
|
111
|
+
is deterministic regardless of what the agent writes. The `[Hudson]` self-tag is
|
|
112
|
+
only for the case where you have the raw report *text* and nothing else; for
|
|
113
|
+
that path, `attribute(nickname, report)` / `attribute()` verifies the prefix and
|
|
114
|
+
repairs it (missing β prepended, wrong nickname β replaced; idempotent).
|
|
115
|
+
|
|
116
|
+
### CLI
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
named-subagents categories # the 14 themes
|
|
120
|
+
named-subagents resolve --task "audit auth for injection" # -> security
|
|
121
|
+
named-subagents resolve --task "audit auth" --explain # ...+ why (keywords, scores)
|
|
122
|
+
named-subagents allocate --category reflect --count 3
|
|
123
|
+
named-subagents assign --role Explore --task "map the router" \
|
|
124
|
+
--count 4 --ledger .ledger.json # Agent payloads
|
|
125
|
+
named-subagents bio Heimdall # who is this figure?
|
|
126
|
+
named-subagents stats --ledger .ledger.json # pool burn-down, generations
|
|
127
|
+
named-subagents doctor # self-checks (see below)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
> **Recording a demo?** `scripts/record-demo.sh` runs a short, narrated
|
|
131
|
+
> walkthrough suitable for `asciinema rec` (or pipe the cast to a GIF) β see its
|
|
132
|
+
> header for the exact commands.
|
|
133
|
+
|
|
134
|
+
### Stable identities: pins
|
|
135
|
+
|
|
136
|
+
Always call the security agent **Argus**:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
named-subagents assign --task "audit the release" --category security --pin security=Argus
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Pinned names bypass the ledger (a stable identity *recurs* by design) and are
|
|
143
|
+
reserved out of normal draws, so nobody else can be issued `Argus`.
|
|
144
|
+
|
|
145
|
+
### Recycle or burn names
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
named-subagents release --category explore --name Hudson --ledger .ledger.json # recycle
|
|
149
|
+
named-subagents retire --category explore --name Columbus --ledger .ledger.json # never again
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`release` returns a short-lived agent's name to the pool; `retire` removes a
|
|
153
|
+
name permanently (every generation). If retire/pins empty a pool entirely you
|
|
154
|
+
get a clear `PoolExhaustedError` up front.
|
|
155
|
+
|
|
156
|
+
### Custom themes & config
|
|
157
|
+
|
|
158
|
+
`--config PATH`, `$NAMED_SUBAGENTS_CONFIG`, or
|
|
159
|
+
`~/.config/named-subagents/config.json` (and, **opt-in**, a project-local
|
|
160
|
+
`./.named-subagents.json` β see the security note below):
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{ "pins": { "security": "Argus" },
|
|
164
|
+
"categories": { "starships": { "theme": "Star systems", "emoji": "π",
|
|
165
|
+
"keywords": ["fleet"], "names": ["Enterprise", "Rocinante"] } },
|
|
166
|
+
"extend": { "explore": { "names": ["Kupe"] } } }
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
New categories are added, same-key categories replace the bundled one, `extend`
|
|
170
|
+
appends to an existing pool. Everything is re-validated on load β global
|
|
171
|
+
uniqueness and a strict name pattern (see [SECURITY.md](SECURITY.md); custom
|
|
172
|
+
names are untrusted input that ends up inside agent prompts).
|
|
173
|
+
|
|
174
|
+
Since 0.3 the project-local **`./.named-subagents.json` is opt-in** β it is the
|
|
175
|
+
one untrusted-input surface (a repo you cloned controls it), so it is *not*
|
|
176
|
+
auto-loaded unless you pass `--cwd-config` or set `NAMED_SUBAGENTS_CWD_CONFIG=1`.
|
|
177
|
+
`--no-cwd-config` (or `NAMED_SUBAGENTS_NO_CWD_CONFIG=1`) forces it off and wins
|
|
178
|
+
over any opt-in. Explicit `--config PATH`, `$NAMED_SUBAGENTS_CONFIG`, and the
|
|
179
|
+
home config are always honored (deliberate or user-owned).
|
|
180
|
+
|
|
181
|
+
### Collision-avoidance against real agents
|
|
182
|
+
|
|
183
|
+
`--avoid-installed` (or `plan_fanout(..., avoid_installed=True)`) scans
|
|
184
|
+
`.claude/agents/` + `~/.claude/agents/` frontmatter and guarantees nicknames
|
|
185
|
+
are disjoint from your installed agent names β case-insensitive, at the base-name
|
|
186
|
+
level, enforced at draw time.
|
|
187
|
+
|
|
188
|
+
### Orchestrator adapters
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
named-subagents assign --task "β¦" --count 4 --format workflow # Workflow snippet
|
|
192
|
+
named-subagents assign --task "β¦" --count 4 --format swarm # swarm YAML fragment
|
|
193
|
+
named-subagents assign --task "β¦" --count 4 --format labels # generic JSON
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Doctor (self-awareness)
|
|
197
|
+
|
|
198
|
+
`named-subagents doctor` checks: registry integrity (uniqueness, sanitization,
|
|
199
|
+
bios coverage), ledger health, pin validity, installed-agent collisions,
|
|
200
|
+
version consistency across `__init__.py`/`pyproject.toml`/`package.json`, and β
|
|
201
|
+
when both runtimes are present β a live PythonβJS parity probe. Non-zero exit
|
|
202
|
+
on failure; `--json` for machines.
|
|
203
|
+
|
|
204
|
+
### `/named-fanout` skill
|
|
205
|
+
|
|
206
|
+
A ready-made Claude Code skill wrapping the CLI lives in
|
|
207
|
+
[`skill/named-fanout/`](skill/named-fanout/SKILL.md):
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
cp -r skill/named-fanout ~/.claude/skills/
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## How non-repeat works
|
|
214
|
+
|
|
215
|
+
`allocate()` draws from the category pool in a deterministic md5-seeded order,
|
|
216
|
+
records used names in the **ledger**, and skips them next time. When a pool is
|
|
217
|
+
exhausted it advances a **generation** and suffixes names (`Magellan`,
|
|
218
|
+
`MagellanΒ·2`, β¦). A display name is never issued to two concurrently-live
|
|
219
|
+
holders, and is never reused at all *unless you explicitly `release` it*.
|
|
220
|
+
Allocation is deterministic given `(category, ledger-state)` β resume- and
|
|
221
|
+
re-run-safe (the same reason Claude Code Workflows ban `Math.random`).
|
|
222
|
+
|
|
223
|
+
## Routing is best-effort
|
|
224
|
+
|
|
225
|
+
Category resolution is `explicit category > subagent_type match > task-keyword
|
|
226
|
+
match > default`. The keyword layer is a **heuristic, not a classifier** β for
|
|
227
|
+
guaranteed themes pass `category=` or `role=` explicitly.
|
|
228
|
+
|
|
229
|
+
## Where this sits (community landscape)
|
|
230
|
+
|
|
231
|
+
[`COMMUNITY.md`](COMMUNITY.md) surveys 11 community Claude Code agent projects.
|
|
232
|
+
The whole ecosystem names agents by **functional role**; none provide
|
|
233
|
+
per-instance nicknames, task-themed names, or a non-repeating ledger. This is
|
|
234
|
+
an **identity layer that composes _under_** orchestrators like `claude-swarm`,
|
|
235
|
+
`metaswarm`, or `claude-flow` rather than competing with them β that's what the
|
|
236
|
+
`--format` adapters are for.
|
|
237
|
+
|
|
238
|
+
## Tests
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
python3 test_named_subagents.py # 266 checks incl. state-machine campaigns
|
|
242
|
+
node js/test_named_subagents.mjs # 279 checks (mirror suite)
|
|
243
|
+
scripts/parity_check.sh # cross-language gate (both runtimes)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
CI runs Python 3.8/3.12/3.13, Node 18/20/22, install smokes for both package
|
|
247
|
+
managers, and the parity gate.
|
|
248
|
+
|
|
249
|
+
## Files
|
|
250
|
+
|
|
251
|
+
| Path | Role |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `named_subagents/` | Python package (reference impl) + **canonical `registry.json`** |
|
|
254
|
+
| `js/` | JS/ESM npm package (twin port; `js/registry.json` is generated at pack time) |
|
|
255
|
+
| `skill/named-fanout/` | Claude Code skill wrapping the CLI |
|
|
256
|
+
| `FINDINGS.md` / `COMMUNITY.md` | research record + ecosystem survey |
|
|
257
|
+
| `SECURITY.md` / `CONTRIBUTING.md` | threat model / parity discipline |
|
|
258
|
+
| `ROADMAP.md` | candidate improvements for future releases |
|
|
259
|
+
|
|
260
|
+
## Roadmap
|
|
261
|
+
|
|
262
|
+
0.3.0 shipped most of the backlog β release automation with supply-chain
|
|
263
|
+
provenance, cwd-config opt-in, type-surface verification + `py.typed`,
|
|
264
|
+
attribution + ledger session/lock helpers, and `resolve --explain` backed by a
|
|
265
|
+
measured accuracy eval (see [`CHANGELOG.md`](CHANGELOG.md)). What's left β
|
|
266
|
+
adoption media, the actual npm/PyPI publish, lint/coverage CI, and the
|
|
267
|
+
probe-gated auto-namer β is tracked in [`ROADMAP.md`](ROADMAP.md). Contributions
|
|
268
|
+
welcome (see [`CONTRIBUTING.md`](CONTRIBUTING.md)).
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
[MIT](LICENSE)
|