Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "claude-team",
"description": "Seventeen named specialist personas for Claude Code: session-scoped /name switching, delegation subagents with model tiers, a persona session launcher, and coordinator workflows with branch hygiene.",
"version": "0.7.0",
"version": "2.0.0",
"author": { "name": "Code Katz" }
}
50 changes: 50 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,56 @@ Auto-maintained via Claude devlog skill. Entries are reverse-chronological.

---

## [2026-07-29] v2 hardening: four specialists, a real race, and a lint I broke

**Category:** `milestone`
**Tags:** `concurrency`, `locking`, `codegen`, `security`, `versioning`, `dogfooding`, `delegation`

**Risk Level:** `medium`
**Breaking Change:** `no`

### Summary

An adversarial review of the codebase produced five findings. All five are fixed, each by the persona whose lane it sits in, working from the installed profiles rather than the repo copy. The suite went 136 to 163. The headline result: the parallel-sessions feature was silently losing data, and two of the four specialists found defects the review had missed.

### Detail

**Dogfooding was the precondition, not a nicety.** The team was cloned and installed through the documented path before any delegation. That validated the two install fixes shipped earlier the same day: the SessionStart hook registered itself in `~/.claude/settings.json`, and all three persona surfaces landed. It also surfaced a gap: Claude Code registers subagent types at session start, so seventeen freshly installed agents were invisible to the running session. The installer prints "Subagents installed (delegate with...)" as though they are live, while `install-commands` correctly states that slash commands need no restart. The one that needs a restart is the one that does not say so. The first round of delegation ran against profiles read from `~/.claude/team/` instead; the agent types appeared later in the session.

**The race was real and worse than reported.** The review found that `cmd_branch_close` does a read-modify-write with no lock, and reasoned that the `>>` appends in `branch start` and `session start` were safe because POSIX makes an O_APPEND write atomic. Akira verified that reasoning, confirmed no row was ever torn, and then showed it was beside the point: an append landing between a rewriter's read and its rename is **erased** by that rename. Atomicity of an append says nothing about its survival. That is the load-bearing argument for locking the appenders too, and the review had explicitly waved it off. Measured at 40-way concurrency, five runs, every run lost data: 23 to 29 of 40 rows survived, 5 to 8 of 20 status updates applied.

He also found a second failure mode nobody had looked for. `block_install` greps for its start marker, misses it against a concurrent write that has not landed, takes the append path, and writes a duplicate block. Two of five runs produced up to four `CLAUDE-TEAM` blocks in `CLAUDE.md`, after which `get_active` reads a corrupted awk range.

**Verification beat reasoning, twice, in the same change.** Akira's first locking implementation treated "no owner record" as stale. Every live holder passes through that state for microseconds between its `mkdir` and its record write, so contenders broke live locks 73 times per run. It also treated "no lock directory" as stale, so contenders removed directories other contenders had just created. Neither was caught by review; both were caught by a harness built to look for them.

**The commands generator closed a gap that had already bitten twice.** `commands/` was hand-maintained while being about 95 percent derivable, and the drift test already contained the transformation as a checker. Alex turned the checker into a generator. He also overruled the brief: offered a choice between extending `generate-agents.sh` and adding a sibling script, he extended it, because `claude-team sync` and `install.sh` both invoke that one script and a sibling would never run on either path, reopening the same gap one level down.

**Two findings were correctly downgraded.** Morgan rated the path traversal Low, Informational as a vulnerability, and said so rather than inflating it: the CLI runs as the invoking user, reads with that user's permissions, and appends `.md`, so every reachable file is one the caller can already `cat`. He fixed it anyway on correctness grounds, because `use ../gtm` exited 0, printed a success line with an empty name, and pinned a non-profile into global state. He also checked `sanitize_branch_for_path`, found git's `check-ref-format` already rejects `..`, and left it alone on the grounds that a control reducing no risk is a liability.

**The symlink finding was closed as working-as-intended.** If the clone moves, the CLI and hook break loudly, and loud is correct: the install genuinely is broken and `bash install.sh` repairs it. Silencing it would hide real breakage, and the symlink buys `git pull` updating the CLI with no reinstall.

### Decisions Made

- **A `mkdir` directory lock, not `flock` with a fallback.** `flock` is absent from stock macOS. A two-scheme design does not exclude itself, so any host with mixed invocations silently loses mutual exclusion, and the fallback would run only on the platform CI does not cover it. The accepted cost is owning liveness by hand: traps, a dead-PID rule, and a 120 second ceiling for the reboot case.
- **Temp files are created beside their destination.** Not comment accuracy. A cross-device `mv` degrades to copy plus unlink, and a reader can observe a half-copied index during it, so this is what makes "readers need no lock" true.
- **The greeting is excised from `use` but not from `launch`.** `use` pins a default that every future session reads; `launch` starts one session, which is the moment a greeting is for.
- **Version numbering normalised to v2.0.0 with no fabricated v1 release.** The repository has no git tags, so v1 is presented as the first generation rather than a dated release. The April roadmap row still reads "v0.6 shipping" and stays verbatim: a dated changelog entry is not rewritten to match a later renumber.

