guild-agents 0.2.6 → 0.2.8
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.
- package/README.md +45 -35
- package/bin/guild.js +9 -7
- package/package.json +5 -6
- package/src/commands/init.js +44 -44
- package/src/commands/new-agent.js +37 -37
- package/src/commands/status.js +11 -11
- package/src/templates/agents/advisor.md +29 -29
- package/src/templates/agents/bugfix.md +32 -32
- package/src/templates/agents/code-reviewer.md +32 -32
- package/src/templates/agents/db-migration.md +32 -32
- package/src/templates/agents/developer.md +32 -32
- package/src/templates/agents/platform-expert.md +38 -36
- package/src/templates/agents/product-owner.md +32 -32
- package/src/templates/agents/qa.md +31 -31
- package/src/templates/agents/tech-lead.md +32 -32
- package/src/templates/skills/build-feature/SKILL.md +85 -85
- package/src/templates/skills/council/SKILL.md +68 -68
- package/src/templates/skills/dev-flow/SKILL.md +31 -31
- package/src/templates/skills/guild-specialize/SKILL.md +69 -68
- package/src/templates/skills/new-feature/SKILL.md +34 -34
- package/src/templates/skills/qa-cycle/SKILL.md +39 -39
- package/src/templates/skills/review/SKILL.md +35 -35
- package/src/templates/skills/session-end/SKILL.md +33 -33
- package/src/templates/skills/session-start/SKILL.md +32 -32
- package/src/templates/skills/status/SKILL.md +34 -34
- package/src/utils/files.js +8 -8
- package/src/utils/generators.js +47 -47
- package/src/utils/github.js +20 -20
- package/src/commands/__tests__/doctor.test.js +0 -85
- package/src/commands/__tests__/list.test.js +0 -82
- package/src/commands/__tests__/new-agent.test.js +0 -40
- package/src/commands/__tests__/status.test.js +0 -35
package/README.md
CHANGED
|
@@ -3,62 +3,64 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/guild-agents)
|
|
4
4
|
[](https://github.com/guild-agents/guild/actions/workflows/ci.yml)
|
|
5
5
|
[](LICENSE)
|
|
6
|
-
[](https://nodejs.org)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Claude Code is powerful but chaotic. Guild gives it structure.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Guild is an npm CLI that sets up 9 specialized agents and 10 skill-based workflows as `.claude/` files in any project. Agents define **who** does the work. Skills define **how** it gets done. Everything is markdown, tracked by git, works offline.
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Why Guild?
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
- **Structure over chaos.** Claude Code without guidance produces inconsistent results. Guild gives every task a clear owner and a repeatable process.
|
|
15
|
+
- **Agents = WHO, Skills = HOW.** Agents are flat `.md` files with identity and expertise. Skills are workflow definitions invoked as slash commands. Clean separation, no magic.
|
|
16
|
+
- **State that persists.** Context lives in `CLAUDE.md`, `PROJECT.md`, and `SESSION.md` -- tracked by git, readable by humans, never lost between sessions.
|
|
17
|
+
- **Zero infrastructure.** No servers, no APIs, no config files. Just markdown files that Claude Code reads natively.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
## How It Works
|
|
19
20
|
|
|
20
|
-
```bash
|
|
21
|
-
npx guild-agents init
|
|
22
21
|
```
|
|
22
|
+
You ──> /build-feature "Add JWT auth"
|
|
23
|
+
│
|
|
24
|
+
▼
|
|
25
|
+
┌─────────┐ ┌───────────────┐ ┌───────────────┐
|
|
26
|
+
│ Advisor │────>│ Tech Lead │────>│ Developer │
|
|
27
|
+
│ evaluate │ │ plan │ │ implement │
|
|
28
|
+
└─────────┘ └───────────────┘ └───────┬───────┘
|
|
29
|
+
│
|
|
30
|
+
┌─────────────┼─────────────┐
|
|
31
|
+
▼ ▼ ▼
|
|
32
|
+
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
33
|
+
│ Reviewer │ │ QA │ │ Bugfix │
|
|
34
|
+
│ review │ │ test │ │ fix │
|
|
35
|
+
└──────────┘ └──────────┘ └──────────┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Skills orchestrate agents through structured pipelines. You invoke a skill as a slash command, and it coordinates the right agents in the right order.
|
|
23
39
|
|
|
24
40
|
## Quick Start
|
|
25
41
|
|
|
26
42
|
```bash
|
|
27
|
-
|
|
43
|
+
npm install -g guild-agents
|
|
44
|
+
guild init
|
|
28
45
|
```
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
The interactive onboarding asks for project name, type, stack, and repo details, then generates the full structure: 9 agents, 10 skills, and 3 state files.
|
|
31
48
|
|
|
32
|
-
|
|
49
|
+
Next, let Guild learn your codebase:
|
|
33
50
|
|
|
34
51
|
```
|
|
35
52
|
/guild-specialize
|
|
36
53
|
```
|
|
37
54
|
|
|
38
|
-
This explores your actual
|
|
55
|
+
This explores your actual code and enriches `CLAUDE.md` with real conventions, patterns, and stack details. Every agent now understands your project.
|
|
39
56
|
|
|
40
|
-
Then
|
|
57
|
+
Then build something:
|
|
41
58
|
|
|
42
59
|
```
|
|
43
60
|
/build-feature Add user authentication with JWT
|
|
44
61
|
```
|
|
45
62
|
|
|
46
|
-
This runs the full pipeline
|
|
47
|
-
|
|
48
|
-
`guild init` generates: CLAUDE.md, PROJECT.md, SESSION.md, `.claude/agents/` (8 agents), `.claude/skills/` (10 skills).
|
|
49
|
-
|
|
50
|
-
## How It Works
|
|
51
|
-
|
|
52
|
-
**Agents** are the WHO. Each agent is a flat `.md` file in `.claude/agents/` that defines identity, responsibilities, and process. Skills invoke agents via the Task tool when their expertise is needed.
|
|
53
|
-
|
|
54
|
-
**Skills** are the HOW. Each skill is a workflow defined in `.claude/skills/*/SKILL.md` and invoked as a slash command. Skills orchestrate one or more agents through a structured process.
|
|
55
|
-
|
|
56
|
-
**State** is maintained across sessions through three files:
|
|
57
|
-
- `CLAUDE.md` — central enriched context (stack, conventions, rules)
|
|
58
|
-
- `PROJECT.md` — project metadata (name, type, architecture)
|
|
59
|
-
- `SESSION.md` — session continuity (current task, progress, next steps)
|
|
60
|
-
|
|
61
|
-
After init, agents are generic. Running `/guild-specialize` reads the real codebase and tailors each agent to the project's specific stack and patterns.
|
|
63
|
+
This runs the full pipeline -- advisor evaluation, tech lead planning, developer implementation, code review, and QA -- all coordinated automatically.
|
|
62
64
|
|
|
63
65
|
## Agents
|
|
64
66
|
|
|
@@ -72,6 +74,7 @@ After init, agents are generic. Running `/guild-specialize` reads the real codeb
|
|
|
72
74
|
| qa | Testing, edge cases, regression validation |
|
|
73
75
|
| bugfix | Bug diagnosis and resolution |
|
|
74
76
|
| db-migration | Schema changes and safe migrations |
|
|
77
|
+
| platform-expert | Diagnoses and resolves Claude Code integration issues |
|
|
75
78
|
|
|
76
79
|
## Skills
|
|
77
80
|
|
|
@@ -94,6 +97,8 @@ After init, agents are generic. Running `/guild-specialize` reads the real codeb
|
|
|
94
97
|
guild init # Interactive project onboarding
|
|
95
98
|
guild new-agent <name> # Create a custom agent
|
|
96
99
|
guild status # Show project status
|
|
100
|
+
guild doctor # Diagnose installation state
|
|
101
|
+
guild list # List installed agents and skills
|
|
97
102
|
```
|
|
98
103
|
|
|
99
104
|
## Generated Structure
|
|
@@ -114,6 +119,7 @@ SESSION.md
|
|
|
114
119
|
qa.md
|
|
115
120
|
bugfix.md
|
|
116
121
|
db-migration.md
|
|
122
|
+
platform-expert.md
|
|
117
123
|
skills/
|
|
118
124
|
guild-specialize/SKILL.md
|
|
119
125
|
build-feature/SKILL.md
|
|
@@ -129,9 +135,13 @@ SESSION.md
|
|
|
129
135
|
|
|
130
136
|
All files are markdown, tracked by git, and work fully offline.
|
|
131
137
|
|
|
138
|
+
## Guild Builds Itself
|
|
139
|
+
|
|
140
|
+
This project uses its own agents and skills to develop itself. Every feature, review, and bugfix goes through the same pipelines that Guild installs in your project.
|
|
141
|
+
|
|
132
142
|
## Requirements
|
|
133
143
|
|
|
134
|
-
- Node.js >=
|
|
144
|
+
- Node.js >= 20
|
|
135
145
|
- Claude Code
|
|
136
146
|
- `gh` CLI (optional, for GitHub integration)
|
|
137
147
|
|
|
@@ -139,11 +149,11 @@ All files are markdown, tracked by git, and work fully offline.
|
|
|
139
149
|
|
|
140
150
|
Two types of contributions:
|
|
141
151
|
|
|
142
|
-
- **Agent and skill templates** (`src/templates/`)
|
|
143
|
-
- **CLI code** (`src/`, `bin/`)
|
|
152
|
+
- **Agent and skill templates** (`src/templates/`) -- improve agent definitions or skill workflows.
|
|
153
|
+
- **CLI code** (`src/`, `bin/`) -- bug fixes, new commands, onboarding improvements.
|
|
144
154
|
|
|
145
155
|
See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for details.
|
|
146
156
|
|
|
147
157
|
## License
|
|
148
158
|
|
|
149
|
-
MIT
|
|
159
|
+
MIT -- see [LICENSE](LICENSE).
|
package/bin/guild.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Guild v1 — CLI entry point
|
|
5
5
|
* Usage:
|
|
6
|
-
* guild init — onboarding
|
|
7
|
-
* guild new-agent —
|
|
8
|
-
* guild status —
|
|
6
|
+
* guild init — interactive onboarding v1
|
|
7
|
+
* guild new-agent — create a new agent
|
|
8
|
+
* guild status — view project status
|
|
9
|
+
* guild doctor — verify setup and report issues
|
|
10
|
+
* guild list — list installed agents and skills
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
import { program } from 'commander';
|
|
@@ -24,7 +26,7 @@ program
|
|
|
24
26
|
// guild init
|
|
25
27
|
program
|
|
26
28
|
.command('init')
|
|
27
|
-
.description('
|
|
29
|
+
.description('Initialize Guild v1 in the current project')
|
|
28
30
|
.action(async () => {
|
|
29
31
|
try {
|
|
30
32
|
const { runInit } = await import('../src/commands/init.js');
|
|
@@ -38,8 +40,8 @@ program
|
|
|
38
40
|
// guild new-agent
|
|
39
41
|
program
|
|
40
42
|
.command('new-agent')
|
|
41
|
-
.description('
|
|
42
|
-
.argument('<name>', '
|
|
43
|
+
.description('Create a new agent')
|
|
44
|
+
.argument('<name>', 'Agent name (lowercase, hyphens)')
|
|
43
45
|
.action(async (name) => {
|
|
44
46
|
try {
|
|
45
47
|
const { runNewAgent } = await import('../src/commands/new-agent.js');
|
|
@@ -53,7 +55,7 @@ program
|
|
|
53
55
|
// guild status
|
|
54
56
|
program
|
|
55
57
|
.command('status')
|
|
56
|
-
.description('
|
|
58
|
+
.description('View Guild project status')
|
|
57
59
|
.action(async () => {
|
|
58
60
|
try {
|
|
59
61
|
const { runStatus } = await import('../src/commands/status.js');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guild-agents",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "A multi-agent framework for Claude Code — specialized AI teams for every project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"src/commands/",
|
|
9
9
|
"src/templates/",
|
|
10
10
|
"src/utils/",
|
|
11
|
-
"!src
|
|
11
|
+
"!src/**/__tests__/"
|
|
12
12
|
],
|
|
13
13
|
"bin": {
|
|
14
14
|
"guild": "bin/guild.js"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"code-review",
|
|
40
40
|
"nodejs"
|
|
41
41
|
],
|
|
42
|
-
"author": "",
|
|
42
|
+
"author": "Guild Agents <guild-agents@users.noreply.github.com>",
|
|
43
43
|
"license": "MIT",
|
|
44
44
|
"repository": {
|
|
45
45
|
"type": "git",
|
|
@@ -50,10 +50,9 @@
|
|
|
50
50
|
"url": "https://github.com/guild-agents/guild/issues"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@clack/prompts": "^0.
|
|
53
|
+
"@clack/prompts": "^1.0.1",
|
|
54
54
|
"chalk": "^5.3.0",
|
|
55
|
-
"commander": "^
|
|
56
|
-
"picocolors": "^1.0.0"
|
|
55
|
+
"commander": "^14.0.3"
|
|
57
56
|
},
|
|
58
57
|
"engines": {
|
|
59
58
|
"node": ">=20.0.0"
|
package/src/commands/init.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* guild init —
|
|
2
|
+
* guild init — Interactive onboarding v1
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
8
|
-
* 4.
|
|
9
|
-
* 5.
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. Verify that a Guild installation does not already exist
|
|
6
|
+
* 2. Collect: name, type, stack, GitHub, existing code
|
|
7
|
+
* 3. Generate PROJECT.md, CLAUDE.md, SESSION.md
|
|
8
|
+
* 4. Copy agents and skills
|
|
9
|
+
* 5. Instructions for /guild-specialize
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import * as p from '@clack/prompts';
|
|
@@ -17,68 +17,68 @@ import { copyTemplates } from '../utils/files.js';
|
|
|
17
17
|
|
|
18
18
|
export async function runInit() {
|
|
19
19
|
console.log('');
|
|
20
|
-
p.intro(chalk.bold.cyan('Guild v1 —
|
|
20
|
+
p.intro(chalk.bold.cyan('Guild v1 — New project'));
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Check for existing installation
|
|
23
23
|
if (existsSync('.claude/agents')) {
|
|
24
24
|
const overwrite = await p.confirm({
|
|
25
|
-
message: 'Guild
|
|
25
|
+
message: 'Guild is already installed in this project. Reinitialize?',
|
|
26
26
|
initialValue: false,
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
if (p.isCancel(overwrite) || !overwrite) {
|
|
30
|
-
p.cancel('
|
|
30
|
+
p.cancel('Cancelled.');
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// ───
|
|
35
|
+
// ─── Name ─────────────────────────────────────────────────────────────────
|
|
36
36
|
const name = await p.text({
|
|
37
|
-
message: '
|
|
38
|
-
placeholder: '
|
|
37
|
+
message: 'Project name:',
|
|
38
|
+
placeholder: 'my-project',
|
|
39
39
|
validate: (val) => {
|
|
40
|
-
if (!val) return '
|
|
40
|
+
if (!val) return 'Name is required';
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
|
-
if (p.isCancel(name)) { p.cancel('
|
|
43
|
+
if (p.isCancel(name)) { p.cancel('Cancelled.'); return; }
|
|
44
44
|
|
|
45
|
-
// ───
|
|
45
|
+
// ─── Type ───────────────────────────────────────────────────────────────────
|
|
46
46
|
const type = await p.select({
|
|
47
|
-
message: '
|
|
47
|
+
message: 'Project type:',
|
|
48
48
|
options: [
|
|
49
49
|
{ value: 'webapp', label: 'Web app (React/Vue/Angular)' },
|
|
50
50
|
{ value: 'api', label: 'API / Backend service' },
|
|
51
51
|
{ value: 'cli', label: 'CLI tool' },
|
|
52
52
|
{ value: 'mobile', label: 'Mobile (React Native)' },
|
|
53
|
-
{ value: 'fullstack', label: '
|
|
53
|
+
{ value: 'fullstack', label: 'Other / Fullstack' },
|
|
54
54
|
],
|
|
55
55
|
});
|
|
56
|
-
if (p.isCancel(type)) { p.cancel('
|
|
56
|
+
if (p.isCancel(type)) { p.cancel('Cancelled.'); return; }
|
|
57
57
|
|
|
58
58
|
// ─── Stack ──────────────────────────────────────────────────────────────────
|
|
59
59
|
const stack = await p.text({
|
|
60
|
-
message: '
|
|
61
|
-
placeholder: '
|
|
60
|
+
message: 'Main stack:',
|
|
61
|
+
placeholder: 'e.g.: Next.js, Supabase, Vercel',
|
|
62
62
|
validate: (val) => {
|
|
63
|
-
if (!val) return '
|
|
63
|
+
if (!val) return 'Stack is required';
|
|
64
64
|
},
|
|
65
65
|
});
|
|
66
|
-
if (p.isCancel(stack)) { p.cancel('
|
|
66
|
+
if (p.isCancel(stack)) { p.cancel('Cancelled.'); return; }
|
|
67
67
|
|
|
68
68
|
// ─── GitHub ─────────────────────────────────────────────────────────────────
|
|
69
69
|
let github = null;
|
|
70
70
|
const hasRepo = await p.confirm({
|
|
71
|
-
message: '
|
|
71
|
+
message: 'Has a GitHub repository?',
|
|
72
72
|
initialValue: true,
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
if (!p.isCancel(hasRepo) && hasRepo) {
|
|
76
76
|
const repoUrl = await p.text({
|
|
77
|
-
message: 'URL
|
|
77
|
+
message: 'Repository URL:',
|
|
78
78
|
placeholder: 'https://github.com/org/repo',
|
|
79
79
|
validate: (val) => {
|
|
80
|
-
if (!val) return '
|
|
81
|
-
if (!val.includes('github.com')) return '
|
|
80
|
+
if (!val) return 'URL is required';
|
|
81
|
+
if (!val.includes('github.com')) return 'Must be a GitHub URL';
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
84
|
if (!p.isCancel(repoUrl)) {
|
|
@@ -86,15 +86,15 @@ export async function runInit() {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// ───
|
|
89
|
+
// ─── Existing code ────────────────────────────────────────────────────────
|
|
90
90
|
const hasExistingCode = await p.confirm({
|
|
91
|
-
message: '
|
|
91
|
+
message: 'Has existing code?',
|
|
92
92
|
initialValue: true,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
// ───
|
|
95
|
+
// ─── Generation ───────────────────────────────────────────────────────────
|
|
96
96
|
const spinner = p.spinner();
|
|
97
|
-
spinner.start('
|
|
97
|
+
spinner.start('Generating Guild v1 structure...');
|
|
98
98
|
|
|
99
99
|
const projectData = {
|
|
100
100
|
name,
|
|
@@ -106,35 +106,35 @@ export async function runInit() {
|
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
108
|
await copyTemplates();
|
|
109
|
-
spinner.message('
|
|
109
|
+
spinner.message('Generating CLAUDE.md...');
|
|
110
110
|
await generateClaudeMd(projectData);
|
|
111
111
|
|
|
112
|
-
spinner.message('
|
|
112
|
+
spinner.message('Generating PROJECT.md...');
|
|
113
113
|
await generateProjectMd(projectData);
|
|
114
114
|
|
|
115
|
-
spinner.message('
|
|
115
|
+
spinner.message('Generating SESSION.md...');
|
|
116
116
|
await generateSessionMd();
|
|
117
117
|
|
|
118
|
-
spinner.stop('
|
|
118
|
+
spinner.stop('Structure created.');
|
|
119
119
|
} catch (error) {
|
|
120
|
-
spinner.stop('Error
|
|
120
|
+
spinner.stop('Error during initialization.');
|
|
121
121
|
throw error;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
// ───
|
|
124
|
+
// ─── Summary ──────────────────────────────────────────────────────────────
|
|
125
125
|
p.log.success('CLAUDE.md');
|
|
126
126
|
p.log.success('PROJECT.md');
|
|
127
127
|
p.log.success('SESSION.md');
|
|
128
|
-
p.log.success('.claude/agents/ (8
|
|
128
|
+
p.log.success('.claude/agents/ (8 base agents)');
|
|
129
129
|
p.log.success('.claude/skills/ (10 skills)');
|
|
130
130
|
|
|
131
131
|
p.note(
|
|
132
|
-
'
|
|
132
|
+
'Open Claude Code in this directory and run:\n\n' +
|
|
133
133
|
' /guild-specialize\n\n' +
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
134
|
+
'This skill will explore your code and enrich CLAUDE.md\n' +
|
|
135
|
+
'with the actual project information.',
|
|
136
|
+
'Next step'
|
|
137
137
|
);
|
|
138
138
|
|
|
139
|
-
p.outro(chalk.bold.cyan('Guild v1
|
|
139
|
+
p.outro(chalk.bold.cyan('Guild v1 ready.'));
|
|
140
140
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* new-agent.js —
|
|
2
|
+
* new-agent.js — Creates a new v1 agent (plain file)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
8
|
-
* 4.
|
|
9
|
-
* 5.
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. Validate name (lowercase, hyphens, no spaces)
|
|
6
|
+
* 2. Verify that Guild is installed
|
|
7
|
+
* 3. Verify that the agent does NOT exist
|
|
8
|
+
* 4. Ask for agent description
|
|
9
|
+
* 5. Create .claude/agents/[name].md with placeholder
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import * as p from '@clack/prompts';
|
|
@@ -17,35 +17,35 @@ import { join } from 'path';
|
|
|
17
17
|
const AGENTS_DIR = join('.claude', 'agents');
|
|
18
18
|
|
|
19
19
|
export async function runNewAgent(agentName) {
|
|
20
|
-
p.intro(chalk.bold.cyan('Guild —
|
|
20
|
+
p.intro(chalk.bold.cyan('Guild — New agent'));
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// Validate name
|
|
23
23
|
if (!isValidAgentName(agentName)) {
|
|
24
|
-
throw new Error(`
|
|
24
|
+
throw new Error(`Invalid name: "${agentName}". Only lowercase, numbers, and hyphens allowed. Example: guild new-agent security-auditor`);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// Verify Guild is installed
|
|
28
28
|
if (!existsSync(AGENTS_DIR)) {
|
|
29
|
-
throw new Error('Guild
|
|
29
|
+
throw new Error('Guild is not installed. Run: guild init');
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// Verify that the agent does NOT exist
|
|
33
33
|
const agentPath = join(AGENTS_DIR, `${agentName}.md`);
|
|
34
34
|
if (existsSync(agentPath)) {
|
|
35
|
-
throw new Error(`
|
|
35
|
+
throw new Error(`Agent "${agentName}" already exists.`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// Ask for description
|
|
39
39
|
const description = await p.text({
|
|
40
|
-
message: `
|
|
41
|
-
placeholder: '
|
|
42
|
-
validate: (val) => !val ? '
|
|
40
|
+
message: `What does "${agentName}" do? (short description):`,
|
|
41
|
+
placeholder: 'e.g.: Evaluates trading opportunities based on technical analysis',
|
|
42
|
+
validate: (val) => !val ? 'Description is required' : undefined,
|
|
43
43
|
});
|
|
44
|
-
if (p.isCancel(description)) { p.cancel('
|
|
44
|
+
if (p.isCancel(description)) { p.cancel('Cancelled.'); return; }
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// Create agent
|
|
47
47
|
const spinner = p.spinner();
|
|
48
|
-
spinner.start(`
|
|
48
|
+
spinner.start(`Creating agent "${agentName}"...`);
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
51
|
const content = `---
|
|
@@ -55,34 +55,34 @@ description: "${description}"
|
|
|
55
55
|
|
|
56
56
|
# ${agentName}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
You are ${agentName} of [PROJECT].
|
|
59
59
|
|
|
60
|
-
##
|
|
61
|
-
[
|
|
60
|
+
## Responsibilities
|
|
61
|
+
[Define with /guild-specialize]
|
|
62
62
|
|
|
63
|
-
##
|
|
64
|
-
[
|
|
63
|
+
## What you do NOT do
|
|
64
|
+
[Define with /guild-specialize]
|
|
65
65
|
|
|
66
|
-
##
|
|
67
|
-
[
|
|
66
|
+
## Process
|
|
67
|
+
[Define with /guild-specialize]
|
|
68
68
|
|
|
69
|
-
##
|
|
70
|
-
-
|
|
69
|
+
## Behavioral rules
|
|
70
|
+
- Always read CLAUDE.md and SESSION.md at the start of the session
|
|
71
71
|
`;
|
|
72
72
|
|
|
73
73
|
writeFileSync(agentPath, content, 'utf8');
|
|
74
74
|
|
|
75
|
-
spinner.stop(`
|
|
75
|
+
spinner.stop(`Agent "${agentName}" created.`);
|
|
76
76
|
|
|
77
|
-
p.log.success(`
|
|
77
|
+
p.log.success(`File: ${agentPath}`);
|
|
78
78
|
p.note(
|
|
79
|
-
`
|
|
80
|
-
`
|
|
81
|
-
'
|
|
79
|
+
`Run /guild-specialize so that Claude\n` +
|
|
80
|
+
`generates the full instructions for "${agentName}".`,
|
|
81
|
+
'Specialization pending'
|
|
82
82
|
);
|
|
83
|
-
p.outro(chalk.bold.cyan(`
|
|
83
|
+
p.outro(chalk.bold.cyan(`Agent ${agentName} ready.`));
|
|
84
84
|
} catch (error) {
|
|
85
|
-
spinner.stop('Error
|
|
85
|
+
spinner.stop('Error creating agent.');
|
|
86
86
|
throw error;
|
|
87
87
|
}
|
|
88
88
|
}
|
package/src/commands/status.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* status.js —
|
|
2
|
+
* status.js — Shows the current project status v1
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as p from '@clack/prompts';
|
|
@@ -9,13 +9,13 @@ import { join } from 'path';
|
|
|
9
9
|
|
|
10
10
|
export async function runStatus() {
|
|
11
11
|
if (!existsSync('PROJECT.md')) {
|
|
12
|
-
throw new Error('Guild
|
|
12
|
+
throw new Error('Guild is not installed. Run: guild init');
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const projectMd = readFileSync('PROJECT.md', 'utf8');
|
|
16
|
-
const nameMatch = projectMd.match(/\*\*
|
|
16
|
+
const nameMatch = projectMd.match(/\*\*Name:\*\*\s*(.+)/);
|
|
17
17
|
const stackMatch = projectMd.match(/\*\*Stack:\*\*\s*(.+)/);
|
|
18
|
-
const projectName = nameMatch ? nameMatch[1].trim() : '
|
|
18
|
+
const projectName = nameMatch ? nameMatch[1].trim() : 'Project';
|
|
19
19
|
|
|
20
20
|
p.intro(chalk.bold.cyan(`Guild — ${projectName}`));
|
|
21
21
|
|
|
@@ -23,20 +23,20 @@ export async function runStatus() {
|
|
|
23
23
|
p.log.info(chalk.gray(`Stack: ${stackMatch[1].trim()}`));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//
|
|
26
|
+
// Active session
|
|
27
27
|
if (existsSync('SESSION.md')) {
|
|
28
|
-
p.log.step('
|
|
28
|
+
p.log.step('Active session');
|
|
29
29
|
const sessionMd = readFileSync('SESSION.md', 'utf8');
|
|
30
|
-
const taskMatch = sessionMd.match(/\*\*
|
|
31
|
-
const stateMatch = sessionMd.match(/\*\*
|
|
32
|
-
if (taskMatch && taskMatch[1].trim() !== '—') p.log.info(`
|
|
30
|
+
const taskMatch = sessionMd.match(/\*\*Current task:\*\*\s*(.+)/);
|
|
31
|
+
const stateMatch = sessionMd.match(/\*\*Status:\*\*\s*(.+)/);
|
|
32
|
+
if (taskMatch && taskMatch[1].trim() !== '—') p.log.info(` Task: ${taskMatch[1].trim()}`);
|
|
33
33
|
if (stateMatch) p.log.info(chalk.gray(` ${stateMatch[1].trim()}`));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
//
|
|
36
|
+
// Agents
|
|
37
37
|
const agentsDir = join('.claude', 'agents');
|
|
38
38
|
if (existsSync(agentsDir)) {
|
|
39
|
-
p.log.step('
|
|
39
|
+
p.log.step('Agents');
|
|
40
40
|
const agents = readdirSync(agentsDir)
|
|
41
41
|
.filter(f => f.endsWith('.md'))
|
|
42
42
|
.map(f => f.replace('.md', ''));
|