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.
- agent_guild/__init__.py +0 -0
- agent_guild/_assets/agents/architect.md +58 -0
- agent_guild/_assets/agents/code-grader.md +76 -0
- agent_guild/_assets/agents/coder.md +43 -0
- agent_guild/_assets/agents/utility.md +31 -0
- agent_guild/_assets/development-workflow.md +93 -0
- agent_guild/_assets/templates/agents-rules.md +6 -0
- agent_guild/_assets/templates/memory-bank-rules.md +6 -0
- agent_guild/_assets/templates/sdd-rules.md +18 -0
- agent_guild/cli.py +76 -0
- agent_guild/files.py +101 -0
- agent_guild/installer.py +268 -0
- agent_guild-1.0.0.dist-info/METADATA +287 -0
- agent_guild-1.0.0.dist-info/RECORD +17 -0
- agent_guild-1.0.0.dist-info/WHEEL +4 -0
- agent_guild-1.0.0.dist-info/entry_points.txt +2 -0
- agent_guild-1.0.0.dist-info/licenses/LICENSE +21 -0
agent_guild/__init__.py
ADDED
|
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))
|
agent_guild/installer.py
ADDED
|
@@ -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,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.
|