### Mistakes Worth Recording

- **I broke CI lint and shipped it.** Commit `00b82aa` introduced three shellcheck findings in `tests/run.sh`, two of them a bare `done` read as a loop terminator. The rest of the suite already quotes `"done"` for exactly that reason, so the new code was the outlier against a convention already visible in the file. Morgan caught it while working in an adjacent file.
- **Morgan's suggested fix for one of those was wrong.** Quoting `${spec%%:*}` would have passed `coordinator on` as a single argument and broken the test. The finding was right and the fix was not, which is the argument for verifying a subagent's patch rather than applying it.
- **A control test passed for the wrong reason.** The first attempt to prove the traversal tests were meaningful ran against a scratch tree that did not contain `gtm.md`, so the traversal resolved to nothing and every assertion passed on unfixed code. The suite now asserts the traversal target exists before testing against it.
- **A `git add` swept a running agent's work into an unrelated commit.** Morgan's `resolve_name` fix landed inside the locking commit. Harmless to the code, wrong for the history. Scoped `git add <paths>` is the rule while agents are live.

### Related

- PRs #19, #20, #21: the same-day work this builds on
- `WRITING.md`: the plain technical English standard all four specialists wrote to
- ROADMAP: local profile overrides, now top priority and still the real gap

---

## [2026-07-29] claude-team sync: one command for the three-copy persona problem

**Category:** `decision`
Expand Down
57 changes: 35 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,26 @@ Four specialists for card and board game projects. Reiner designs the systems, C

---

**What's New — v0.7**
**What's New in v2.0**

v1 gave you the team. v2 makes the team dependable: every session gets its own persona, every edit reaches every copy, and every install path ends up with the same working setup.

**One persona edit, every copy updated** — `claude-team sync` regenerates the delegation subagents and reinstalls all three installed persona files in one step. Before this, editing a profile updated one of three copies and left the rest stale with no warning, so `/akira` and `claude-team use akira` could quietly disagree about who Akira is.

**Session context on every install path** — the SessionStart hook now registers when you install from a clone, not only through the plugin system. If the clone moves, `claude-team install-hook` re-points it.

**Plain technical English from the coding six** — Akira, Sasha, Robin, Alex, Morgan, and Jordan write to a fourteen-rule standard adapted from the plain-language principles of ASD-STE100. Named actors, one instruction per sentence, no filler, and no loss of precision. See [WRITING.md](WRITING.md).

**Session-scoped personas** — the `/akira`-style commands no longer touch global state, so parallel sessions each keep their own persona with no cross-talk. `claude-team use` still exists for pinning a global default and now says so out loud.

**`claude-team launch <persona>`** — open a dedicated Claude Code session with the persona baked in as system prompt, on its tier model (Fable 5 for the deep-reasoning personas, Opus 4.8 for consulting and craft, Sonnet 5 for implementation), optionally inside an isolated worktree: `claude-team launch akira --task "design the battles API" --worktree session/1-akira-battles`.

**Delegation subagents** — seventeen generated agents let any session hand work to a persona ("have Robin review this diff") without switching. Regenerate from profiles with `scripts/generate-agents.sh`.
**Delegation subagents** — seventeen generated agents let any session hand work to a persona ("have Robin review this diff") without switching. Regenerate from profiles with `claude-team sync`.

**Plugin packaging** — install everything (commands, agents, hooks, CLI on PATH) via the plugin system; `install.sh` remains for manual setups.

**Worktree-isolated `/parallel`** — session plans create a git worktree per session and never switch branches; the coordination session merges in dependency order.

**What's New — v0.6**

