agents.dev 1.0.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/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Agents.dev
2
+
3
+ **Agents.dev** is a CLI tool that acts as a "Source of Truth" for your AI Development Agents.
4
+ Inspired by tools like *Specify*, it allows you to define your agent personas in a single, agnostic YAML format and "compile" them into configuration files for various AI coding assistants.
5
+
6
+ ## 🚀 Supported Targets
7
+
8
+ The CLI currently installs agents directly into the configuration paths for:
9
+
10
+ - **Gemini CLI**: `.gemini/commands/dev/`
11
+ - **Roo Code**: `.roo/commands/`
12
+ - **Kilo Code**: `.kilocode/workflows/`
13
+ - **OpenCode**: `.opencode/command/`
14
+
15
+ ## 📦 Installation
16
+
17
+ This project is designed to be run as a dev dependency or a local tool within your repository.
18
+
19
+ ```bash
20
+ npm install
21
+ ```
22
+
23
+ ## 🛠️ Usage
24
+
25
+ ### 1. Define your Agents
26
+ Create YAML files in the `definitions/` directory.
27
+
28
+ **Example:** `definitions/backend-architect.yaml`
29
+ ```yaml
30
+ name: Backend Architect
31
+ role: Senior Backend Engineer
32
+ emoji: 🏗️
33
+ systemPrompt: |
34
+ You are a Senior Backend Engineer.
35
+ You specialize in Scalable Node.js APIs.
36
+ rules:
37
+ - Always write unit tests.
38
+ - Use snake_case for database columns.
39
+ ```
40
+
41
+ ### 2. Build/Install
42
+ Run the start command to convert your YAMLs into target configurations.
43
+
44
+ **Interactive Mode:**
45
+ ```bash
46
+ npm start
47
+ ```
48
+ *Select which targets you want to update using the interactive menu.*
49
+
50
+ **CLI Mode (CI/CD friendly):**
51
+ ```bash
52
+ npm start -- --target gemini,roo
53
+ ```
54
+
55
+ ## ✅ Validation
56
+ The CLI includes Zod validation to ensure your definitions are complete.
57
+ Required fields:
58
+ - `name`
59
+ - `role`
60
+ - `systemPrompt` (min 10 characters)
61
+
62
+ ## 📂 Project Structure
63
+ ```text
64
+ .
65
+ ├── definitions/ # Your Source of Truth (YAML)
66
+ ├── src/ # CLI Source Code
67
+ ├── .gemini/ # Generated Gemini Commands
68
+ ├── .roo/ # Generated Roo Contexts
69
+ ├── .kilocode/ # Generated Kilo Workflows
70
+ └── .opencode/ # Generated OpenCode Commands
71
+ ```
@@ -0,0 +1,12 @@
1
+ name: Backend Architect
2
+ role: Senior Backend Engineer specializes in scalable APIs
3
+ emoji: 🏗️
4
+ systemPrompt: |
5
+ You are a Senior Backend Engineer. Your goal is to design and implement scalable, robust, and secure backend systems.
6
+ You prefer Node.js with TypeScript or Python with FastAPI.
7
+ You always consider performance implications.
8
+ rules:
9
+ - Follow RESTful API design principles.
10
+ - Use environment variables for secrets.
11
+ - Write unit tests for all business logic.
12
+ - Document API endpoints.
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "agents.dev",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "start": "npx ts-node src/index.ts build"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "type": "commonjs",
14
+ "dependencies": {
15
+ "@types/inquirer": "^9.0.9",
16
+ "chalk": "^5.6.2",
17
+ "commander": "^14.0.2",
18
+ "fs-extra": "^11.3.2",
19
+ "inquirer": "^8.2.7",
20
+ "user": "^0.0.0",
21
+ "yaml": "^2.8.2",
22
+ "zod": "^4.1.13"
23
+ },
24
+ "devDependencies": {
25
+ "@types/fs-extra": "^11.0.4",
26
+ "@types/node": "^25.0.1",
27
+ "ts-node": "^10.9.2",
28
+ "typescript": "^5.9.3"
29
+ }
30
+ }
package/src/index.ts ADDED
@@ -0,0 +1,140 @@
1
+ import { Command } from 'commander';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import YAML from 'yaml';
5
+ import chalk from 'chalk';
6
+ import inquirer from 'inquirer';
7
+ import { AgentDefinition, AgentSchema } from './types';
8
+ import { toGeminiSystemPrompt } from './transformers/gemini';
9
+ import { toRooRules } from './transformers/roo';
10
+ import { toKiloConfig } from './transformers/kilo';
11
+ import { toOpenCodeCommand } from './transformers/opencode';
12
+
13
+ const program = new Command();
14
+
15
+ program
16
+ .name('agents')
17
+ .description('Agent Installer CLI')
18
+ .version('1.0.0');
19
+
20
+ program
21
+ .command('build')
22
+ .description('Build agent definitions into target formats')
23
+ .option('-o, --out <dir>', 'Output directory', '.')
24
+ .option('-t, --target <targets>', 'Comma-separated target formats (gemini, roo, kilo, opencode)')
25
+ .action(async (options) => {
26
+ const definitionsDir = path.join(process.cwd(), 'definitions');
27
+ const outDir = path.resolve(options.out);
28
+
29
+ // Determine targets
30
+ let selectedTargets: string[] = [];
31
+ if (options.target) {
32
+ selectedTargets = options.target.split(',').map((t: string) => t.trim().toLowerCase());
33
+ } else {
34
+ const answers = await inquirer.prompt([
35
+ {
36
+ type: 'checkbox',
37
+ name: 'targets',
38
+ message: 'Select target formats to build:',
39
+ choices: [
40
+ { name: 'Gemini CLI', value: 'gemini', checked: true },
41
+ { name: 'Roo Code', value: 'roo', checked: false },
42
+ { name: 'Kilo Code', value: 'kilo', checked: false },
43
+ { name: 'OpenCode', value: 'opencode', checked: false }
44
+ ],
45
+ validate: (answer) => {
46
+ if (answer.length < 1) {
47
+ return 'You must choose at least one target.';
48
+ }
49
+ return true;
50
+ }
51
+ }
52
+ ]);
53
+ selectedTargets = answers.targets;
54
+ }
55
+
56
+ if (selectedTargets.length === 0) {
57
+ console.log(chalk.yellow('No targets selected. Exiting.'));
58
+ return;
59
+ }
60
+
61
+ console.log(chalk.blue(`Building agents from ${definitionsDir} to ${outDir}...`));
62
+ console.log(chalk.blue(`Targets: ${selectedTargets.join(', ')}`));
63
+
64
+ try {
65
+ if (outDir !== process.cwd()) {
66
+ await fs.ensureDir(outDir);
67
+ }
68
+
69
+ const files = await fs.readdir(definitionsDir);
70
+
71
+ for (const file of files) {
72
+ if (!file.endsWith('.yaml') && !file.endsWith('.yml')) continue;
73
+
74
+ const content = await fs.readFile(path.join(definitionsDir, file), 'utf-8');
75
+ const rawAgent = YAML.parse(content);
76
+ const parseResult = AgentSchema.safeParse(rawAgent);
77
+
78
+ if (!parseResult.success) {
79
+ console.error(chalk.red(`Validation failed for ${file}:`));
80
+ parseResult.error.issues.forEach((err) => {
81
+ console.error(chalk.red(` - ${err.path.join('.')}: ${err.message}`));
82
+ });
83
+ continue; // Skip this agent
84
+ }
85
+
86
+ const agent = parseResult.data;
87
+ const slug = file.replace(/\.(yaml|yml)$/, '');
88
+
89
+ console.log(chalk.green(`Processing agent: ${agent.name} (${slug})`));
90
+
91
+ // specific outputs
92
+ const allTargets = [
93
+ {
94
+ id: 'gemini',
95
+ subDir: '.gemini/commands/dev',
96
+ ext: 'md',
97
+ content: toGeminiSystemPrompt(agent),
98
+ name: `${slug}.md`
99
+ },
100
+ {
101
+ id: 'roo',
102
+ subDir: '.roo/commands',
103
+ ext: 'md',
104
+ content: toRooRules(agent),
105
+ name: `${slug}.md`
106
+ },
107
+ {
108
+ id: 'kilo',
109
+ subDir: '.kilocode/workflows',
110
+ ext: 'md',
111
+ content: toKiloConfig(agent),
112
+ name: `${slug}.md`
113
+ },
114
+ {
115
+ id: 'opencode',
116
+ subDir: '.opencode/command',
117
+ ext: 'md',
118
+ content: toOpenCodeCommand(agent),
119
+ name: `${slug}.md`
120
+ }
121
+ ];
122
+
123
+ const targetsToBuild = allTargets.filter(t => selectedTargets.includes(t.id));
124
+
125
+ for (const target of targetsToBuild) {
126
+ const targetDir = path.join(outDir, target.subDir);
127
+ await fs.ensureDir(targetDir);
128
+ await fs.writeFile(path.join(targetDir, target.name), target.content);
129
+ console.log(chalk.gray(` -> ${target.subDir}/${target.name}`));
130
+ }
131
+ }
132
+ console.log(chalk.bold.green('Build complete!'));
133
+
134
+ } catch (err) {
135
+ console.error(chalk.red('Build failed:'), err);
136
+ process.exit(1);
137
+ }
138
+ });
139
+
140
+ program.parse(process.argv);
@@ -0,0 +1,31 @@
1
+ import { AgentDefinition } from '../types';
2
+
3
+ export function toGeminiSystemPrompt(agent: AgentDefinition): string {
4
+ const parts = [];
5
+
6
+ // Identity
7
+ parts.push(`# Identity\n`);
8
+ parts.push(`You are **${agent.name}** ${agent.emoji || ''}`);
9
+ parts.push(`Role: ${agent.role}\n`);
10
+
11
+ // System Prompt
12
+ parts.push(`# Core Instructions\n`);
13
+ parts.push(agent.systemPrompt.trim());
14
+ parts.push('\n');
15
+
16
+ // Rules
17
+ if (agent.rules && agent.rules.length > 0) {
18
+ parts.push(`# Rules & Guidelines\n`);
19
+ agent.rules.forEach(rule => parts.push(`- ${rule}`));
20
+ parts.push('\n');
21
+ }
22
+
23
+ // Tools (if any)
24
+ if (agent.tools && agent.tools.length > 0) {
25
+ parts.push(`# Preferred Tools\n`);
26
+ agent.tools.forEach(tool => parts.push(`- ${tool}`));
27
+ parts.push('\n');
28
+ }
29
+
30
+ return parts.join('\n');
31
+ }
@@ -0,0 +1,21 @@
1
+ import { AgentDefinition } from '../types';
2
+
3
+ export function toKiloConfig(agent: AgentDefinition): string {
4
+ // Kilo Code generic config/prompt
5
+ const parts = [];
6
+
7
+ parts.push(`<!--- Kilo Code Agent Config --->`);
8
+ parts.push(`# ${agent.name} ${agent.emoji || ''}`);
9
+ parts.push(`**Role**: ${agent.role}\n`);
10
+
11
+ parts.push(`## Instructions`);
12
+ parts.push(agent.systemPrompt.trim());
13
+ parts.push('\n');
14
+
15
+ if (agent.rules && agent.rules.length > 0) {
16
+ parts.push(`## Constraints`);
17
+ agent.rules.forEach(rule => parts.push(`- ${rule}`));
18
+ }
19
+
20
+ return parts.join('\n');
21
+ }
@@ -0,0 +1,21 @@
1
+ import { AgentDefinition } from '../types';
2
+
3
+ export function toOpenCodeCommand(agent: AgentDefinition): string {
4
+ // OpenCode generic config/prompt
5
+ const parts = [];
6
+
7
+ parts.push(`<!--- OpenCode Agent Config --->`);
8
+ parts.push(`# ${agent.name} ${agent.emoji || ''}`);
9
+ parts.push(`**Role**: ${agent.role}\n`);
10
+
11
+ parts.push(`## Instructions`);
12
+ parts.push(agent.systemPrompt.trim());
13
+ parts.push('\n');
14
+
15
+ if (agent.rules && agent.rules.length > 0) {
16
+ parts.push(`## Constraints`);
17
+ agent.rules.forEach(rule => parts.push(`- ${rule}`));
18
+ }
19
+
20
+ return parts.join('\n');
21
+ }
@@ -0,0 +1,23 @@
1
+ import { AgentDefinition } from '../types';
2
+
3
+ export function toRooRules(agent: AgentDefinition): string {
4
+ // Roo Code / Cline usually expects a clear set of rules and role definition.
5
+ const parts = [];
6
+
7
+ parts.push(`# ${agent.name} (${agent.role})`);
8
+ parts.push(`\n${agent.systemPrompt.trim()}\n`);
9
+
10
+ if (agent.rules && agent.rules.length > 0) {
11
+ parts.push(`## Analytical Rules & Guidelines`);
12
+ agent.rules.forEach(rule => parts.push(`- ${rule}`));
13
+ parts.push('\n');
14
+ }
15
+
16
+ // Tools might be handled differently in Roo, but listing them as preferences is safe
17
+ if (agent.tools && agent.tools.length > 0) {
18
+ parts.push(`## Tool Usage Preferences`);
19
+ agent.tools.forEach(tool => parts.push(`- Prefer using ${tool} when applicable.`));
20
+ }
21
+
22
+ return parts.join('\n');
23
+ }
package/src/types.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+
3
+ export const AgentSchema = z.object({
4
+ name: z.string().min(1, "Name is required"),
5
+ role: z.string().min(1, "Role is required"),
6
+ emoji: z.string().optional(),
7
+ systemPrompt: z.string().min(10, "System prompt must be at least 10 characters"),
8
+ rules: z.array(z.string()).optional(),
9
+ tools: z.array(z.string()).optional()
10
+ });
11
+
12
+ export type AgentDefinition = z.infer<typeof AgentSchema>;
@@ -0,0 +1,19 @@
1
+ import inquirer from 'inquirer';
2
+
3
+ (async () => {
4
+ console.log('Testing inquirer checkbox...');
5
+ const answers = await inquirer.prompt([
6
+ {
7
+ type: 'checkbox',
8
+ name: 'targets',
9
+ message: 'Select target formats:',
10
+ choices: [
11
+ { name: 'Gemini CLI', value: 'gemini', checked: true },
12
+ { name: 'Roo Code', value: 'roo', checked: true },
13
+ { name: 'Kilo Code', value: 'kilo', checked: true },
14
+ { name: 'OpenCode', value: 'opencode', checked: true }
15
+ ]
16
+ }
17
+ ]);
18
+ console.log('Selected:', answers.targets);
19
+ })();
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "strict": true,
6
+ "esModuleInterop": true,
7
+ "skipLibCheck": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "outDir": "./dist",
10
+ "rootDir": "./src",
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["src/**/*"],
14
+ "exclude": ["node_modules"]
15
+ }