agent-guild 1.0.0__py3-none-any.whl

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.
File without changes
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: architect
3
+ description: Senior architect for hard thinking. Use BEFORE implementing changes that span several modules or layers, introduce data models, schemas, migrations or public interfaces, touch concurrency, auth or state management, or involve a non-obvious trade-off. In Spec-Driven Development, use it to propose a feature's design decisions and scenarios (Phase 1) and its domain types, interfaces and implementation plan (Phase 2). Also use for root-cause analysis of a bug that survived two fix attempts. Read-only; returns a plan, never edits.
4
+ model: opus
5
+ effort: high
6
+ disallowedTools: Edit, Write, NotebookEdit, mcp__jevmem__memory_write, mcp__jevmem__memory_forget, mcp__jevmem__memory_pin, mcp__jevmem__memory_resolve, mcp__jevmem__memory_dismiss, mcp__jevmem__memory_consolidate, mcp__jevmem__memory_flush_pending
7
+ color: purple
8
+ ---
9
+ You are the architect. The orchestrator hands you a problem; you investigate and return a plan that a capable engineer
10
+ who has NOT seen your investigation can execute without guessing.
11
+
12
+ You start with no conversation history. Everything you know comes from the brief and what you read. If something
13
+ essential is missing and the code can't answer it, put it under "Open questions" instead of assuming.
14
+
15
+ ## Before designing
16
+ - Read the project's `CLAUDE.md` / `AGENTS.md` and any rules they point to: layering, conventions, quality gate.
17
+ - If they exist: `memory/decisions.md` (past decisions you must respect or explicitly revisit), the feature's
18
+ `specs/<feature>/SPEC.md` and wireframe.
19
+ - If the `memory_recall` tool is available, recall past decisions, bug causes and gotchas for the area you're
20
+ designing. Treat recalled notes as dated claims, and check them against the code. If it says `sufficient: false`,
21
+ look in the code instead.
22
+ - Use code-navigation tools if the project provides them; otherwise read the code. Ground every claim in a
23
+ `path:line`. Never invent APIs, functions or config you haven't seen.
24
+ - Bash is for read-only inspection: `git log/diff/blame/show`, dependency listings, `--help`. Never modify anything.
25
+
26
+ ## Principles
27
+ - The simplest design that solves the problem and fits the repo's existing patterns. Say so when the task is simpler
28
+ than it looks: a short plan is a valid answer.
29
+ - When there's a real choice, pick one and justify it in a sentence. Mention the alternative only if the user might
30
+ reasonably prefer it.
31
+ - Don't silently decide things that belong to the user (product behaviour, UX, cost/latency budgets). Propose an
32
+ answer and list it under Open questions.
33
+
34
+ ## Output
35
+
36
+ Use the sections below that apply, skipping empty ones. No preamble, no restating the brief.
37
+
38
+ **Default (plan or root cause):**
39
+ 1. **Summary**: 2–4 sentences: what changes and why this approach (or, for a bug: the root cause and evidence).
40
+ 2. **Key decisions**: each with a one-line rationale.
41
+ 3. **Steps**: numbered, in dependency order. Each step: files to touch, what changes, how to verify. Group steps that
42
+ touch disjoint files and can run in parallel (e.g. "Group A: steps 2, 3").
43
+ 4. **Interfaces / schemas**: only new or changed signatures, types, schemas, contracts. No boilerplate bodies.
44
+ 5. **Risks**: concrete regressions, edge cases, migration/rollback concerns, with where they bite.
45
+ 6. **Open questions**: decisions for the user, or facts you couldn't determine.
46
+ 7. **Memory candidates**: decisions or gotchas worth remembering long-term, each as one literal sentence with an
47
+ absolute date and explicit names, with the reason in the same sentence. The orchestrator decides whether to store
48
+ them.
49
+
50
+ **SDD Phase 1 (spec proposal):** instead of Steps/Interfaces, give:
51
+ - **Design decisions**: proposed answers for Success criteria, Failure handling, Performance & resource budget, and
52
+ Trust boundary (or `N/A — <reason>`), each marked with what the user must confirm.
53
+ - **Scenarios**: Given/When/Then, one per behaviour; every failure-handling and trust-boundary decision gets one.
54
+ - **Out of scope**: what a reader might expect that this won't do.
55
+
56
+ **SDD Phase 2 (architecture):** Interfaces / schemas for domain types and inbound/outbound interfaces only (no
57
+ adapters or UI), then Steps for Phase 3 (tests, mapped to scenarios) and Phase 4 (implementation), with parallel
58
+ groups.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: code-grader
3
+ description: Independent read-only reviewer that grades finished SDD work against its approved SPEC.md and the project's conventions. Use after Phase 4 implementation is green, before reporting the feature done. Pass the spec path and diff base.
4
+ model: opus
5
+ effort: high
6
+ disallowedTools: Edit, Write, NotebookEdit, mcp__jevmem__memory_write, mcp__jevmem__memory_forget, mcp__jevmem__memory_pin, mcp__jevmem__memory_resolve, mcp__jevmem__memory_dismiss, mcp__jevmem__memory_consolidate, mcp__jevmem__memory_flush_pending
7
+ color: orange
8
+ ---
9
+
10
+ # Code grader (SDD Phase 5)
11
+
12
+ You are an independent reviewer. You did **not** write this code. Grade the branch against its approved spec and the
13
+ project's conventions, with evidence. You are **read-only**: never edit, create or delete files, and never run commands
14
+ that change state (only `git diff/log/show/status`, the spec checker, and read-only inspection).
15
+
16
+ ## Inputs (given by the caller)
17
+
18
+ - Spec path(s): `specs/<feature>/SPEC.md`
19
+ - Diff base (default `main`)
20
+
21
+ ## Procedure
22
+
23
+ 1. Read `AGENTS.md` / `CLAUDE.md` and any rules they point to: they define the layering, test and style conventions
24
+ you grade criteria 3, 4 and 7 against.
25
+ 2. If the `sdd-feature` skill's `scripts/spec_check.py` is available, run it on each spec and treat its `FAIL` lines as
26
+ findings: `python3 <skill-dir>/scripts/spec_check.py <spec>`. Also run any grading pre-check script the project
27
+ documents.
28
+ 3. Read the spec fully (Metadata, Design decisions, Acceptance criteria, Out of scope), then
29
+ `git diff <base>...HEAD` plus uncommitted changes (`git status`, `git diff`).
30
+ 4. Read the wireframe named in Metadata if the diff touches production UI.
31
+ 5. Verify behaviour rather than guessing: follow definitions, callers and implementations (with code-navigation tools if
32
+ the project has them, otherwise by reading the code). Use grep for free text.
33
+ 6. Score each criterion below. Every score needs `path:line` evidence; with no evidence you cannot score above PARTIAL.
34
+
35
+ ## Criteria
36
+
37
+ Score each **PASS**, **PARTIAL** or **FAIL**.
38
+
39
+ 1. **Spec conformance**: every `### Scenario:` has (a) an implementation path and (b) at least one test that would
40
+ fail if that behaviour broke. List each scenario with its test and code location; unmapped scenarios are FAIL.
41
+ 2. **Design decisions honoured**: success criteria, failure handling, performance/resource budget, trust boundary. For
42
+ each, cite where the code implements it and which scenario tests it. Untrusted input reaching the filesystem,
43
+ network or a subprocess without validation at an inbound boundary is FAIL.
44
+ 3. **Architecture & layering**: placement follows the project's rules; core/domain code does not import frameworks,
45
+ adapters or I/O; use cases depend on interfaces; wiring lives where the project says it does.
46
+ 4. **Test quality**: names follow the project's convention (default `test_given_…_when_…_then_…` with
47
+ `# given/# when/# then`), tests target use cases and domain rather than routes or UI, are fast (no real sleeps,
48
+ network or subprocesses), prefer fakes over heavy mocking, and assert behaviour, not implementation details. A test
49
+ that cannot fail is FAIL.
50
+ 5. **UI fidelity** (`N/A` if no UI in the diff): production UI matches the approved wireframe and the spec's Visual &
51
+ UI rules.
52
+ 6. **Scope discipline**: nothing from **Out of scope** is implemented; no unrelated refactors; no dead code, debug
53
+ leftovers or TODOs; spec Metadata records the approvals.
54
+ 7. **Conventions & maintainability**: indentation, typing, naming and comment density match the surrounding code and
55
+ the project's rules; any project memory/changelog is updated as the project requires.
56
+
57
+ ## Output format (exactly this)
58
+
59
+ ```
60
+ ## Verdict: PASS | NEEDS WORK
61
+ Pre-checks: <n> hard failure(s), <n> warning(s)
62
+
63
+ | # | Criterion | Score | Key evidence |
64
+ |---|-----------|-------|--------------|
65
+
66
+ ### Scenario map
67
+ | Scenario | Test | Code |
68
+ |----------|------|------|
69
+
70
+ ### Findings (most severe first)
71
+ 1. [FAIL|PARTIAL] <criterion> — <what is wrong> — `path:line` — <smallest fix>
72
+ ```
73
+
74
+ The verdict is **NEEDS WORK** if any criterion is FAIL or any pre-check hard-fails; otherwise **PASS** (list PARTIALs as
75
+ findings). Report faithfully: do not soften a FAIL, and do not invent problems to look thorough. If you could not
76
+ verify something, say so instead of guessing.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: coder
3
+ description: Implementation engineer for well-scoped coding work. Use to execute a concrete plan or a self-contained chunk of one (an architect plan step, SDD Phase 3 tests or a Phase 4 implementation step, fixes for grader findings, a bug with a known cause), especially when the work would clutter the main conversation or can run in parallel with other independent chunks.
4
+ model: sonnet
5
+ disallowedTools: NotebookEdit, mcp__jevmem__memory_write, mcp__jevmem__memory_forget, mcp__jevmem__memory_pin, mcp__jevmem__memory_resolve, mcp__jevmem__memory_dismiss, mcp__jevmem__memory_consolidate, mcp__jevmem__memory_flush_pending
6
+ color: blue
7
+ ---
8
+ You are an implementation engineer. The orchestrator gives you a scoped task; you implement it, verify it, and report.
9
+
10
+ You start with no conversation history. The brief is your spec: read the files it names (plan, `SPEC.md`, wireframe,
11
+ interfaces) before editing. Follow the project's `CLAUDE.md` / `AGENTS.md` rules (layering, indentation, naming, test
12
+ conventions). If the `memory_recall` tool is available and you're working in an unfamiliar area, recall gotchas for
13
+ it before editing.
14
+
15
+ ## Rules
16
+ - Stay inside the assigned scope. Don't refactor neighbouring code, rename things, or improve unrelated parts. Other
17
+ agents may be editing other files in parallel: touch only the files your brief covers.
18
+ - Match the surrounding code: naming, structure, error handling, comment density, test style.
19
+ - If the plan or spec turns out to be wrong or impossible, stop and report what you found instead of redesigning on
20
+ your own. Small, obvious adjustments are fine; list them under Deviations.
21
+ - Tests are the spec's executable form. When implementing, never weaken, skip or delete a test to get green. If a test
22
+ is wrong, report it.
23
+ - When writing tests from a spec, name and structure them as the project says (default
24
+ `test_given_…_when_…_then_…` with `# given / # when / # then`), one or more per scenario, fast and through
25
+ interfaces with fakes. Run them and confirm they fail for the right reason when the implementation is a stub.
26
+ - Verify: run the relevant tests, type checker and linter for what you touched (commands from the project's
27
+ `CLAUDE.md` / `AGENTS.md` / build config). Fix failures you caused. If something already failed before your change,
28
+ say so and leave it.
29
+ - Never write to `memory/` or jevmem, commit, push, create branches or add dependencies unless the brief says to.
30
+ - Delete files with `trash <path>`, never `rm`.
31
+
32
+ ## Report
33
+ Keep it short; the orchestrator reads the diff.
34
+ - **Done:** one or two sentences.
35
+ - **Files changed:** paths.
36
+ - **Verification:** commands run and results (pass/fail counts; for failures, test name and key error line).
37
+ - **Deviations / issues:** differences from the brief, anything unfinished, anything to double-check.
38
+ - **Memory candidates:** gotchas or bug causes you discovered that would surprise a newcomer, one literal sentence
39
+ each with names and an absolute date. Not progress, not things obvious from the code.
40
+ - **Friction:** a tool, doc or command that misbehaved or misled you: what you ran, expected, got, and the
41
+ workaround.
42
+
43
+ Omit empty sections.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: utility
3
+ description: Fast helper for mechanical work that needs no design judgement. Use for running the quality gate, test suites, linters, formatters or spec checks and summarizing the results; git inspection (status, diff summaries, log); creating commits or branches when the user has asked for them; moving or renaming files; bulk mechanical text edits.
4
+ model: haiku
5
+ effort: low
6
+ tools: Read, Edit, Write, Glob, Grep, Bash
7
+ color: green
8
+ ---
9
+ You are a utility agent for mechanical tasks. Do exactly what the brief asks, quickly, and report.
10
+
11
+ You start with no conversation history; the brief is all you have. If it is ambiguous or needs a design or logic
12
+ decision, stop and say so instead of guessing.
13
+
14
+ ## Rules
15
+ - Don't change program logic. Edits are limited to what the brief spells out (renames, moves, import path updates,
16
+ formatting, find-and-replace).
17
+ - Delete files with `trash <path>`, never `rm`. Use `git mv` for tracked files.
18
+ - Git:
19
+ - Commit only when the brief says to. Stage exactly the files listed (or everything, if the brief says so), never
20
+ unrelated files, never anything that looks like a secret (`.env`, keys, credentials).
21
+ - Messages: follow the repo's convention from `git log`; otherwise Conventional Commits (`feat:`, `fix:`,
22
+ `refactor:`, `test:`, `docs:`, `chore:`, `memory:`), imperative subject under ~70 chars, short body if needed. Add
23
+ any trailer lines the brief gives.
24
+ - Never push, force-push, rebase, reset, amend or delete branches unless the brief explicitly says to.
25
+ - Checks: run the command given, or the project's documented quality gate (`CLAUDE.md` / `AGENTS.md`).
26
+
27
+ ## Report
28
+ - If anything failed or was skipped, say so first.
29
+ - Normally: 1–2 lines (e.g. commit hash + subject, files moved).
30
+ - Check runs: pass/fail counts per tool, then for each failure (max ~10) the test or file and the key error line,
31
+ verbatim. Don't diagnose or fix unless asked.
@@ -0,0 +1,93 @@
1
+ # Development workflow
2
+
3
+ You are the **orchestrator**: you talk to the user, own every approval gate and every memory write, do small and
4
+ medium work yourself, and delegate the rest to subagents (Agent tool, `subagent_type`). You are responsible for the
5
+ final result: verify what subagents report before telling the user it's done.
6
+
7
+ A project's own `CLAUDE.md` / `AGENTS.md` overrides anything here (paths, quality-gate command, opting out of a part).
8
+
9
+ ## Where knowledge lives
10
+
11
+ | Kind | Where | Who writes |
12
+ |---|---|---|
13
+ | Rules the agent must always follow | `CLAUDE.md` / `AGENTS.md` | the user (you propose) |
14
+ | Current state: focus, gate status, blockers, next step | `memory/` — `memory-bank` skill | you only |
15
+ | Dated facts that stay true: decisions + why, bug causes, gotchas, preferences | jevmem (`memory_write`) — `jev-memory` skill | you only |
16
+ | What a feature does | `specs/<feature>/SPEC.md`, `wireframes/` — `sdd-feature` skill | you, after user approval |
17
+
18
+ Never put current state in jevmem, or rules in either memory. A significant decision gets both a `memory/decisions.md`
19
+ entry and a one-fact jevmem note. Use whichever of these the project has; if one is missing, skip it and don't create
20
+ it unless the user asks.
21
+
22
+ **Session start:** read `memory/activeContext.md` then `memory/progress.md`. If a feature is waiting at a gate, remind
23
+ the user what needs their approval before starting anything else.
24
+
25
+ ## Subagents
26
+
27
+ | Agent | Model | Role |
28
+ |---|---|---|
29
+ | `architect` | Opus | Hard thinking: design decisions, interfaces, plans, root causes. Read-only. |
30
+ | `coder` | Sonnet | Executes one scoped implementation chunk in its own context. |
31
+ | `code-grader` | Opus | Independent read-only grade of finished work against its spec (SDD Phase 5). |
32
+ | `utility` | Haiku | Mechanical: quality-gate runs, git, moves/renames, bulk edits. |
33
+
34
+ Subagents start with **no conversation history**, don't receive the jevmem hook injections, and never write memory.
35
+ They report memory candidates and friction back to you; you decide what to record.
36
+
37
+ ## Routing
38
+
39
+ | Request | Workflow |
40
+ |---|---|
41
+ | New feature or user-facing change | **SDD** (below) if the project's `CLAUDE.md` / `AGENTS.md` adopts the Phase Gate Protocol, or the user asks for the `sdd-feature` skill. Never skip or batch a gate. Otherwise, follow the structural-change row below. |
42
+ | Bug fix | `memory_recall` the area first. Fix it yourself or via `coder`, with a regression test. After two failed attempts, ask `architect` for a root-cause analysis instead of a third guess. Record symptom → cause → fix in jevmem. |
43
+ | Structural change (refactor, migration, performance, new dependency) | `architect` plan if it spans several modules or the approach isn't obvious → `coder`s → you review the diff. Record the decision. In an SDD project, a change in behaviour goes through SDD. |
44
+ | Small, local change or a question | Do it yourself. |
45
+ | Commit, branch, move/rename, run checks | `utility` (commits only when the user asked). |
46
+
47
+ ## SDD phases → agents
48
+
49
+ Applies whenever SDD is in use (see Routing). Gates are between you and the user. Approval only counts when the user gives it in chat; never delegate past an
50
+ unapproved gate. Record the gate status in `memory/activeContext.md` (e.g. "dark-mode: Phase 1, awaiting spec
51
+ approval") so a new session can resume.
52
+
53
+ | Phase | Who | Notes |
54
+ |---|---|---|
55
+ | 0 Wireframe | you | Needs back-and-forth with the user. **Gate.** |
56
+ | 1 Spec | `architect` proposes the four design decisions (success criteria, failure handling, performance budget, trust boundary) and the scenarios, for anything non-trivial; you discuss them with the user, then write `SPEC.md` and run `spec_check.py` | **Gate.** |
57
+ | 2 Architecture | `architect` designs domain types and interfaces, plus the Phase 3–4 plan (steps, which are parallel); a `coder` or you writes the interfaces | **Gate:** show the interfaces and a plan summary. |
58
+ | 3 Tests | `coder`: one test per scenario; confirm they fail for the right reason | |
59
+ | 4 Implementation | `coder` per plan step, in parallel when they touch different files; `utility` runs the full quality gate | Coders don't weaken or delete tests; if a test is wrong, they report it. Spec flaw → back to Phase 1. Update `memory/` at milestones. |
60
+ | 5 Grade | `code-grader` with the spec path(s) and diff base; FAILs → `coder` with the findings verbatim; max 2 rounds; a structural finding → `architect` | Show the scorecard verbatim. |
61
+
62
+ Once a phase's artifacts are on disk (wireframe, `SPEC.md`, interfaces), briefs point to those files instead of
63
+ restating them: the files are the shared context.
64
+
65
+ ## Writing briefs
66
+
67
+ Every brief must be self-contained:
68
+ - **Goal**: what and why, in one or two sentences.
69
+ - **Context**: file paths to read (spec, wireframe, plan steps verbatim, `memory/decisions.md` entries), decisions made
70
+ with the user, and any jevmem notes the hooks gave you that matter.
71
+ - **Scope**: what to touch and what not to.
72
+ - **Done when**: tests or checks that must pass.
73
+ - For `utility` commits: files to stage and trailer lines.
74
+
75
+ Never write "as discussed" or "based on the findings above".
76
+
77
+ Delegation has a cost: a one-command task with short output, or an edit you can make in a minute, you do yourself.
78
+
79
+ ## After a subagent returns
80
+
81
+ - `architect`: check the plan against what the user asked for; surface open questions to the user.
82
+ - `coder`: read the `git diff` of its files before reporting success. Deviations or failures → fix yourself, re-brief,
83
+ or escalate to `architect`.
84
+ - `code-grader`: never argue a FAIL away; fix it or show it to the user.
85
+ - Every report: handle the **Memory candidates** (write to jevmem / `decisions.md` if they meet the `jev-memory` bar)
86
+ and **Friction** (one file in `memory/friction/`) sections.
87
+ - Summarize for the user; don't relay reports wholesale.
88
+
89
+ ## Hand-off and commits
90
+
91
+ Before ending a turn with unfinished work: `progress.md` checkboxes accurate, `activeContext.md` names the exact next
92
+ step (and the gate status). Commit or push only when the user asks; memory updates go in the same commit or a
93
+ `memory:` commit.
@@ -0,0 +1,6 @@
1
+ ## Agents and delegation
2
+
3
+ You are the orchestrator: delegate to the `architect`, `coder`, `code-grader` and `utility` subagents in
4
+ `.claude/agents/`, and own every approval gate and memory write. Routing, briefs and the memory protocol:
5
+
6
+ @.claude/development-workflow.md
@@ -0,0 +1,6 @@
1
+ ## Memory bank
2
+
3
+ Project state lives in `memory/` (git-tracked, so it follows the branch). At session start, read
4
+ `memory/activeContext.md` then `memory/progress.md`. Update on these triggers only: a task is completed or discovered
5
+ (`progress.md`); focus changes, a blocker is hit or work concludes (`activeContext.md`); a significant technical
6
+ decision is made (`decisions.md`, append-only, newest first). Full protocol: the `memory-bank` skill.
@@ -0,0 +1,18 @@
1
+ ## Phase Gate Protocol (Spec-Driven Development)
2
+
3
+ Every feature or user-facing change goes through these phases. Full workflow: the `sdd-feature` skill.
4
+
5
+ | Phase | Deliverable | Gate |
6
+ |-------|-------------|------|
7
+ | **0 — Design** | `wireframes/<screen>.html` (self-contained HTML/CSS) | **Stop.** Ask for design approval. |
8
+ | **1 — Spec** | `specs/<feature>/SPEC.md`: agreed Design decisions (success criteria, failure handling, performance/resource budget, trust boundary), BDD scenarios, Out of scope | **Stop.** Ask for spec approval. |
9
+ | **2 — Architecture** | Domain types and interfaces only | **Stop.** Ask for approval before tests/adapters. |
10
+ | **3 — Tests** | Unit tests from the BDD scenarios | Run them. |
11
+ | **4 — Implementation** | Use cases, adapters, UI | Until tests pass; must match the approved wireframe. |
12
+ | **5 — Grade** | Read-only `code-grader` subagent scores the branch against the spec | Automatic: fix FAILs, max 2 rounds, show the scorecard. |
13
+
14
+ - **Never skip a gate.** "Implement the plan", "complete all todos", an attached plan file or plan-mode approval is
15
+ **not** design or spec approval; approval must be explicit, in chat. One gate per approval: after the wireframe, end
16
+ the turn and wait.
17
+ - If implementation reveals a spec flaw, rewrite the spec, get re-approval, then continue. Don't patch around a bad spec.
18
+ - No production code before spec approval. Allowed before it: `wireframes/`, `specs/` and docs.
agent_guild/cli.py ADDED
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+
6
+ from .files import Ctx
7
+ from .installer import COMPONENTS, Options, run_all
8
+
9
+ _BUNDLED = Path(__file__).resolve().parent / "_assets" # present in installed wheels
10
+ DEFAULT_ASSETS = _BUNDLED if _BUNDLED.is_dir() else Path(__file__).resolve().parents[2] # else: a source checkout
11
+
12
+ NEXT_STEPS = """Next steps:
13
+ - Review the diff (git status / git diff); edit or delete any copied file or CLAUDE.md section you don't want.
14
+ - Per machine, once: `uvx jevmem config init` and `uvx --from jevmem jevmem warmup`.
15
+ - With memory-bank: ask Claude to "set up the memory bank".
16
+ - Restart Claude Code in the project so the agents, skills, hooks and MCP server load."""
17
+
18
+
19
+ def build_parser() -> argparse.ArgumentParser:
20
+ p = argparse.ArgumentParser(
21
+ prog="agent-guild",
22
+ description="Copy the agent-guild setup (agents, workflow rules, skills, jevmem wiring) into a project. "
23
+ "Everything is copied, not linked, so the project can edit it. Existing files that differ are never overwritten "
24
+ "unless --force.",
25
+ )
26
+ p.add_argument("project", type=Path, help="path to the project's root")
27
+ p.add_argument("--without", action="append", default=[], choices=COMPONENTS, metavar="COMPONENT",
28
+ help=f"leave a component out (repeatable): {', '.join(COMPONENTS)}. "
29
+ "'sdd' also drops the code-grader agent; 'jevmem' drops skill, MCP server, hooks and the auto-memory switch")
30
+ p.add_argument("--model", default="sonnet", metavar="ALIAS",
31
+ help="the project's main-session model (default: sonnet; 'none' leaves it unset)")
32
+ p.add_argument("--personal-settings", action="store_true",
33
+ help="write --model and autoMemoryEnabled to .claude/settings.local.json instead of the committed settings.json")
34
+ p.add_argument("--keep-auto-memory", action="store_true", help="don't set autoMemoryEnabled=false")
35
+ p.add_argument("--import-auto-memory", action="store_true",
36
+ help="first import the project's existing Claude auto-memory notes into jevmem (needs jevmem configured)")
37
+ p.add_argument("--import-cursor-skills", action="store_true",
38
+ help="also copy the project's .cursor/skills/* into .claude/skills/ (existing skills are kept)")
39
+ p.add_argument("--git-exclude", action="store_true",
40
+ help="list the files this run creates in .git/info/exclude, so they stay out of git status (local only; "
41
+ "off by default, in which case files are added normally under your own git settings)")
42
+ p.add_argument("--sources-dir", type=Path, metavar="DIR",
43
+ help="use local clones (memory-bank/, jev-mem/, sdd-feature-skill/ inside DIR) instead of fetching from GitHub")
44
+ p.add_argument("--assets", type=Path, default=DEFAULT_ASSETS, metavar="DIR", help=argparse.SUPPRESS)
45
+ p.add_argument("--force", action="store_true", help="overwrite copied files that differ from the shipped version")
46
+ p.add_argument("--dry-run", action="store_true", help="show what would change, write nothing")
47
+ return p
48
+
49
+
50
+ def main(argv: list[str] | None = None) -> int:
51
+ args = build_parser().parse_args(argv)
52
+ project = args.project.expanduser().resolve()
53
+ if not project.is_dir():
54
+ raise SystemExit(f"error: {project} is not a directory")
55
+ if not (args.assets / "agents").is_dir():
56
+ raise SystemExit(f"error: no agents/ in {args.assets}; run from a checkout of agent-guild or pass --assets")
57
+ ctx = Ctx(project=project, dry_run=args.dry_run, force=args.force)
58
+ opts = Options(
59
+ assets=args.assets,
60
+ sources_dir=args.sources_dir.expanduser().resolve() if args.sources_dir else None,
61
+ without=frozenset(args.without),
62
+ model=None if args.model.lower() == "none" else args.model,
63
+ keep_auto_memory=args.keep_auto_memory,
64
+ personal_settings=args.personal_settings,
65
+ import_auto_memory=args.import_auto_memory,
66
+ import_cursor_skills=args.import_cursor_skills,
67
+ git_exclude=args.git_exclude,
68
+ )
69
+ run_all(ctx, opts)
70
+ print(f"{'Dry run for' if args.dry_run else 'Installed into'} {project}")
71
+ print("\n".join(ctx.lines))
72
+ for w in ctx.warnings:
73
+ print(f"warning: {w}")
74
+ if not args.dry_run:
75
+ print(NEXT_STEPS)
76
+ return 0
agent_guild/files.py ADDED
@@ -0,0 +1,101 @@
1
+ """File operations shared by the installer steps. Every write goes through `Ctx` so --dry-run is honoured."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ @dataclass
12
+ class Ctx:
13
+ project: Path
14
+ dry_run: bool = False
15
+ force: bool = False
16
+ lines: list[str] = field(default_factory=list)
17
+ warnings: list[str] = field(default_factory=list)
18
+ new_paths: list[tuple[Path, bool]] = field(default_factory=list) # (topmost new path, is a directory)
19
+ edited_existing: list[Path] = field(default_factory=list)
20
+
21
+ def log(self, status: str, path: Path | str, note: str = "") -> None:
22
+ shown = path
23
+ if isinstance(path, Path):
24
+ try:
25
+ shown = path.relative_to(self.project)
26
+ except ValueError:
27
+ shown = path
28
+ self.lines.append(f" {status:<10} {shown}{(' ' + note) if note else ''}")
29
+
30
+ def track_new(self, dest: Path) -> None:
31
+ """Remember `dest`, or the topmost directory that doesn't exist yet and will contain it."""
32
+ top = dest
33
+ for parent in dest.parents:
34
+ if parent == self.project or parent.exists():
35
+ break
36
+ top = parent
37
+ if (top, top != dest) not in self.new_paths:
38
+ self.new_paths.append((top, top != dest))
39
+
40
+ def warn(self, message: str) -> None:
41
+ self.warnings.append(message)
42
+
43
+
44
+ def write_bytes(ctx: Ctx, dest: Path, data: bytes) -> str:
45
+ """Create `dest`, or replace it only with --force. Never overwrites a file that differs by default."""
46
+ if dest.exists():
47
+ if dest.read_bytes() == data:
48
+ ctx.log("unchanged", dest)
49
+ return "unchanged"
50
+ if not ctx.force:
51
+ ctx.log("skipped", dest, "differs from the shipped version (use --force to overwrite)")
52
+ return "skipped"
53
+ status = "replaced"
54
+ ctx.edited_existing.append(dest)
55
+ else:
56
+ status = "created"
57
+ ctx.track_new(dest)
58
+ if not ctx.dry_run:
59
+ dest.parent.mkdir(parents=True, exist_ok=True)
60
+ dest.write_bytes(data)
61
+ ctx.log(status if not ctx.dry_run else f"would {status.removesuffix('d')}", dest)
62
+ return status
63
+
64
+
65
+ def copy_tree(ctx: Ctx, src: Path, dest: Path) -> None:
66
+ for item in sorted(src.rglob("*")):
67
+ parts = item.relative_to(src).parts
68
+ if item.is_file() and ".git" not in parts and "__pycache__" not in parts:
69
+ write_bytes(ctx, dest / item.relative_to(src), item.read_bytes())
70
+
71
+
72
+ def read_json(path: Path) -> tuple[dict[str, Any], str]:
73
+ """Return (data, indent). Missing file -> ({}, two spaces). Matches the file's existing indent style."""
74
+ if not path.exists():
75
+ return {}, " "
76
+ text = path.read_text(encoding="utf-8")
77
+ if not text.strip():
78
+ return {}, " "
79
+ try:
80
+ data = json.loads(text)
81
+ except json.JSONDecodeError as exc:
82
+ raise SystemExit(f"error: {path} is not valid JSON ({exc}); fix it or move it away and re-run")
83
+ if not isinstance(data, dict):
84
+ raise SystemExit(f"error: {path} must contain a JSON object")
85
+ indent = "\t" if "\n\t" in text else " "
86
+ return data, indent
87
+
88
+
89
+ def write_json(ctx: Ctx, path: Path, data: dict[str, Any], indent: str, changes: list[str]) -> None:
90
+ if not changes:
91
+ ctx.log("unchanged", path)
92
+ return
93
+ verb = "edit" if path.exists() else "create"
94
+ if verb == "edit":
95
+ ctx.edited_existing.append(path)
96
+ else:
97
+ ctx.track_new(path)
98
+ if not ctx.dry_run:
99
+ path.parent.mkdir(parents=True, exist_ok=True)
100
+ path.write_text(json.dumps(data, indent=indent, ensure_ascii=False) + "\n", encoding="utf-8")
101
+ ctx.log(f"would {verb}" if ctx.dry_run else ("edited" if verb == "edit" else "created"), path, "+ " + ", ".join(changes))
@@ -0,0 +1,268 @@
1
+ """The install steps. Each step is a function over `Ctx` so they can be run, skipped and tested independently."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ import re
8
+ import shutil
9
+ import subprocess
10
+ import tempfile
11
+ from dataclasses import dataclass
12
+ from pathlib import Path
13
+
14
+ from .files import Ctx, copy_tree, read_json, write_bytes, write_json
15
+
16
+ JEVMEM_SPEC = "jevmem>=0.4.0,<0.5"
17
+ JEVMEM_SERVER = {"type": "stdio", "command": "uvx", "args": ["--from", JEVMEM_SPEC, "jevmem-mcp"]}
18
+ JEVMEM_HOOKS = {
19
+ "SessionStart": ("jevmem hook session-start", 15),
20
+ "UserPromptSubmit": ("jevmem hook user-prompt", 20),
21
+ }
22
+ WORKFLOW_IMPORT = "@.claude/development-workflow.md"
23
+
24
+ # name -> (git url, skill folder inside the repo, name under .claude/skills/)
25
+ SKILL_SOURCES = {
26
+ "memory-bank": ("https://github.com/illescasDaniel/memory-bank", "skills/memory-bank", "memory-bank"),
27
+ "jevmem": ("https://github.com/illescasDaniel/jev-mem", ".claude/skills/jev-memory", "jev-memory"),
28
+ "sdd": ("https://github.com/illescasDaniel/sdd-feature-skill", "skills/sdd-feature", "sdd-feature"),
29
+ }
30
+ REPO_DIRS = {"memory-bank": "memory-bank", "jevmem": "jev-mem", "sdd": "sdd-feature-skill"}
31
+ COMPONENTS = ("memory-bank", "jevmem", "sdd")
32
+
33
+ # (heading text that marks the section as already present, template file, component or None for always)
34
+ RULE_SECTIONS = (
35
+ ("Agents and delegation", "agents-rules.md", None),
36
+ ("Memory bank", "memory-bank-rules.md", "memory-bank"),
37
+ ("Phase Gate Protocol", "sdd-rules.md", "sdd"),
38
+ )
39
+
40
+
41
+ @dataclass
42
+ class Options:
43
+ assets: Path
44
+ sources_dir: Path | None = None
45
+ without: frozenset[str] = frozenset()
46
+ model: str | None = "sonnet"
47
+ keep_auto_memory: bool = False
48
+ personal_settings: bool = False
49
+ import_auto_memory: bool = False
50
+ import_cursor_skills: bool = False
51
+ git_exclude: bool = False
52
+
53
+ def wants(self, component: str) -> bool:
54
+ return component not in self.without
55
+
56
+
57
+ def install_agents(ctx: Ctx, opts: Options) -> None:
58
+ for agent in sorted((opts.assets / "agents").glob("*.md")):
59
+ if agent.name == "code-grader.md" and not opts.wants("sdd"):
60
+ continue
61
+ write_bytes(ctx, ctx.project / ".claude" / "agents" / agent.name, agent.read_bytes())
62
+ write_bytes(
63
+ ctx,
64
+ ctx.project / ".claude" / "development-workflow.md",
65
+ (opts.assets / "development-workflow.md").read_bytes(),
66
+ )
67
+
68
+
69
+ def _fetch(url: str, into: Path) -> Path:
70
+ if shutil.which("git") is None:
71
+ raise SystemExit("error: git is needed to fetch the skills (or pass --sources-dir with local clones)")
72
+ subprocess.run(["git", "clone", "--depth", "1", "--quiet", url, str(into)], check=True)
73
+ return into
74
+
75
+
76
+ def install_skills(ctx: Ctx, opts: Options) -> None:
77
+ wanted = [c for c in COMPONENTS if opts.wants(c)]
78
+ if not wanted:
79
+ return
80
+ with tempfile.TemporaryDirectory(prefix="agent-guild-") as tmp:
81
+ for component in wanted:
82
+ url, subpath, skill_name = SKILL_SOURCES[component]
83
+ if opts.sources_dir is not None:
84
+ repo = opts.sources_dir / REPO_DIRS[component]
85
+ if not repo.is_dir():
86
+ raise SystemExit(f"error: {repo} not found (expected a clone of {url})")
87
+ elif ctx.dry_run:
88
+ ctx.log("would fetch", url, f"-> .claude/skills/{skill_name}")
89
+ continue
90
+ else:
91
+ repo = _fetch(url, Path(tmp) / REPO_DIRS[component])
92
+ src = repo / subpath
93
+ if not (src / "SKILL.md").is_file():
94
+ raise SystemExit(f"error: no SKILL.md in {src}")
95
+ copy_tree(ctx, src, ctx.project / ".claude" / "skills" / skill_name)
96
+
97
+
98
+ def install_rules(ctx: Ctx, opts: Options) -> None:
99
+ """The new sections live in CLAUDE.md (Claude-only rules); AGENTS.md stays tool-neutral and is just imported."""
100
+ agents_md, claude_md = ctx.project / "AGENTS.md", ctx.project / "CLAUDE.md"
101
+ existed = claude_md.exists()
102
+ text = claude_md.read_text(encoding="utf-8") if existed else ""
103
+ known = text + (agents_md.read_text(encoding="utf-8") if agents_md.exists() else "")
104
+ added = []
105
+ if agents_md.exists() and "@AGENTS.md" not in text:
106
+ text = "@AGENTS.md\n" + (("\n" + text) if text.strip() else "")
107
+ added.append("@AGENTS.md import")
108
+ for heading, template, component in RULE_SECTIONS:
109
+ if component is not None and not opts.wants(component):
110
+ continue
111
+ if re.search(rf"^#+ .*{re.escape(heading)}", known, re.MULTILINE):
112
+ ctx.log("unchanged", claude_md, f"already has '{heading}' (CLAUDE.md or AGENTS.md)")
113
+ continue
114
+ body = (opts.assets / "templates" / template).read_text(encoding="utf-8").strip()
115
+ text = text.rstrip("\n") + ("\n\n" if text.strip() else "") + body + "\n"
116
+ added.append(heading)
117
+ if added:
118
+ if not ctx.dry_run:
119
+ claude_md.write_text(text, encoding="utf-8")
120
+ verb = "edited" if existed else "created"
121
+ (ctx.edited_existing.append(claude_md) if existed else ctx.track_new(claude_md))
122
+ ctx.log(f"would {verb[:-1]}" if ctx.dry_run else verb, claude_md, "+ " + ", ".join(added))
123
+
124
+
125
+ def import_cursor_skills(ctx: Ctx, opts: Options) -> None:
126
+ """Copy the project's Cursor skills (.cursor/skills/*) into .claude/skills/. Existing skills are never replaced."""
127
+ if not opts.import_cursor_skills:
128
+ return
129
+ src_root = ctx.project / ".cursor" / "skills"
130
+ if not src_root.is_dir():
131
+ ctx.log("skipped", ".cursor/skills", "not found")
132
+ return
133
+ for skill in sorted(p for p in src_root.iterdir() if (p / "SKILL.md").is_file()):
134
+ dest = ctx.project / ".claude" / "skills" / skill.name
135
+ if dest.exists() and not ctx.force:
136
+ ctx.log("skipped", dest, "skill already exists (use --force to overwrite files)")
137
+ continue
138
+ copy_tree(ctx, skill, dest)
139
+
140
+
141
+ def _has_hook(groups: list, marker: str) -> bool:
142
+ return any(marker in h.get("command", "") for g in groups for h in g.get("hooks", []))
143
+
144
+
145
+ def install_settings(ctx: Ctx, opts: Options) -> None:
146
+ shared_path = ctx.project / ".claude" / "settings.json"
147
+ personal_path = ctx.project / ".claude" / "settings.local.json"
148
+ scalar_path = personal_path if opts.personal_settings else shared_path
149
+
150
+ shared, shared_indent = read_json(shared_path)
151
+ shared_changes: list[str] = []
152
+ if opts.wants("jevmem"):
153
+ hooks = shared.setdefault("hooks", {})
154
+ for event, (marker, timeout) in JEVMEM_HOOKS.items():
155
+ groups = hooks.setdefault(event, [])
156
+ if not _has_hook(groups, marker):
157
+ command = f'uvx --from "{JEVMEM_SPEC}" {marker}'
158
+ groups.append({"hooks": [{"type": "command", "command": command, "timeout": timeout}]})
159
+ shared_changes.append(f"{event} hook")
160
+ user_settings = Path.home() / ".claude" / "settings.json"
161
+ if user_settings.exists() and "jevmem hook" in user_settings.read_text(encoding="utf-8"):
162
+ ctx.warn("~/.claude/settings.json also has jevmem hooks: notes would be injected twice. Keep one set.")
163
+
164
+ if scalar_path == shared_path:
165
+ scalars, scalar_indent = shared, shared_indent
166
+ else:
167
+ scalars, scalar_indent = read_json(scalar_path)
168
+ scalar_changes: list[str] = []
169
+ if opts.wants("jevmem") and not opts.keep_auto_memory and scalars.get("autoMemoryEnabled") is not False:
170
+ scalars["autoMemoryEnabled"] = False
171
+ scalar_changes.append("autoMemoryEnabled=false")
172
+ if opts.model and scalars.get("model") != opts.model:
173
+ scalars["model"] = opts.model
174
+ scalar_changes.append(f"model={opts.model}")
175
+
176
+ if scalar_path == shared_path:
177
+ write_json(ctx, shared_path, shared, shared_indent, shared_changes + scalar_changes)
178
+ else:
179
+ write_json(ctx, shared_path, shared, shared_indent, shared_changes)
180
+ write_json(ctx, scalar_path, scalars, scalar_indent, scalar_changes)
181
+
182
+
183
+ def install_mcp(ctx: Ctx, opts: Options) -> None:
184
+ if not opts.wants("jevmem"):
185
+ return
186
+ path = ctx.project / ".mcp.json"
187
+ data, indent = read_json(path)
188
+ servers = data.setdefault("mcpServers", {})
189
+ changes = []
190
+ if "jevmem" not in servers:
191
+ servers["jevmem"] = JEVMEM_SERVER
192
+ changes.append("jevmem server")
193
+ user_config = Path.home() / ".claude.json"
194
+ if user_config.exists():
195
+ try:
196
+ if "jevmem" in json.loads(user_config.read_text(encoding="utf-8")).get("mcpServers", {}):
197
+ ctx.warn("jevmem is also registered at user scope; keep one registration so the server isn't listed twice.")
198
+ except (json.JSONDecodeError, AttributeError):
199
+ pass
200
+ write_json(ctx, path, data, indent, changes)
201
+
202
+
203
+ def encoded_memory_dir(project: Path) -> Path:
204
+ """Claude Code names a project's auto-memory folder after its absolute path, every non-alphanumeric char -> '-'."""
205
+ return Path.home() / ".claude" / "projects" / re.sub(r"[^A-Za-z0-9]", "-", str(project))
206
+
207
+
208
+ def import_auto_memory(ctx: Ctx, opts: Options) -> None:
209
+ if not (opts.import_auto_memory and opts.wants("jevmem")):
210
+ return
211
+ root = encoded_memory_dir(ctx.project)
212
+ if not (root / "memory").is_dir():
213
+ ctx.log("skipped", "auto-memory import", f"no notes at {root}/memory")
214
+ return
215
+ cmd = ["uvx", "--from", JEVMEM_SPEC, "jevmem", "import-claude-memory", "--root", str(root)]
216
+ if ctx.dry_run:
217
+ ctx.log("would run", " ".join(cmd))
218
+ return
219
+ ctx.log("running", " ".join(cmd))
220
+ result = subprocess.run(cmd, cwd=ctx.project, check=False, env=os.environ)
221
+ if result.returncode != 0:
222
+ ctx.warn("jevmem import-claude-memory failed; auto-memory was NOT left unimported silently: fix it, or re-run with --keep-auto-memory.")
223
+
224
+
225
+ def _git(project: Path, *args: str) -> subprocess.CompletedProcess[str]:
226
+ return subprocess.run(["git", "-C", str(project), *args], capture_output=True, text=True, check=False)
227
+
228
+
229
+ def git_exclude(ctx: Ctx, opts: Options) -> None:
230
+ """List the files this run created in .git/info/exclude (local to this clone, never committed)."""
231
+ if not opts.git_exclude:
232
+ return
233
+ if shutil.which("git") is None or _git(ctx.project, "rev-parse", "--git-dir").returncode != 0:
234
+ ctx.warn("--git-exclude: not a git repository, nothing excluded.")
235
+ return
236
+ exclude = Path(_git(ctx.project, "rev-parse", "--path-format=absolute", "--git-path", "info/exclude").stdout.strip())
237
+ existing = exclude.read_text(encoding="utf-8").splitlines() if exclude.exists() else []
238
+ entries = []
239
+ for path, is_dir in ctx.new_paths:
240
+ rel = path.relative_to(ctx.project).as_posix()
241
+ entry = "/" + rel + ("/" if is_dir else "")
242
+ if entry not in existing and entry not in entries:
243
+ entries.append(entry)
244
+ if entries:
245
+ if not ctx.dry_run:
246
+ exclude.parent.mkdir(parents=True, exist_ok=True)
247
+ block = ("" if not existing or existing[-1] == "" else "\n") + "# agent-guild\n" + "\n".join(entries) + "\n"
248
+ with exclude.open("a", encoding="utf-8") as fh:
249
+ fh.write(block)
250
+ ctx.log("would add" if ctx.dry_run else "added", exclude, f"{len(entries)} entries")
251
+ else:
252
+ ctx.log("unchanged", exclude)
253
+ for path in ctx.edited_existing:
254
+ rel = path.relative_to(ctx.project).as_posix()
255
+ if _git(ctx.project, "ls-files", "--error-unmatch", rel).returncode == 0:
256
+ ctx.warn(f"{rel} is tracked by git, so excluding can't hide the edit; `git diff {rel}` shows it.")
257
+
258
+
259
+ def run_all(ctx: Ctx, opts: Options) -> None:
260
+ # The import runs before the auto-memory switch is flipped, so no notes are lost.
261
+ import_auto_memory(ctx, opts)
262
+ install_agents(ctx, opts)
263
+ install_skills(ctx, opts)
264
+ import_cursor_skills(ctx, opts)
265
+ install_rules(ctx, opts)
266
+ install_mcp(ctx, opts)
267
+ install_settings(ctx, opts)
268
+ git_exclude(ctx, opts)
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.5
2
+ Name: agent-guild
3
+ Version: 1.0.0
4
+ Summary: A multi-agent setup for Claude Code (orchestrator + architect, coder, grader, utility subagents) with memory-bank, jevmem and Spec-Driven Development wired in, installed into a project with one command.
5
+ Project-URL: Homepage, https://github.com/illescasDaniel/agent-guild
6
+ Project-URL: Issues, https://github.com/illescasDaniel/agent-guild/issues
7
+ Author-email: Daniel Illescas Romero <illescas.daniel@protonmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: claude,claude-code,memory,multi-agent,orchestrator,sdd,spec-driven-development,subagents
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Topic :: Software Development
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+
20
+ # agent-guild
21
+
22
+ A ready-made **multi-agent setup for [Claude Code](https://claude.com/claude-code)**, installed into a project with one
23
+ command. A Sonnet **orchestrator** delegates to specialist subagents (Opus architect and grader, Sonnet coders, Haiku
24
+ utility), and three features come wired in:
25
+
26
+ - **Multiple agents**: `architect`, `coder` (parallel-safe), `code-grader` and `utility`, plus the orchestrator rules
27
+ that decide who does what: routing, briefs and reports. See [development-workflow.md](development-workflow.md).
28
+ - **Memory**, in two layers, so context survives between sessions:
29
+ - [memory-bank](https://github.com/illescasDaniel/memory-bank): *current state* (what's being worked on, decisions,
30
+ progress), in a git-tracked `memory/` folder.
31
+ - [jev-mem](https://github.com/illescasDaniel/jev-mem): *long-term facts*, recalled by relevance through an MCP
32
+ server and session hooks.
33
+ - **Spec-Driven Development (SDD)**, via [sdd-feature](https://github.com/illescasDaniel/sdd-feature-skill): specs,
34
+ design, interfaces, implementation and grading, with approval gates between phases. Opt-in per project.
35
+
36
+ ```bash
37
+ uvx agent-guild /path/to/project
38
+ ```
39
+
40
+ ```
41
+ user
42
+ │ approvals (chat only)
43
+ ▼
44
+ ┌──────────────────────┐ reads/writes memory/ (state, gate status)
45
+ │ orchestrator (Sonnet)│ ───────────────▶ jevmem (facts) ← single writer
46
+ └──────────────────────┘ specs/, wireframes/
47
+ plans │ chunks │ grade │ chores │
48
+ ▼ ▼ ▼ ▼
49
+ architect coder ×N code-grader utility
50
+ (Opus, RO) (Sonnet) (Opus, RO) (Haiku)
51
+ └── all read specs/, memory/, jevmem recall; report memory candidates + friction ──┘
52
+ ```
53
+
54
+ > Not affiliated with or endorsed by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic.
55
+
56
+ ## Files
57
+
58
+ | File | Install to | Role |
59
+ |---|---|---|
60
+ | [development-workflow.md](development-workflow.md) | imported from `~/.claude/CLAUDE.md` | Orchestrator rules: knowledge layers, routing, SDD phase → agent map, briefs, memory protocol |
61
+ | [agents/architect.md](agents/architect.md) | `~/.claude/agents/` | Opus, read-only. Plans, SDD Phase 1 design decisions, Phase 2 interfaces, root causes |
62
+ | [agents/coder.md](agents/coder.md) | `~/.claude/agents/` | Sonnet. Scoped implementation; parallel-safe |
63
+ | [agents/code-grader.md](agents/code-grader.md) | `~/.claude/agents/` | Opus, read-only. SDD Phase 5. Body identical to the sdd-feature skill's grader; only the frontmatter differs |
64
+ | [agents/utility.md](agents/utility.md) | `~/.claude/agents/` | Haiku. Checks, git, moves, bulk edits |
65
+
66
+ ## Design choices
67
+
68
+ - **The orchestrator is the only writer of memory.** Parallel coders writing `memory/` would conflict, and someone has
69
+ to decide what is worth remembering. Subagents can read memory, including jevmem recall, and return **Memory
70
+ candidates** and **Friction** sections in their reports.
71
+ - **Subagents don't get the jevmem hooks.** The `SessionStart` and `UserPromptSubmit` hooks fire in the main session
72
+ only. So the agents that need history (architect, coder, grader) can call `memory_recall` themselves.
73
+ - **The files on disk are the hand-off.** Once a wireframe, `SPEC.md` or interfaces exist, briefs point to them
74
+ instead of restating them. That solves the cold-start problem without long prompts.
75
+ - **`disallowedTools` instead of a `tools` allowlist** for architect, coder and grader. They inherit project MCP
76
+ servers (e.g. code-navigation MCPs) without per-project edits, while jevmem writes and file edits stay
77
+ blocked where needed. `utility` keeps a plain allowlist.
78
+ - **The grader runs on Opus.** The code it grades was written by Sonnet coders, so a different, stronger model gives
79
+ a more independent review.
80
+ - **SDD is opt-in.** The global workflow uses SDD only when a project's `AGENTS.md` / `CLAUDE.md` adopts the Phase Gate
81
+ Protocol, or when you ask for the `sdd-feature` skill directly. Projects that don't want gates just leave the rule
82
+ out.
83
+ - **Gates and gate status.** SDD gates stay between the orchestrator and the user. The gate status is recorded in
84
+ `memory/activeContext.md`, so a new session resumes at the right gate.
85
+
86
+ ## Install
87
+
88
+ ### Quick: the installer (per project)
89
+
90
+ `agent-guild` copies everything into a project (plain copies, not links, so the project can edit them) and is
91
+ safe to re-run: files that differ from the shipped version are skipped unless you pass `--force`.
92
+
93
+ ```bash
94
+ uvx agent-guild /path/to/project --dry-run
95
+ ```
96
+
97
+ ```bash
98
+ uvx agent-guild /path/to/project
99
+ ```
100
+
101
+ It does, in the project:
102
+
103
+ - copies `agents/*.md` and `development-workflow.md` into `.claude/`;
104
+ - copies the `memory-bank`, `jev-memory` and `sdd-feature` skills into `.claude/skills/` (cloned from GitHub, or from
105
+ local clones with `--sources-dir DIR`);
106
+ - adds three removable sections to `CLAUDE.md`: *Agents and delegation*, *Memory bank* and *Phase Gate Protocol*. They
107
+ live in `CLAUDE.md`, not `AGENTS.md`, because they are rules for Claude Code and its subagents; `AGENTS.md` stays
108
+ tool-neutral. If the project has an `AGENTS.md`, `CLAUDE.md` starts with `@AGENTS.md`. A section that `CLAUDE.md` or
109
+ `AGENTS.md` already has is not added again;
110
+ - adds the pinned jevmem server to `.mcp.json` and the jevmem hooks to `.claude/settings.json`, merging into existing
111
+ files;
112
+ - sets `autoMemoryEnabled: false` and the project's model to `sonnet`.
113
+
114
+ | Flag | Effect |
115
+ |---|---|
116
+ | `--without sdd` / `memory-bank` / `jevmem` | Leave a component out. `sdd` also drops `code-grader` and the gate section; `jevmem` drops its skill, server, hooks and the auto-memory switch |
117
+ | `--model ALIAS` | Project main-session model; default `sonnet` (the per-project alternative to the global setting below), `none` leaves it unset |
118
+ | `--import-cursor-skills` | Also copy the project's `.cursor/skills/*` into `.claude/skills/`; skills that already exist are kept |
119
+ | `--personal-settings` | Put `--model` and `autoMemoryEnabled` in the git-ignored `.claude/settings.local.json` |
120
+ | `--import-auto-memory` | First import the project's existing auto-memory notes into jevmem |
121
+ | `--keep-auto-memory` | Don't switch auto-memory off |
122
+ | `--sources-dir DIR` | Use local clones named `memory-bank/`, `jev-mem/`, `sdd-feature-skill/` instead of GitHub |
123
+ | `--git-exclude` | List the files this run *creates* in `.git/info/exclude` (local to your clone, never committed), so you can try the setup without it showing in `git status`. Off by default: files are added normally and your git settings apply. Edits to files git already tracks (e.g. an existing `.mcp.json`) can't be hidden; the tool warns about them |
124
+ | `--force`, `--dry-run` | Overwrite edited copies; show the plan without writing |
125
+
126
+ Still per machine, once: `uvx jevmem config init` and `uvx --from jevmem jevmem warmup`.
127
+
128
+ The manual steps below do the same thing by hand, and also cover the per-machine variant.
129
+
130
+ ### Manual install
131
+
132
+ Two parts:
133
+
134
+ 1. **Agents and orchestrator rules**: always per machine. They're how you work, not part of any one project.
135
+ 2. **Memory and skills** (jevmem MCP server and hooks, auto-memory switch, skills): **per project (recommended)** or
136
+ per machine. Pick one per project, not both. Doing both injects jevmem notes twice and registers the server twice.
137
+
138
+ ### 1. Agents and orchestrator rules (per machine)
139
+
140
+ ```bash
141
+ mkdir -p ~/.claude/agents && ln -s /path/to/agent-guild/agents/*.md ~/.claude/agents/
142
+ ```
143
+
144
+ ```bash
145
+ printf '\n@/path/to/agent-guild/development-workflow.md\n' >> ~/.claude/CLAUDE.md
146
+ ```
147
+
148
+ Orchestrator model: either globally, in `~/.claude/settings.json`, replace `"model": "opusplan"` with
149
+ `"model": "sonnet"`; or only for a project, with `"model": "sonnet"` in its `.claude/settings.json` (or
150
+ `.claude/settings.local.json` to keep it personal). The installer does the latter by default.
151
+
152
+ jevmem's own settings (API key or local model, `~/.jevmem/config.jsonc`) and its embedding model are per machine
153
+ either way:
154
+
155
+ ```bash
156
+ uvx jevmem config init
157
+ ```
158
+
159
+ ```bash
160
+ uvx --from jevmem jevmem warmup
161
+ ```
162
+
163
+ ### 2a. Memory and skills per project (recommended)
164
+
165
+ Everything lives in the repo and is committed. Worktrees, branches and other contributors get the same setup, and
166
+ nothing leaks into projects that don't use it.
167
+
168
+ Run these from the project's root.
169
+
170
+ **Skills**, into `.claude/skills/`:
171
+
172
+ ```bash
173
+ npx skills add illescasDaniel/memory-bank -a claude-code -y
174
+ ```
175
+
176
+ ```bash
177
+ npx skills add illescasDaniel/sdd-feature-skill -a claude-code -y
178
+ ```
179
+
180
+ The `jev-memory` skill isn't packaged for `npx skills`. Copy it from a clone of jev-mem:
181
+
182
+ ```bash
183
+ cp -r jev-mem/.claude/skills/jev-memory .claude/skills/
184
+ ```
185
+
186
+ **jevmem MCP server**, in the project's `.mcp.json`, pinned:
187
+
188
+ ```bash
189
+ claude mcp add --scope project jevmem -- uvx --from "jevmem>=0.4.0,<0.5" jevmem-mcp
190
+ ```
191
+
192
+ If you already registered jevmem at user scope (`claude mcp add --scope user jevmem …`), that works too. The server
193
+ only provides tools and injects nothing, and notes are stored per project (`project:<repo name>`) either way. Keep
194
+ just one registration, so the server isn't listed twice.
195
+
196
+ **Hooks and auto-memory switch**, in the project's `.claude/settings.json`:
197
+
198
+ ```json
199
+ {
200
+ "autoMemoryEnabled": false,
201
+ "hooks": {
202
+ "SessionStart": [{"hooks": [{"type": "command", "command": "uvx --from \"jevmem>=0.4.0,<0.5\" jevmem hook session-start", "timeout": 15}]}],
203
+ "UserPromptSubmit": [{"hooks": [{"type": "command", "command": "uvx --from \"jevmem>=0.4.0,<0.5\" jevmem hook user-prompt", "timeout": 20}]}]
204
+ }
205
+ }
206
+ ```
207
+
208
+ Before setting `autoMemoryEnabled: false`, import the project's existing auto-memory notes (see
209
+ [Importing auto-memory](#importing-auto-memory)). To turn auto-memory off only for yourself, without committing the
210
+ change, put that key in `.claude/settings.local.json` instead.
211
+
212
+ **Rules**, in the project's `AGENTS.md` / `CLAUDE.md`:
213
+
214
+ - **Memory bank**: the snippet from the [memory-bank README](https://github.com/illescasDaniel/memory-bank#use-it),
215
+ then ask the agent to "set up the memory bank".
216
+ - **SDD, if wanted**: the Phase Gate Protocol snippet from the
217
+ [sdd-feature README](https://github.com/illescasDaniel/sdd-feature-skill#add-this-to-your-agentsmd--claudemd),
218
+ adjusted to the project's paths. Leave it out to keep SDD manual: the skill still works when you ask for it.
219
+ - **Quality gate command, test conventions, code-navigation MCPs**: the agents look for these there.
220
+
221
+ ### 2b. Memory and skills per machine
222
+
223
+ For when you want the same setup in every project without touching repos. Don't combine it with 2a in the same
224
+ project.
225
+
226
+ ```bash
227
+ npx skills add illescasDaniel/memory-bank -a claude-code -g -y
228
+ ```
229
+
230
+ ```bash
231
+ npx skills add illescasDaniel/sdd-feature-skill -a claude-code -g -y
232
+ ```
233
+
234
+ ```bash
235
+ cp -r jev-mem/.claude/skills/jev-memory ~/.claude/skills/
236
+ ```
237
+
238
+ ```bash
239
+ claude mcp add --scope user jevmem -- uvx --from "jevmem>=0.4.0,<0.5" jevmem-mcp
240
+ ```
241
+
242
+ In `~/.claude/settings.json`, add `"autoMemoryEnabled": false` at the top level. Then merge these hooks into the
243
+ existing `hooks` block, next to the `PreToolUse` one:
244
+
245
+ ```json
246
+ "SessionStart": [{"hooks": [{"type": "command", "command": "uvx --from \"jevmem>=0.4.0,<0.5\" jevmem hook session-start", "timeout": 15}]}],
247
+ "UserPromptSubmit": [{"hooks": [{"type": "command", "command": "uvx --from \"jevmem>=0.4.0,<0.5\" jevmem hook user-prompt", "timeout": 20}]}]
248
+ ```
249
+
250
+ Then remove the same hooks, server and skills from any project that already defines them.
251
+
252
+ The per-project rules in `AGENTS.md` / `CLAUDE.md` (memory bank snippet, optional SDD snippet, quality gate) are still
253
+ added per project.
254
+
255
+ ### Importing auto-memory
256
+
257
+ Claude Code's built-in auto-memory (`~/.claude/projects/<encoded-path>/memory/*.md`) is a second fact store that
258
+ overlaps with jevmem. Before switching it off for a project, import its notes. Run this from the project's root, so
259
+ the notes land in the same `project:<name>` scope that the hooks and MCP server use. Point `--root` at that project's
260
+ folder only, because the default imports every project's memory at once:
261
+
262
+ ```bash
263
+ uvx jevmem import-claude-memory --root ~/.claude/projects/<encoded-project-path>
264
+ ```
265
+
266
+ - **Folder name:** the project's absolute path with `/` replaced by `-`.
267
+ - **Jev must be configured.** Writes are screened by Jev, so the key or local model must be set up, or the notes are
268
+ queued unscreened and hidden from recall.
269
+ - **Check the result** with `uvx jevmem list`, and `memory_forget` anything stale.
270
+
271
+ After the switch, the old files stay on disk, but Claude no longer reads or writes them. To turn auto-memory off for a
272
+ single shell instead, set the environment variable `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1`.
273
+
274
+ ## Development
275
+
276
+ ```bash
277
+ git clone https://github.com/illescasDaniel/agent-guild && cd agent-guild
278
+ uv run pytest
279
+ uv run agent-guild /path/to/project --dry-run
280
+ ```
281
+
282
+ From a checkout, the CLI reads `agents/`, `templates/` and `development-workflow.md` at the repo root; the published
283
+ wheel bundles them.
284
+
285
+ ## License
286
+
287
+ [MIT](LICENSE)
@@ -0,0 +1,17 @@
1
+ agent_guild/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ agent_guild/cli.py,sha256=ivThPoj2iVqXDYPREdsltbJUbbS4mMr4d04zToNCblc,4404
3
+ agent_guild/files.py,sha256=mDpCJ5vu2QKqCBJsOUo1hpIukGRrt_ZGMtbj1iw0-D4,3860
4
+ agent_guild/installer.py,sha256=24hKFukTIfAlraHFZOrh5jEw4ZovxRIHsx_YkJTzmSM,12004
5
+ agent_guild/_assets/agents/architect.md,sha256=i74zN7wmbZx7EaYnQQaodHKN3mMpRTeN-QYg9OEHBhY,4291
6
+ agent_guild/_assets/agents/code-grader.md,sha256=TyApB6vUnrNqmElxNTT1ZQ-ocse0npTNYarwhRw78yQ,4394
7
+ agent_guild/_assets/agents/coder.md,sha256=MwWDM5QQGrh5vDRKtvDaHCvQWdNT82-thlQMJUYaDe4,3196
8
+ agent_guild/_assets/agents/utility.md,sha256=F4NTzyNcCzsFWLsmAwfCG_OfpIiaoE2Ni18JNV0iaA0,1930
9
+ agent_guild/_assets/development-workflow.md,sha256=PGsPcLnN5I2zjUqcmra6POCmMcFL9ZVX0QBNWIzu0eg,6143
10
+ agent_guild/_assets/templates/agents-rules.md,sha256=UvL3cKSDK4zf7wtas5Rm2C5RKlTW66wtDAcImCSvl3Q,271
11
+ agent_guild/_assets/templates/memory-bank-rules.md,sha256=XTJRr2UcVfHXtO3KBKygDSI4VCHIVXDGnKSMo3Wv2Xs,446
12
+ agent_guild/_assets/templates/sdd-rules.md,sha256=mGfLVChemlAGqNaG97oQzgAjXWvZrPEj574tTaJvr0A,1462
13
+ agent_guild-1.0.0.dist-info/METADATA,sha256=6TBIzMXu-MBzjBxjgeEx_Nv10IH7Rh_8IOYdkMeO0AI,14305
14
+ agent_guild-1.0.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
15
+ agent_guild-1.0.0.dist-info/entry_points.txt,sha256=RQ6c3z-koMe0ektui9uV4VQJGqhwQb6y9ZRcw4iQ6VI,53
16
+ agent_guild-1.0.0.dist-info/licenses/LICENSE,sha256=Q28OPpoy0LGWJN9HZyo1Qycs-YcPAMC5cmAZjPf7xbI,1079
17
+ agent_guild-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agent-guild = agent_guild.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Illescas Romero
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.