opencode-agile-agent 1.0.1
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 +71 -0
- package/bin/cli.js +434 -0
- package/bin/validate-templates.js +58 -0
- package/package.json +52 -0
- package/templates/.opencode/ARCHITECTURE.md +368 -0
- package/templates/.opencode/README.md +391 -0
- package/templates/.opencode/agents/api-designer.md +312 -0
- package/templates/.opencode/agents/backend-specialist.md +214 -0
- package/templates/.opencode/agents/code-archaeologist.md +260 -0
- package/templates/.opencode/agents/database-architect.md +212 -0
- package/templates/.opencode/agents/debugger.md +302 -0
- package/templates/.opencode/agents/developer.md +523 -0
- package/templates/.opencode/agents/devops-engineer.md +253 -0
- package/templates/.opencode/agents/documentation-writer.md +247 -0
- package/templates/.opencode/agents/explorer-agent.md +239 -0
- package/templates/.opencode/agents/feature-lead.md +302 -0
- package/templates/.opencode/agents/frontend-specialist.md +186 -0
- package/templates/.opencode/agents/game-developer.md +391 -0
- package/templates/.opencode/agents/mobile-developer.md +264 -0
- package/templates/.opencode/agents/orchestrator.md +463 -0
- package/templates/.opencode/agents/penetration-tester.md +256 -0
- package/templates/.opencode/agents/performance-optimizer.md +292 -0
- package/templates/.opencode/agents/pr-reviewer.md +468 -0
- package/templates/.opencode/agents/product-manager.md +225 -0
- package/templates/.opencode/agents/product-owner.md +264 -0
- package/templates/.opencode/agents/project-planner.md +248 -0
- package/templates/.opencode/agents/qa-automation-engineer.md +276 -0
- package/templates/.opencode/agents/security-auditor.md +260 -0
- package/templates/.opencode/agents/seo-specialist.md +266 -0
- package/templates/.opencode/agents/system-analyst.md +428 -0
- package/templates/.opencode/agents/test-engineer.md +229 -0
- package/templates/.opencode/config.template.json +129 -0
- package/templates/.opencode/rules/coding-standards.md +250 -0
- package/templates/.opencode/rules/git-conventions.md +149 -0
- package/templates/.opencode/skills/api-patterns/SKILL.md +162 -0
- package/templates/.opencode/skills/brainstorming/SKILL.md +255 -0
- package/templates/.opencode/skills/clean-code/SKILL.md +351 -0
- package/templates/.opencode/skills/code-philosophy/SKILL.md +512 -0
- package/templates/.opencode/skills/frontend-design/SKILL.md +237 -0
- package/templates/.opencode/skills/intelligent-routing/SKILL.md +195 -0
- package/templates/.opencode/skills/parallel-agents/SKILL.md +274 -0
- package/templates/.opencode/skills/plan-writing/SKILL.md +251 -0
- package/templates/.opencode/skills/systematic-debugging/SKILL.md +210 -0
- package/templates/.opencode/skills/testing-patterns/SKILL.md +252 -0
- package/templates/.opencode/workflows/brainstorm.md +110 -0
- package/templates/.opencode/workflows/create.md +108 -0
- package/templates/.opencode/workflows/debug.md +128 -0
- package/templates/.opencode/workflows/deploy.md +160 -0
- package/templates/.opencode/workflows/enhance.md +253 -0
- package/templates/.opencode/workflows/orchestrate.md +130 -0
- package/templates/.opencode/workflows/plan.md +163 -0
- package/templates/.opencode/workflows/review.md +135 -0
- package/templates/.opencode/workflows/status.md +102 -0
- package/templates/.opencode/workflows/test.md +146 -0
- package/templates/AGENTS.template.md +426 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# opencode-agile-agent
|
|
2
|
+
|
|
3
|
+
Scaffold OpenCode LLM SpecKit into any project with a single command.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# default
|
|
9
|
+
npx opencode-agile-agent
|
|
10
|
+
|
|
11
|
+
# explicit latest (recommended for docs/releases)
|
|
12
|
+
npx opencode-agile-agent@latest
|
|
13
|
+
|
|
14
|
+
# legacy alias (still supported)
|
|
15
|
+
npx create-opencode-agile
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What This CLI Installs
|
|
19
|
+
|
|
20
|
+
This package copies a full .opencode template into your target project, including:
|
|
21
|
+
|
|
22
|
+
1. Specialist agents in .opencode/agents
|
|
23
|
+
2. Reusable skills in .opencode/skills
|
|
24
|
+
3. Workflow commands in .opencode/workflows
|
|
25
|
+
4. Shared rules in .opencode/rules
|
|
26
|
+
5. Project docs and config under .opencode
|
|
27
|
+
6. A generated AGENTS.md in project root
|
|
28
|
+
|
|
29
|
+
## Template Source Of Truth
|
|
30
|
+
|
|
31
|
+
The installer uses the folder below as the template source:
|
|
32
|
+
|
|
33
|
+
- templates/.opencode
|
|
34
|
+
|
|
35
|
+
This folder is now synced from the project .opencode kit so every npx install gets the same LLM SpecKit content.
|
|
36
|
+
|
|
37
|
+
## Installed Structure (Summary)
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
your-project/
|
|
41
|
+
├── .opencode/
|
|
42
|
+
│ ├── agents/
|
|
43
|
+
│ ├── skills/
|
|
44
|
+
│ ├── workflows/
|
|
45
|
+
│ ├── rules/
|
|
46
|
+
│ ├── ARCHITECTURE.md
|
|
47
|
+
│ ├── README.md
|
|
48
|
+
│ ├── config.template.json
|
|
49
|
+
│ └── package.json
|
|
50
|
+
└── AGENTS.md
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Node.js 16+
|
|
56
|
+
|
|
57
|
+
## Development Notes
|
|
58
|
+
|
|
59
|
+
- Main CLI: bin/cli.js
|
|
60
|
+
- Template validator: bin/validate-templates.js
|
|
61
|
+
- Published files: bin, templates, README.md
|
|
62
|
+
|
|
63
|
+
## Validate Template Before Publish
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
node bin/validate-templates.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { existsSync, mkdirSync, cpSync, writeFileSync, readFileSync } from 'fs';
|
|
6
|
+
import { createInterface } from 'readline';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const templatesDir = join(__dirname, '..', 'templates');
|
|
11
|
+
|
|
12
|
+
// Colors for terminal output
|
|
13
|
+
const colors = {
|
|
14
|
+
reset: '\x1b[0m',
|
|
15
|
+
bright: '\x1b[1m',
|
|
16
|
+
green: '\x1b[32m',
|
|
17
|
+
blue: '\x1b[34m',
|
|
18
|
+
yellow: '\x1b[33m',
|
|
19
|
+
cyan: '\x1b[36m',
|
|
20
|
+
red: '\x1b[31m',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const log = {
|
|
24
|
+
info: (msg) => console.log(`${colors.blue}ℹ${colors.reset} ${msg}`),
|
|
25
|
+
success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
|
|
26
|
+
warn: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
|
|
27
|
+
error: (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`),
|
|
28
|
+
title: (msg) => console.log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ASCII Art Banner
|
|
32
|
+
const banner = `
|
|
33
|
+
${colors.cyan}╔═══════════════════════════════════════════════════════════╗
|
|
34
|
+
║ ║
|
|
35
|
+
║ ${colors.bright}OpenCode Agile Agent - Spec-Driven Development${colors.reset}${colors.cyan} ║
|
|
36
|
+
║ ║
|
|
37
|
+
╚═══════════════════════════════════════════════════════════╝${colors.reset}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
// Create readline interface
|
|
41
|
+
const rl = createInterface({
|
|
42
|
+
input: process.stdin,
|
|
43
|
+
output: process.stdout
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Promisify question
|
|
47
|
+
const question = (prompt) => new Promise((resolve) => {
|
|
48
|
+
rl.question(prompt, resolve);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Detect project framework
|
|
52
|
+
async function detectProjectFramework() {
|
|
53
|
+
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
54
|
+
|
|
55
|
+
if (!existsSync(packageJsonPath)) {
|
|
56
|
+
return { framework: 'unknown', language: 'javascript' };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
61
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
62
|
+
|
|
63
|
+
// Detect framework
|
|
64
|
+
if (deps['next']) return { framework: 'next', language: 'typescript' };
|
|
65
|
+
if (deps['nuxt']) return { framework: 'nuxt', language: 'typescript' };
|
|
66
|
+
if (deps['@angular/core']) return { framework: 'angular', language: 'typescript' };
|
|
67
|
+
if (deps['svelte']) return { framework: 'svelte', language: 'typescript' };
|
|
68
|
+
if (deps['vue'] || deps['vue2'] || deps['vue3']) return { framework: 'vue', language: 'typescript' };
|
|
69
|
+
if (deps['react'] || deps['react-dom']) return { framework: 'react', language: 'typescript' };
|
|
70
|
+
if (deps['express']) return { framework: 'express', language: 'typescript' };
|
|
71
|
+
if (deps['fastify']) return { framework: 'fastify', language: 'typescript' };
|
|
72
|
+
if (deps['nestjs'] || deps['@nestjs/core']) return { framework: 'nestjs', language: 'typescript' };
|
|
73
|
+
|
|
74
|
+
// Check for TypeScript
|
|
75
|
+
const hasTypeScript = deps['typescript'] || existsSync(join(process.cwd(), 'tsconfig.json'));
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
framework: 'generic',
|
|
79
|
+
language: hasTypeScript ? 'typescript' : 'javascript'
|
|
80
|
+
};
|
|
81
|
+
} catch {
|
|
82
|
+
return { framework: 'unknown', language: 'javascript' };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Framework options
|
|
87
|
+
const frameworkOptions = [
|
|
88
|
+
{ name: 'React', value: 'react' },
|
|
89
|
+
{ name: 'Vue.js', value: 'vue' },
|
|
90
|
+
{ name: 'Next.js', value: 'next' },
|
|
91
|
+
{ name: 'Nuxt.js', value: 'nuxt' },
|
|
92
|
+
{ name: 'Angular', value: 'angular' },
|
|
93
|
+
{ name: 'Svelte', value: 'svelte' },
|
|
94
|
+
{ name: 'NestJS', value: 'nestjs' },
|
|
95
|
+
{ name: 'Express', value: 'express' },
|
|
96
|
+
{ name: 'Fastify', value: 'fastify' },
|
|
97
|
+
{ name: 'Generic / Other', value: 'generic' },
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
// Generate AGENTS.md based on project config
|
|
101
|
+
function generateAgentsMd(config) {
|
|
102
|
+
const { projectName, framework, language, styling, stateManagement, testing } = config;
|
|
103
|
+
|
|
104
|
+
return `# AGENTS.md - ${projectName}
|
|
105
|
+
|
|
106
|
+
> **Instructions for AI agents working on this project**
|
|
107
|
+
>
|
|
108
|
+
> This file defines _how_ to build. For _what_ to build, see feature requirements.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 📦 Project Stack
|
|
113
|
+
|
|
114
|
+
- **Framework:** ${framework.charAt(0).toUpperCase() + framework.slice(1)}
|
|
115
|
+
- **Language:** ${language.charAt(0).toUpperCase() + language.slice(1)}
|
|
116
|
+
- **Styling:** ${styling}
|
|
117
|
+
- **State Management:** ${stateManagement}
|
|
118
|
+
- **Testing:** ${testing}
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 📚 Core Documentation (CRITICAL)
|
|
123
|
+
|
|
124
|
+
Before making architectural or styling decisions, **review** these documents:
|
|
125
|
+
|
|
126
|
+
| Document | Purpose | Location |
|
|
127
|
+
|----------|---------|----------|
|
|
128
|
+
| API Standards | API response structure, error handling | \`docs/api-standards.md\` |
|
|
129
|
+
| UI Standards | Styling rules, component patterns | \`docs/ui-standards.md\` |
|
|
130
|
+
| Code Style | Linting, formatting rules | \`.eslintrc.js\`, \`.prettierrc\` |
|
|
131
|
+
| Architecture | System design, data flow | \`docs/architecture.md\` |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🎨 Code Conventions
|
|
136
|
+
|
|
137
|
+
### File Naming
|
|
138
|
+
|
|
139
|
+
| Type | Pattern | Example |
|
|
140
|
+
|------|---------|---------|
|
|
141
|
+
| Components | \`PascalCase.tsx\` | \`UserCard.tsx\` |
|
|
142
|
+
| Pages | \`PascalCasePage.tsx\` | \`LoginPage.tsx\` |
|
|
143
|
+
| Stores | \`camelCase.store.ts\` | \`auth.store.ts\` |
|
|
144
|
+
| Hooks/Composables | \`useCamelCase.ts\` | \`useAuth.ts\` |
|
|
145
|
+
| Types | \`camelCase.types.ts\` | \`user.types.ts\` |
|
|
146
|
+
| Utils | \`camelCase.utils.ts\` | \`date.utils.ts\` |
|
|
147
|
+
| API | \`camelCase.api.ts\` | \`auth.api.ts\` |
|
|
148
|
+
| Tests | \`*.test.ts\` or \`*.spec.ts\` | \`auth.test.ts\` |
|
|
149
|
+
|
|
150
|
+
### Code Style
|
|
151
|
+
|
|
152
|
+
- **Indentation:** 2 spaces
|
|
153
|
+
- **Quotes:** single
|
|
154
|
+
- **Semicolons:** required
|
|
155
|
+
- **Line Width:** 100
|
|
156
|
+
- **Trailing Commas:** es5
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 🔧 Project-Specific Rules
|
|
161
|
+
|
|
162
|
+
<!-- ADD YOUR CUSTOM RULES HERE -->
|
|
163
|
+
|
|
164
|
+
### Rule 1: Error Handling
|
|
165
|
+
|
|
166
|
+
Always use proper error typing:
|
|
167
|
+
|
|
168
|
+
\`\`\`typescript
|
|
169
|
+
// ✅ GOOD
|
|
170
|
+
try {
|
|
171
|
+
await saveUser(user);
|
|
172
|
+
} catch (err: unknown) {
|
|
173
|
+
const e = err as { response?: { data?: { message?: string } } };
|
|
174
|
+
error.value = e.response?.data?.message ?? 'Operation failed';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ❌ BAD
|
|
178
|
+
catch (err: any) {
|
|
179
|
+
error.value = err.message;
|
|
180
|
+
}
|
|
181
|
+
\`\`\`
|
|
182
|
+
|
|
183
|
+
### Rule 2: Type Safety
|
|
184
|
+
|
|
185
|
+
Always use explicit types, never \`any\`:
|
|
186
|
+
|
|
187
|
+
\`\`\`typescript
|
|
188
|
+
// ✅ GOOD
|
|
189
|
+
interface User {
|
|
190
|
+
id: string;
|
|
191
|
+
name: string;
|
|
192
|
+
email: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function getUser(id: string): Promise<User> {
|
|
196
|
+
return api.get(\`/users/\${id}\`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ❌ BAD
|
|
200
|
+
function getUser(id: any): any {
|
|
201
|
+
return api.get(\`/users/\${id}\`);
|
|
202
|
+
}
|
|
203
|
+
\`\`\`
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🧪 Testing Standards
|
|
208
|
+
|
|
209
|
+
### Unit Tests
|
|
210
|
+
|
|
211
|
+
\`\`\`typescript
|
|
212
|
+
describe('useAuthStore', () => {
|
|
213
|
+
beforeEach(() => {
|
|
214
|
+
// Setup
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
afterEach(() => {
|
|
218
|
+
// Cleanup
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should login successfully', async () => {
|
|
222
|
+
// Arrange
|
|
223
|
+
const credentials = { email: 'test@example.com', password: 'password' };
|
|
224
|
+
|
|
225
|
+
// Act
|
|
226
|
+
await authStore.login(credentials);
|
|
227
|
+
|
|
228
|
+
// Assert
|
|
229
|
+
expect(authStore.isAuthenticated).toBe(true);
|
|
230
|
+
expect(authStore.user).toBeDefined();
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
\`\`\`
|
|
234
|
+
|
|
235
|
+
### Test Coverage
|
|
236
|
+
|
|
237
|
+
- **Minimum:** 70% coverage
|
|
238
|
+
- **Target:** 80% coverage
|
|
239
|
+
- **Critical paths:** 100% coverage (auth, payments, etc.)
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## 🚀 Quick Reference
|
|
244
|
+
|
|
245
|
+
### Commands
|
|
246
|
+
|
|
247
|
+
\`\`\`bash
|
|
248
|
+
# Development
|
|
249
|
+
npm run dev # Start dev server
|
|
250
|
+
npm run build # Production build
|
|
251
|
+
npm run test # Run tests
|
|
252
|
+
npm run lint # Lint check
|
|
253
|
+
npm run format # Format code
|
|
254
|
+
npm run type-check # TypeScript check (if applicable)
|
|
255
|
+
\`\`\`
|
|
256
|
+
|
|
257
|
+
### Important Files
|
|
258
|
+
|
|
259
|
+
\`\`\`
|
|
260
|
+
src/
|
|
261
|
+
├── components/ # Reusable components
|
|
262
|
+
├── pages/ # Page components
|
|
263
|
+
├── stores/ # State management
|
|
264
|
+
├── api/ # API calls
|
|
265
|
+
├── types/ # TypeScript types
|
|
266
|
+
├── utils/ # Utility functions
|
|
267
|
+
└── hooks/ # Custom hooks/composables
|
|
268
|
+
\`\`\`
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 💡 Key Reminders
|
|
273
|
+
|
|
274
|
+
1. **Follow existing patterns** - Check similar files first
|
|
275
|
+
2. **Handle errors gracefully** - Always use try/catch/finally
|
|
276
|
+
3. **Think about loading states** - UX matters
|
|
277
|
+
4. **Use TypeScript strictly** - No \`any\` types
|
|
278
|
+
5. **Test your code** - Write tests for critical logic
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
**Keep this file updated as the project evolves.**
|
|
283
|
+
`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Main installation function
|
|
287
|
+
async function install() {
|
|
288
|
+
console.log(banner);
|
|
289
|
+
|
|
290
|
+
log.title('🚀 OpenCode Agile Agent Installer');
|
|
291
|
+
|
|
292
|
+
// Check if .opencode already exists
|
|
293
|
+
const opencodePath = join(process.cwd(), '.opencode');
|
|
294
|
+
if (existsSync(opencodePath)) {
|
|
295
|
+
log.warn('.opencode directory already exists!');
|
|
296
|
+
const overwrite = await question('Do you want to overwrite it? (y/N): ');
|
|
297
|
+
if (overwrite.toLowerCase() !== 'y') {
|
|
298
|
+
log.info('Installation cancelled.');
|
|
299
|
+
rl.close();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Detect project
|
|
305
|
+
log.info('Detecting project configuration...');
|
|
306
|
+
const detected = await detectProjectFramework();
|
|
307
|
+
|
|
308
|
+
log.info(`Detected: ${detected.framework} (${detected.language})`);
|
|
309
|
+
|
|
310
|
+
// Ask for project details
|
|
311
|
+
log.title('📝 Project Configuration');
|
|
312
|
+
|
|
313
|
+
// Project name
|
|
314
|
+
let projectName = '';
|
|
315
|
+
try {
|
|
316
|
+
const packageJson = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf-8'));
|
|
317
|
+
projectName = packageJson.name || 'My Project';
|
|
318
|
+
} catch {
|
|
319
|
+
projectName = 'My Project';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const customName = await question(`Project name (${projectName}): `);
|
|
323
|
+
projectName = customName || projectName;
|
|
324
|
+
|
|
325
|
+
// Framework selection
|
|
326
|
+
log.info('\nAvailable frameworks:');
|
|
327
|
+
frameworkOptions.forEach((opt, i) => {
|
|
328
|
+
const marker = opt.value === detected.framework ? ' (detected)' : '';
|
|
329
|
+
console.log(` ${i + 1}. ${opt.name}${marker}`);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const frameworkInput = await question(`Select framework (1-${frameworkOptions.length}) [default: ${detected.framework}]: `);
|
|
333
|
+
let framework = detected.framework;
|
|
334
|
+
if (frameworkInput) {
|
|
335
|
+
const idx = parseInt(frameworkInput) - 1;
|
|
336
|
+
if (idx >= 0 && idx < frameworkOptions.length) {
|
|
337
|
+
framework = frameworkOptions[idx].value;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Language
|
|
342
|
+
const languageInput = await question(`Language (typescript/javascript) [default: ${detected.language}]: `);
|
|
343
|
+
const language = languageInput || detected.language;
|
|
344
|
+
|
|
345
|
+
// Styling
|
|
346
|
+
const stylingInput = await question(`Styling (tailwind/css-modules/styled-components/scss/other) [default: tailwind]: `);
|
|
347
|
+
const styling = stylingInput || 'tailwind';
|
|
348
|
+
|
|
349
|
+
// State management
|
|
350
|
+
const stateInput = await question(`State management (pinia/zustand/redux/none) [default: none]: `);
|
|
351
|
+
const stateManagement = stateInput || 'none';
|
|
352
|
+
|
|
353
|
+
// Testing
|
|
354
|
+
const testingInput = await question(`Testing (jest/vitest/mocha/none) [default: vitest]: `);
|
|
355
|
+
const testing = testingInput || 'vitest';
|
|
356
|
+
|
|
357
|
+
const config = { projectName, framework, language, styling, stateManagement, testing };
|
|
358
|
+
|
|
359
|
+
log.title('📦 Installing OpenCode Agile Agent...');
|
|
360
|
+
|
|
361
|
+
// Create .opencode directory
|
|
362
|
+
try {
|
|
363
|
+
// Copy templates
|
|
364
|
+
log.info('Copying templates...');
|
|
365
|
+
|
|
366
|
+
// Create .opencode directory
|
|
367
|
+
if (!existsSync(opencodePath)) {
|
|
368
|
+
mkdirSync(opencodePath, { recursive: true });
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Copy all template files
|
|
372
|
+
const templateOpencode = join(templatesDir, '.opencode');
|
|
373
|
+
if (existsSync(templateOpencode)) {
|
|
374
|
+
cpSync(templateOpencode, opencodePath, { recursive: true, overwrite: true });
|
|
375
|
+
log.success('Templates copied successfully');
|
|
376
|
+
} else {
|
|
377
|
+
log.error('Templates directory not found!');
|
|
378
|
+
rl.close();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Generate AGENTS.md
|
|
383
|
+
log.info('Generating AGENTS.md...');
|
|
384
|
+
const agentsMd = generateAgentsMd(config);
|
|
385
|
+
writeFileSync(join(process.cwd(), 'AGENTS.md'), agentsMd);
|
|
386
|
+
log.success('AGENTS.md generated');
|
|
387
|
+
|
|
388
|
+
// Success message
|
|
389
|
+
log.title('✅ Installation Complete!');
|
|
390
|
+
|
|
391
|
+
console.log(`
|
|
392
|
+
${colors.green}OpenCode Agile Agent has been installed successfully!${colors.reset}
|
|
393
|
+
|
|
394
|
+
${colors.cyan}What's included:${colors.reset}
|
|
395
|
+
✓ .opencode/agents/ - Full LLM SpecKit agent set
|
|
396
|
+
✓ .opencode/skills/ - Reusable skill modules
|
|
397
|
+
✓ .opencode/workflows/ - Workflow command templates
|
|
398
|
+
✓ .opencode/rules/ - Shared coding and git conventions
|
|
399
|
+
✓ .opencode/README.md - Kit documentation
|
|
400
|
+
✓ AGENTS.md - Project-specific coding standards
|
|
401
|
+
|
|
402
|
+
${colors.cyan}Next steps:${colors.reset}
|
|
403
|
+
1. Review and customize AGENTS.md for your project
|
|
404
|
+
2. Start using agents with your AI assistant
|
|
405
|
+
3. Read .opencode/README.md for detailed workflow
|
|
406
|
+
|
|
407
|
+
${colors.cyan}Example usage:${colors.reset}
|
|
408
|
+
"I want to implement user authentication with JWT"
|
|
409
|
+
|
|
410
|
+
The agents will:
|
|
411
|
+
→ Gather requirements
|
|
412
|
+
→ Create specs and task breakdown
|
|
413
|
+
→ Implement the feature
|
|
414
|
+
→ Review code quality
|
|
415
|
+
→ ✅ Deliver production-ready code
|
|
416
|
+
|
|
417
|
+
${colors.yellow}Happy coding with AI-powered agile development! 🚀${colors.reset}
|
|
418
|
+
`);
|
|
419
|
+
|
|
420
|
+
} catch (error) {
|
|
421
|
+
log.error(`Installation failed: ${error.message}`);
|
|
422
|
+
console.error(error);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
rl.close();
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Run installation
|
|
429
|
+
install().catch((error) => {
|
|
430
|
+
log.error(`Unexpected error: ${error.message}`);
|
|
431
|
+
console.error(error);
|
|
432
|
+
rl.close();
|
|
433
|
+
process.exit(1);
|
|
434
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { existsSync, statSync } from 'fs';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const templatesDir = join(__dirname, '..', 'templates');
|
|
10
|
+
|
|
11
|
+
// Required files for templates
|
|
12
|
+
const requiredFiles = [
|
|
13
|
+
'.opencode/README.md',
|
|
14
|
+
'.opencode/ARCHITECTURE.md',
|
|
15
|
+
'.opencode/config.template.json',
|
|
16
|
+
'.opencode/package.json',
|
|
17
|
+
'.opencode/agents/orchestrator.md',
|
|
18
|
+
'.opencode/agents/feature-lead.md',
|
|
19
|
+
'.opencode/agents/developer.md',
|
|
20
|
+
'.opencode/agents/system-analyst.md',
|
|
21
|
+
'.opencode/agents/pr-reviewer.md',
|
|
22
|
+
'.opencode/skills/clean-code/SKILL.md',
|
|
23
|
+
'.opencode/skills/plan-writing/SKILL.md',
|
|
24
|
+
'.opencode/skills/testing-patterns/SKILL.md',
|
|
25
|
+
'.opencode/workflows/create.md',
|
|
26
|
+
'.opencode/workflows/plan.md',
|
|
27
|
+
'.opencode/workflows/review.md',
|
|
28
|
+
'.opencode/rules/coding-standards.md',
|
|
29
|
+
'.opencode/rules/git-conventions.md',
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
let hasErrors = false;
|
|
33
|
+
|
|
34
|
+
// Check if templates directory exists
|
|
35
|
+
if (!existsSync(templatesDir)) {
|
|
36
|
+
console.error('❌ Templates directory not found!');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Check each required file
|
|
41
|
+
requiredFiles.forEach(file => {
|
|
42
|
+
const filePath = join(templatesDir, file);
|
|
43
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
44
|
+
console.log(`✓ ${file}`);
|
|
45
|
+
} else {
|
|
46
|
+
console.error(`✗ ${file} - Missing`);
|
|
47
|
+
hasErrors = true;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log('');
|
|
52
|
+
if (hasErrors) {
|
|
53
|
+
console.error('❌ Validation failed! Some required files are missing.');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
} else {
|
|
56
|
+
console.log('✅ All templates validated successfully!');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-agile-agent",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "AI Agile Spec-Driven Development - Install .opencode agile agent system into any project",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"agile",
|
|
8
|
+
"spec-driven",
|
|
9
|
+
"opencode",
|
|
10
|
+
"cli",
|
|
11
|
+
"scaffold",
|
|
12
|
+
"template",
|
|
13
|
+
"agent",
|
|
14
|
+
"development"
|
|
15
|
+
],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"bin": {
|
|
20
|
+
"opencode-agile-agent": "./bin/cli.js",
|
|
21
|
+
"create-opencode-agile": "./bin/cli.js"
|
|
22
|
+
},
|
|
23
|
+
"main": "./bin/cli.js",
|
|
24
|
+
"files": [
|
|
25
|
+
"bin",
|
|
26
|
+
"templates",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=16.0.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "node bin/cli.js --help",
|
|
34
|
+
"prepublishOnly": "node bin/validate-templates.js"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"chalk": "^5.3.0",
|
|
38
|
+
"commander": "^12.0.0",
|
|
39
|
+
"fs-extra": "^11.2.0",
|
|
40
|
+
"inquirer": "^9.2.15",
|
|
41
|
+
"ora": "^8.0.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": ""
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": ""
|
|
50
|
+
},
|
|
51
|
+
"homepage": ""
|
|
52
|
+
}
|