guild-agents 0.2.8 → 0.3.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guild-agents",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "A multi-agent framework for Claude Code — specialized AI teams for every project",
5
5
  "type": "module",
6
6
  "files": [
@@ -45,7 +45,7 @@
45
45
  "type": "git",
46
46
  "url": "git+https://github.com/guild-agents/guild.git"
47
47
  },
48
- "homepage": "https://github.com/guild-agents/guild",
48
+ "homepage": "https://guildagents.dev",
49
49
  "bugs": {
50
50
  "url": "https://github.com/guild-agents/guild/issues"
51
51
  },
@@ -13,7 +13,7 @@ import * as p from '@clack/prompts';
13
13
  import chalk from 'chalk';
14
14
  import { existsSync } from 'fs';
15
15
  import { generateProjectMd, generateSessionMd, generateClaudeMd } from '../utils/generators.js';
16
- import { copyTemplates } from '../utils/files.js';
16
+ import { copyTemplates, getAgentNames, getSkillNames } from '../utils/files.js';
17
17
 
18
18
  export async function runInit() {
19
19
  console.log('');
@@ -122,19 +122,24 @@ export async function runInit() {
122
122
  }
123
123
 
124
124
  // ─── Summary ──────────────────────────────────────────────────────────────
125
- p.log.success('CLAUDE.md');
126
- p.log.success('PROJECT.md');
127
- p.log.success('SESSION.md');
128
- p.log.success('.claude/agents/ (8 base agents)');
129
- p.log.success('.claude/skills/ (10 skills)');
130
-
131
- p.note(
132
- 'Open Claude Code in this directory and run:\n\n' +
133
- ' /guild-specialize\n\n' +
134
- 'This skill will explore your code and enrich CLAUDE.md\n' +
135
- 'with the actual project information.',
136
- 'Next step'
137
- );
125
+ const agentCount = getAgentNames().length;
126
+ const skillCount = getSkillNames().length;
127
+ p.log.success(`Created: CLAUDE.md, PROJECT.md, SESSION.md, ${agentCount} agents, ${skillCount} skills`);
128
+
129
+ const relevantSkills = projectData.hasExistingCode
130
+ ? ['/guild-specialize', '/build-feature', '/review']
131
+ : ['/build-feature', '/new-feature', '/council'];
132
+ p.log.info(`Start with: ${relevantSkills.join(' ')}`);
133
+
134
+ const quickStart = projectData.hasExistingCode
135
+ ? '1. Open Claude Code in this directory\n' +
136
+ '2. Run /guild-specialize to analyze your codebase\n' +
137
+ '3. Start building with /build-feature'
138
+ : '1. Open Claude Code in this directory\n' +
139
+ '2. Start building with /build-feature\n' +
140
+ '3. Run /guild-specialize once you have code';
141
+
142
+ p.note(quickStart, 'Quick start');
138
143
 
139
144
  p.outro(chalk.bold.cyan('Guild v1 ready.'));
140
145
  }
@@ -6,24 +6,7 @@ import * as p from '@clack/prompts';
6
6
  import chalk from 'chalk';
7
7
  import { existsSync, readdirSync, readFileSync } from 'fs';
8
8
  import { join } from 'path';