**[Parallel sessions](#coordinator-proactive-team-check-ins)** — run independent work streams simultaneously, each with a dedicated team member, scoped task, and explicit file boundary. No merge conflicts. No context bleed.

**[Casual and production workflow modes](#coordinator-proactive-team-check-ins)** — casual mode (default) commits straight to main with no branch enforcement; production mode adds branch gates, worktrees, and MR/PR flow as an explicit opt-in.

---

## Who This Is For
Expand Down Expand Up @@ -800,11 +802,13 @@ Each persona is installed as three self-contained files, and `profiles/` is the
|---|---|---|
| `~/.claude/team/<name>.md` | `claude-team show`, `claude-team use` | copied from `profiles/` |
| `~/.claude/agents/<name>.md` | delegation ("have robin review this diff") | regenerated from `profiles/` |
| `~/.claude/commands/<name>.md` | the `/<name>` slash command | copied from `commands/` |
| `~/.claude/commands/<name>.md` | the `/<name>` slash command | regenerated from `profiles/` |

Editing the installed profile updates the first and silently leaves the other two stale, with nothing to warn you. `sync` regenerates both derived files and reinstalls all three.

Editing the installed profile updates the first and silently leaves the other two stale, with nothing to warn you. `sync` regenerates the subagent and reinstalls all three.
Both `agents/` and `commands/` are generated by `scripts/generate-agents.sh`, which `sync` runs for you. Never edit them by hand; the next sync overwrites your change. The test suite fails if either drifts from its profile.

The slash command is the one piece `sync` cannot generate, since `commands/` is hand-maintained: it is the profile with the Required Interactive Behaviors section excised, wrapped in a switch preamble. For a brand-new persona, copy `commands/robin.md` to `commands/yourname.md` and swap the body in. The test suite fails if a slash command drifts from its profile.
A profile needs a `## Greeting` section, holding the one line the persona says when you switch to it with `/<name>`. The generator refuses to run without it, so a new persona cannot ship a slash command that ends in a bare separator. `## Greeting` is excised from the delegation subagent, which is invoked rather than switched to and has nobody to greet.

---

Expand Down Expand Up @@ -880,28 +884,37 @@ See [ROADMAP.md](ROADMAP.md) for the living roadmap with current priorities and

For the full version history, see [DEVLOG.md](DEVLOG.md).

### v0.4
The `0.4` through `0.7` numbers used during development are retired. v1 is the first generation of the tool. v2 is what ships today.

**Sage (Business Advisor)** — business formation, financial ops, legal awareness, fundraising literacy, compliance basics. Clear professional-advice boundary: Sage flags exactly when to consult a licensed attorney, CPA, or financial advisor. Expanded the team to eleven specialists.
### v2.0 (current)

### v0.5
**A team you can rely on across sessions, installs, and edits**

**Kai (UX Design & Visual Art)** — wireframes, HTML/CSS mockups, visual design, AI image generation via Hugging Face MCP (FLUX.1, Qwen-Image). Clear boundary with Sasha: Kai designs the visual target, Sasha implements it in production code. Expanded the team to twelve specialists.
- Session-scoped personas: parallel sessions each keep their own specialist, with no cross-talk
- `claude-team launch <persona>` opens a dedicated session with the persona as system prompt, on its tier model
- Seventeen delegation subagents, so any session can hand work to a specialist without switching
- Plugin packaging: commands, agents, hooks, and the CLI installed in one step
- Worktree-isolated `/parallel`, so session plans never switch branches in a shared checkout
- `claude-team sync` propagates a profile edit to all three installed copies
- `claude-team install-hook` registers session context on the clone install path
- Plain technical English standard for the six coding specialists ([WRITING.md](WRITING.md))
- 135-test suite covering the CLI commands, both coordinator modes, and the install path

### v0.6 (current)
### v1.0

**Two-mode coordinator + branch hygiene infrastructure**
**The specialist roster, the coordinator, and branch hygiene**

- Casual mode (default): no branch enforcement — commit directly to `main`
- Prod mode (opt-in): branch required before any code, worktree isolation, MR/PR workflow
- `/prod-mode` and `/casual-mode` slash commands
- **Sage (Business Advisor):** business formation, financial ops, legal awareness, fundraising literacy, compliance basics. Clear professional-advice boundary: Sage flags exactly when to consult a licensed attorney, CPA, or financial advisor.
- **Kai (UX Design & Visual Art):** wireframes, HTML/CSS mockups, visual design, AI image generation via Hugging Face MCP (FLUX.1, Qwen-Image). Clear boundary with Sasha: Kai designs the visual target, Sasha implements it in production code.
- **Two-mode coordinator:** casual mode (default) applies no branch enforcement, so you commit directly to `main`. Prod mode is an opt-in that requires a branch before any code, with worktree isolation and an MR/PR workflow.
- `/prod-mode` and `/casual-mode` slash commands for mid-session toggling
- `claude-team branch` and `claude-team session` command families
- 82-test suite covering all CLI commands and both coordinator modes
- Parallel sessions: independent work streams, each with a dedicated team member, scoped task, and explicit file boundary

### Later — Exploring with the Community

If any of these would change how you use the tool, [open an issue](https://github.com/code-katz/claude-team-cli/issues).

- **Local profile overrides:** `~/.claude/team/local/` for per-user customizations without forking the repo
- **Local profile overrides:** `~/.claude/team/local/` for per-user customizations without forking the repo. This is the next thing we want to build. `claude-team sync` made persona edits stick across all three copies, but the edit still lives in tracked files that the next `git pull` overwrites. Overrides are what turn "customize a persona" into something you only have to do once.
- **Team-scoped profiles:** `claude-team init` creates a `.claude-team/` config in a project repo, shared across the dev team
- **Session handoff briefing:** when switching team members mid-task, the coordinator generates a structured briefing so the incoming specialist doesn't start cold
Loading
Loading