9
-
10
- /**
11
- * Parses YAML frontmatter from a markdown file content.
12
- * Returns an object with key-value pairs from the frontmatter.
13
- */
14
- function parseFrontmatter(content) {
15
- const match = content.match(/^---\n([\s\S]*?)\n---/);
16
- if (!match) return {};
17
- const fm = {};
18
- for (const line of match[1].split('\n')) {
19
- const colonIndex = line.indexOf(':');
20
- if (colonIndex === -1) continue;
21
- const key = line.slice(0, colonIndex).trim();
22
- const value = line.slice(colonIndex + 1).trim().replace(/^["']|["']$/g, '');
23
- if (key && value) fm[key] = value;
24
- }
25
- return fm;
26
- }
9
+ import { parseFrontmatter } from '../utils/files.js';
27
10
 
28
11
  export async function runList() {
29
12
  p.intro(chalk.bold.cyan('Guild — Agents & Skills'));
@@ -35,8 +35,31 @@ When running a single build-feature, a simple `git checkout -b` is sufficient.
35
35
 
36
36
  ## 6-Phase Pipeline
37
37
 
38
+ ### Progress Display
39
+
40
+ At the start of each phase, display a progress indicator to the user before any agent output:
41
+
42
+ ```text
43
+ [1/6] Advisor — Evaluating feature...
44
+ [2/6] Product Owner — Defining spec...
45
+ [3/6] Tech Lead — Defining technical approach...
46
+ [4/6] Developer — Implementing...
47
+ [5/6] Code Reviewer — Reviewing changes...
48
+ [6/6] QA — Validating acceptance criteria...
49
+ ```
50
+
51
+ When a phase loops (review-fix or QA-review cycles), show the iteration:
52
+
53
+ ```text
54
+ [5/6 · round 2] Code Reviewer — Re-reviewing after fixes...
55
+ [4/6 · round 2] Developer — Fixing review blockers...
56
+ ```
57
+
58
+ This indicator MUST be displayed before spawning the agent for that phase.
59
+
38
60
  ### Phase 1 — Evaluation (Advisor)
39
61
 
62
+ **Progress:** `[1/6] Advisor — Evaluating feature...`
40
63
  **Agent:** Reads `.claude/agents/advisor.md` via Task tool
41
64
  **Input:** The feature description provided by the user
42
65
  **Process:**
@@ -50,6 +73,7 @@ When running a single build-feature, a simple `git checkout -b` is sufficient.
50
73
 
51
74
  ### Phase 2 — Specification (Product Owner)
52
75
 
76
+ **Progress:** `[2/6] Product Owner — Defining spec...`
53
77
  **Agent:** Reads `.claude/agents/product-owner.md` via Task tool
54
78
  **Input:** The feature approved by the Advisor + their observations
55
79
  **Process:**
@@ -62,6 +86,7 @@ When running a single build-feature, a simple `git checkout -b` is sufficient.
62
86
 
63
87
  ### Phase 3 — Technical Approach (Tech Lead)
64
88
 
89
+ **Progress:** `[3/6] Tech Lead — Defining technical approach...`
65
90
  **Agent:** Reads `.claude/agents/tech-lead.md` via Task tool
66
91
  **Input:** Product Owner tasks + acceptance criteria
67
92
  **Process:**
@@ -74,6 +99,7 @@ When running a single build-feature, a simple `git checkout -b` is sufficient.
74
99
 
75
100
  ### Phase 4 — Implementation (Developer)
76
101
 
102
+ **Progress:** `[4/6] Developer — Implementing...`
77
103
  **Agent:** Reads `.claude/agents/developer.md` via Task tool
78
104
  **Input:** Tech Lead technical plan + PO acceptance criteria
79
105
  **Process:**
@@ -97,6 +123,7 @@ This gate CANNOT be skipped, even if the user requested phase skipping. The spec
97
123
 
98
124
  ### Phase 5 — Review (Code Reviewer)
99
125
 
126
+ **Progress:** `[5/6] Code Reviewer — Reviewing changes...`
100
127
  **Agent:** Reads `.claude/agents/code-reviewer.md` via Task tool
101
128
  **Input:** The implemented changes (git diff)
102
129
  **Process:**
@@ -109,6 +136,8 @@ This gate CANNOT be skipped, even if the user requested phase skipping. The spec
109
136
 
110
137
  ### Phase 6 — QA (delegates to /qa-cycle)
111
138
 
139
+ **Progress:** `[6/6] QA — Validating acceptance criteria...`
140
+
112
141
  Runs the `/qa-cycle` skill passing the PO acceptance criteria as context. The qa-cycle handles:
113
142
 
114
143
  1. Running project tests and lint
@@ -197,12 +226,23 @@ Task tool with:
197
226
  ```text
198
227
  User: /build-feature add dark mode toggle to settings page
199
228
 
200
- Phase 1 Advisor: Approved. Low risk, aligns with UX roadmap.
201
- Phase 2 PO: 3 tasks defined with acceptance criteria.
202
- Phase 3 — Tech Lead: Use CSS variables + context provider pattern.
203
- Phase 4Developer: Implemented ThemeContext, toggle component, CSS vars.
204
- Phase 5 Review: Passed. 1 suggestion (memoize context value).
205
- Phase 6 — QA: All 3 acceptance criteria verified. 0 bugs.
229
+ [1/6] Advisor Evaluating feature...
230
+ Approved. Low risk, aligns with UX roadmap.
231
+
232
+ [2/6] Product Owner Defining spec...
233
+ 3 tasks defined with acceptance criteria.
234
+
235
+ [3/6] Tech Lead — Defining technical approach...
236
+ Use CSS variables + context provider pattern.
237
+
238
+ [4/6] Developer — Implementing...
239
+ Implemented ThemeContext, toggle component, CSS vars.
240
+
241
+ [5/6] Code Reviewer — Reviewing changes...
242
+ Passed. 1 suggestion (memoize context value).
243
+
244
+ [6/6] QA — Validating acceptance criteria...
245
+ All 3 acceptance criteria verified. 0 bugs.
206
246
 
207
247
  Feature complete. PR ready for merge.
208
248
  ```
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: create-pr
3
+ description: "Create a pull request from the current branch with structured summary"
4
+ user-invocable: true
5
+ ---
6
+
7
+ # Create PR
8
+
9
+ Creates a pull request from the current feature branch with a structured summary, test results, and change description. Closes the pipeline loop: init -> build-feature -> create-pr.
10
+
11
+ ## When to use
12
+
13
+ - After completing a feature with `/build-feature`
14
+ - When you have changes on a feature branch ready for review
15
+ - To create a well-structured PR without manual formatting
16
+
17
+ ## Usage
18
+
19
+ `/create-pr`
20
+
21
+ ## Process
22
+
23
+ ### Step 1 -- Verify branch state
24
+
25
+ 1. Confirm you are NOT on `main` or `develop` -- refuse to create PR from default branches
26
+ 2. Run `git status` to check for uncommitted changes -- if any, warn the user and ask whether to commit first
27
+ 3. Run `git log main..HEAD --oneline` to get the list of commits that will be in the PR
28
+ 4. If there are no commits ahead of main, report that there is nothing to PR
29
+
30
+ ### Step 2 -- Gather context
31
+
32
+ Collect the information needed for the PR description:
33
+
34
+ 1. **Commits**: `git log main..HEAD --oneline` -- list of all commits on this branch
35
+ 2. **Diff summary**: `git diff main..HEAD --stat` -- files changed with line counts
36
+ 3. **Test results**: Run project tests (e.g., `npm test`) and capture pass/fail
37
+ 4. **Lint results**: Run project lint (e.g., `npm run lint`) and capture pass/fail
38
+ 5. **Branch name**: Extract feature name from the branch (e.g., `feature/dark-mode` -> `dark-mode`)
39
+
40
+ If tests or lint fail, warn the user but allow them to proceed (some PRs are draft/WIP).
41
+
42
+ ### Step 3 -- Generate PR description
43
+
44
+ Build a structured PR description:
45
+
46
+ ```markdown
47
+ ## Summary
48
+ [2-4 bullet points describing what this PR does, derived from commit messages]
49
+
50
+ ## Changes
51
+ [File-level summary from git diff --stat]
52
+
53
+ ## Test plan
54
+ - [x] Tests: [pass/fail] ([count] tests)
55
+ - [x] Lint: [pass/fail]
56
+ - [ ] [Any manual verification steps if applicable]
57
+ ```
58
+
59
+ ### Step 4 -- Create the PR
60
+
61
+ 1. Push the branch to origin: `git push -u origin [branch-name]`
62
+ 2. Create the PR using `gh pr create`:
63
+ - Title: derived from branch name or first commit message (max 70 chars)
64
+ - Body: the generated description from Step 3
65
+ - Base: `main` (or the project's default branch)
66
+ 3. Report the PR URL to the user
67
+
68
+ ### Step 5 -- Post-creation
69
+
70
+ 1. Display the PR URL
71
+ 2. Suggest next steps:
72
+ - "Request review from a teammate"
73
+ - "Run `/review` for an AI code review"
74
+ - "Merge when ready with `gh pr merge [number]`"
75
+
76
+ ## Example Session
77
+
78
+ ```text
79
+ User: /create-pr
80
+
81
+ Checking branch state...
82
+ Branch: feature/dark-mode (4 commits ahead of main)
83
+ Tests: 82 passed, 0 failed
84
+ Lint: 0 errors
85
+
86
+ Creating PR...
87
+ PR #42: "feat: add dark mode toggle to settings"
88
+ https://github.com/org/repo/pull/42
89
+
90
+ Next steps:
91
+ - Request review from a teammate
92
+ - Run /review for AI code review
93
+ - Merge when ready
94
+ ```
95
+
96
+ ## Notes
97
+
98
+ - The PR title should be concise (under 70 characters) and follow conventional commits format when the project uses it
99
+ - If the branch has `wip:` commits from build-feature checkpoints, consider squashing them before creating the PR
100
+ - This skill does NOT merge the PR -- that is a manual step or a separate command
@@ -12,20 +12,56 @@ const AGENTS_DIR = join('.claude', 'agents');
12
12
  const SKILLS_DIR = join('.claude', 'skills');
13
13
 
14
14
  /**
15
- * Returns the names of the 9 v1 agents.
15
+ * Returns the names of the v1 agents by reading the templates directory.
16
+ * Adding a new .md file to src/templates/agents/ automatically includes it.
16
17
  */
17
18
  export function getAgentNames() {
18
- return [
19
- 'advisor',
20
- 'product-owner',
21
- 'tech-lead',
22
- 'developer',
23
- 'code-reviewer',
24
- 'qa',
25
- 'bugfix',
26
- 'db-migration',
27
- 'platform-expert',
28
- ];
19
+ const agentsDir = join(TEMPLATES_DIR, 'agents');
20
+ if (!existsSync(agentsDir)) {
21
+ return [];
22
+ }
23
+ return readdirSync(agentsDir)
24
+ .filter(f => f.endsWith('.md'))
25
+ .map(f => f.replace('.md', ''))
26
+ .sort();
27
+ }
28
+
29
+ /**
30
+ * Returns the names of the v1 skills by reading the templates directory.
31
+ * Adding a new directory to src/templates/skills/ automatically includes it.
32
+ */
33
+ export function getSkillNames() {
34
+ const skillsDir = join(TEMPLATES_DIR, 'skills');
35
+ if (!existsSync(skillsDir)) {
36
+ return [];
37
+ }
38
+ return readdirSync(skillsDir, { withFileTypes: true })
39
+ .filter(d => d.isDirectory())
40
+ .map(d => d.name)
41
+ .sort();
42
+ }
43
+
44
+ /**
45
+ * Parses YAML frontmatter from markdown content.
46
+ * Returns an object with { name, description, ...other fields } or empty object if no frontmatter.
47
+ */
48
+ export function parseFrontmatter(content) {
49
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
50
+ if (!match) return {};
51
+
52
+ const frontmatter = {};
53
+ for (const line of match[1].split('\n')) {
54
+ const colonIndex = line.indexOf(':');
55
+ if (colonIndex === -1) continue;
56
+ const key = line.slice(0, colonIndex).trim();
57
+ let value = line.slice(colonIndex + 1).trim();
58
+ // Remove surrounding quotes
59
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
60
+ value = value.slice(1, -1);
61
+ }
62
+ if (key) frontmatter[key] = value;
63
+ }
64
+ return frontmatter;
29
65
  }
30
66
 
31
67
  /**
@@ -31,6 +31,67 @@ export async function generateProjectMd(data) {
31
31
  writeFileSync('PROJECT.md', content, 'utf8');
32
32
  }
33
33
 
34
+ /**
35
+ * Infers code conventions based on project type and stack.
36
+ * Rules accumulate (not exclusive). Deduplicates lines.
37
+ */
38
+ export function inferCodeConventions(type, stack) {
39
+ const s = (stack || '').toLowerCase();
40
+ const rules = [];
41
+
42
+ // Stack-specific rules
43
+ if (s.includes('next') || s.includes('react')) {
44
+ rules.push('- Components in PascalCase', '- CSS Modules or Tailwind utility classes');
45
+ }
46
+ if (s.includes('express') || (s.includes('node') && type === 'api')) {
47
+ rules.push('- Controllers/routes pattern', '- Async/await error handling');
48
+ }
49
+ if (s.includes('typescript') || /\bts\b/.test(s)) {
50
+ rules.push('- Strict TypeScript', '- Interfaces over types where possible');
51
+ }
52
+
53
+ // Type-specific fallbacks (only if no stack rules matched)
54
+ if (rules.length === 0) {
55
+ if (type === 'cli') {
56
+ rules.push('- Commander.js command pattern', '- ESModules throughout');
57
+ } else if (type === 'api') {
58
+ rules.push('- REST or GraphQL endpoint conventions', '- Input validation on all endpoints');
59
+ } else {
60
+ rules.push('- Consistent naming conventions', '- ESModules throughout');
61
+ }
62
+ }
63
+
64
+ // Deduplicate
65
+ return [...new Set(rules)].join('\n');
66
+ }
67
+
68
+ /**
69
+ * Infers likely environment variables based on project type and stack.
70
+ * Rules accumulate. Deduplicates lines.
71
+ */
72
+ export function inferEnvVars(type, stack) {
73
+ const s = (stack || '').toLowerCase();
74
+ const vars = [];
75
+
76
+ // Stack-specific
77
+ if (s.includes('supabase')) vars.push('- `SUPABASE_URL`', '- `SUPABASE_ANON_KEY`');
78
+ if (s.includes('firebase')) vars.push('- `FIREBASE_API_KEY`', '- `FIREBASE_PROJECT_ID`');
79
+ if (s.includes('postgres')) vars.push('- `DATABASE_URL`');
80
+ if (s.includes('redis')) vars.push('- `REDIS_URL`');
81
+ if (s.includes('stripe')) vars.push('- `STRIPE_SECRET_KEY`', '- `STRIPE_WEBHOOK_SECRET`');
82
+ if (s.includes('vercel')) vars.push('- `VERCEL_URL`');
83
+ if (/\baws\b/.test(s)) vars.push('- `AWS_ACCESS_KEY_ID`', '- `AWS_SECRET_ACCESS_KEY`', '- `AWS_REGION`');
84
+
85
+ // Type-specific fallbacks
86
+ if (vars.length === 0) {
87
+ if (type === 'webapp') vars.push('- `NODE_ENV`', '- `API_URL`');
88
+ else if (type === 'api') vars.push('- `NODE_ENV`', '- `PORT`', '- `DATABASE_URL`');
89
+ else vars.push('- `NODE_ENV`');
90
+ }
91
+
92
+ return [...new Set(vars)].join('\n');
93
+ }
94
+
34
95
  /**
35
96
  * Generates CLAUDE.md — central document with placeholders for guild-specialize.
36
97
  */
@@ -47,13 +108,13 @@ ${data.stack}
47
108
  [PENDING: guild-specialize]
48
109
 
49
110
  ## Code conventions
50
- [PENDING: guild-specialize]
111
+ ${inferCodeConventions(data.type, data.stack)}
51
112
 
52
113
  ## Architecture patterns
53
114
  [PENDING: guild-specialize]
54
115
 
55
116
  ## Environment variables
56
- [PENDING: guild-specialize]
117
+ ${inferEnvVars(data.type, data.stack)}
57
118
 
58
119
  ## Global rules
59
120
  - Do not implement without an approved plan
@@ -72,6 +133,7 @@ ${data.stack}
72
133
  - /guild-specialize — enrich CLAUDE.md by exploring the actual project
73
134
  - /build-feature — full development pipeline
74
135
  - /new-feature — create branch and scaffold for a feature
136
+ - /create-pr — create a structured pull request from current branch
75
137
  - /council — debate decisions with multiple agents
76
138
  - /review — code review on the current diff
77
139
  - /qa-cycle — QA + bugfix cycle