@agentfile/cli 0.1.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/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +26 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +275 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/sync.d.ts +4 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +68 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +25 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +11 -0
- package/dist/logger.js.map +1 -0
- package/package.json +44 -0
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { initCommand } from './commands/init.js';
|
|
5
|
+
import { syncCommand } from './commands/sync.js';
|
|
6
|
+
import { validateCommand } from './commands/validate.js';
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name('agentfile')
|
|
10
|
+
.description('Unified AI agent contract manager')
|
|
11
|
+
.version('0.1.0');
|
|
12
|
+
program
|
|
13
|
+
.command('init')
|
|
14
|
+
.description('Scaffold a new agentfile setup in the current project')
|
|
15
|
+
.action(initCommand);
|
|
16
|
+
program
|
|
17
|
+
.command('sync')
|
|
18
|
+
.description('Generate agent instruction files from ai/contract.yaml')
|
|
19
|
+
.option('--dry-run', 'Render templates without writing files')
|
|
20
|
+
.action((options) => syncCommand({ dryRun: options.dryRun }));
|
|
21
|
+
program
|
|
22
|
+
.command('validate')
|
|
23
|
+
.description('Validate ai/contract.yaml schema (used in CI)')
|
|
24
|
+
.action(validateCommand);
|
|
25
|
+
program.parse();
|
|
26
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,8BAA8B;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAU,oBAAoB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAU,oBAAoB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,mCAAmC,CAAC;KAChD,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,WAAW,EAAE,wCAAwC,CAAC;KAC7D,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AAE/D,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,eAAe,CAAC,CAAA;AAE1B,OAAO,CAAC,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA4NA,wBAAsB,WAAW,kBA4FhC"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
// ─── Scaffolding Templates ─────────────────────────────────────────────────
|
|
6
|
+
function contractYaml(name, stack) {
|
|
7
|
+
const stackList = stack.map(s => ` - ${s}`).join('\n');
|
|
8
|
+
return `version: 1
|
|
9
|
+
|
|
10
|
+
project:
|
|
11
|
+
name: ${name}
|
|
12
|
+
stack:
|
|
13
|
+
${stackList}
|
|
14
|
+
|
|
15
|
+
rules:
|
|
16
|
+
|
|
17
|
+
coding:
|
|
18
|
+
- Prefer small composable functions
|
|
19
|
+
- Avoid unnecessary abstractions
|
|
20
|
+
- Write readable code before optimizing
|
|
21
|
+
|
|
22
|
+
architecture:
|
|
23
|
+
- Follow feature-based folder structure
|
|
24
|
+
- Avoid cross-feature imports
|
|
25
|
+
|
|
26
|
+
testing:
|
|
27
|
+
- Critical business logic must have unit tests
|
|
28
|
+
- Prefer integration tests over mocks
|
|
29
|
+
|
|
30
|
+
naming:
|
|
31
|
+
- Use descriptive variable names
|
|
32
|
+
- Avoid abbreviations
|
|
33
|
+
|
|
34
|
+
skills:
|
|
35
|
+
|
|
36
|
+
- name: example-skill
|
|
37
|
+
description: Replace this with your first shared workflow
|
|
38
|
+
context:
|
|
39
|
+
- Add any relevant file paths or conventions here
|
|
40
|
+
steps:
|
|
41
|
+
- Describe the first step
|
|
42
|
+
- Describe the second step
|
|
43
|
+
expected_output: Describe what a correct result looks like
|
|
44
|
+
examples:
|
|
45
|
+
- input: "example input"
|
|
46
|
+
output: "example output"
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
const claudeTemplate = `# Project Instructions
|
|
50
|
+
|
|
51
|
+
**Project:** \${project.name}
|
|
52
|
+
**Stack:** \${project.stack.join(', ')}
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Coding Rules
|
|
57
|
+
|
|
58
|
+
\${rules.coding}
|
|
59
|
+
|
|
60
|
+
## Architecture
|
|
61
|
+
|
|
62
|
+
\${rules.architecture}
|
|
63
|
+
|
|
64
|
+
## Testing
|
|
65
|
+
|
|
66
|
+
\${rules.testing}
|
|
67
|
+
|
|
68
|
+
## Naming
|
|
69
|
+
|
|
70
|
+
\${rules.naming}
|
|
71
|
+
\${skills}
|
|
72
|
+
\${override}
|
|
73
|
+
`;
|
|
74
|
+
const copilotTemplate = `# Copilot Instructions
|
|
75
|
+
|
|
76
|
+
This file configures GitHub Copilot for the **\${project.name}** project.
|
|
77
|
+
Stack: \${project.stack.join(', ')}
|
|
78
|
+
|
|
79
|
+
## Coding
|
|
80
|
+
|
|
81
|
+
\${rules.coding}
|
|
82
|
+
|
|
83
|
+
## Architecture
|
|
84
|
+
|
|
85
|
+
\${rules.architecture}
|
|
86
|
+
|
|
87
|
+
## Testing
|
|
88
|
+
|
|
89
|
+
\${rules.testing}
|
|
90
|
+
|
|
91
|
+
## Naming Conventions
|
|
92
|
+
|
|
93
|
+
\${rules.naming}
|
|
94
|
+
\${skills}
|
|
95
|
+
\${override}
|
|
96
|
+
`;
|
|
97
|
+
const cursorTemplate = `---
|
|
98
|
+
description: \${project.name} — global coding rules
|
|
99
|
+
globs: ["**/*"]
|
|
100
|
+
alwaysApply: true
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
# \${project.name} Rules
|
|
104
|
+
|
|
105
|
+
Stack: \${project.stack.join(', ')}
|
|
106
|
+
|
|
107
|
+
## Coding
|
|
108
|
+
|
|
109
|
+
\${rules.coding}
|
|
110
|
+
|
|
111
|
+
## Architecture
|
|
112
|
+
|
|
113
|
+
\${rules.architecture}
|
|
114
|
+
|
|
115
|
+
## Testing
|
|
116
|
+
|
|
117
|
+
\${rules.testing}
|
|
118
|
+
|
|
119
|
+
## Naming
|
|
120
|
+
|
|
121
|
+
\${rules.naming}
|
|
122
|
+
\${override}
|
|
123
|
+
`;
|
|
124
|
+
const agentsMdTemplate = `# AGENTS.md
|
|
125
|
+
|
|
126
|
+
> This file is auto-generated by [agentfile](https://github.com/dennishavermans/agentfile).
|
|
127
|
+
> Edit \`ai/contract.yaml\` — do not edit this file directly.
|
|
128
|
+
|
|
129
|
+
**Project:** \${project.name}
|
|
130
|
+
**Stack:** \${project.stack.join(', ')}
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Coding Rules
|
|
135
|
+
|
|
136
|
+
\${rules.coding}
|
|
137
|
+
|
|
138
|
+
## Architecture
|
|
139
|
+
|
|
140
|
+
\${rules.architecture}
|
|
141
|
+
|
|
142
|
+
## Testing
|
|
143
|
+
|
|
144
|
+
\${rules.testing}
|
|
145
|
+
|
|
146
|
+
## Naming
|
|
147
|
+
|
|
148
|
+
\${rules.naming}
|
|
149
|
+
\${skills}
|
|
150
|
+
\${override}
|
|
151
|
+
`;
|
|
152
|
+
const agentsExample = `# Copy this file to .ai-agents (no extension) and list the agents you use.
|
|
153
|
+
# This file is gitignored — it is yours, not the team's.
|
|
154
|
+
#
|
|
155
|
+
# Available agents (one per line):
|
|
156
|
+
# claude
|
|
157
|
+
# copilot
|
|
158
|
+
# cursor
|
|
159
|
+
# agents-md
|
|
160
|
+
`;
|
|
161
|
+
const gitignoreAdditions = `
|
|
162
|
+
# agentfile — AI agent personal config and generated files
|
|
163
|
+
.ai-agents
|
|
164
|
+
CLAUDE.md
|
|
165
|
+
.github/copilot-instructions.md
|
|
166
|
+
.cursor/
|
|
167
|
+
.windsurfrules
|
|
168
|
+
ai.override.yaml
|
|
169
|
+
`;
|
|
170
|
+
const ciWorkflow = `name: Validate AI Contract
|
|
171
|
+
|
|
172
|
+
on:
|
|
173
|
+
push:
|
|
174
|
+
paths:
|
|
175
|
+
- 'ai/contract.yaml'
|
|
176
|
+
- 'ai/agents/**'
|
|
177
|
+
pull_request:
|
|
178
|
+
paths:
|
|
179
|
+
- 'ai/contract.yaml'
|
|
180
|
+
- 'ai/agents/**'
|
|
181
|
+
|
|
182
|
+
jobs:
|
|
183
|
+
validate:
|
|
184
|
+
name: Validate AI contract
|
|
185
|
+
runs-on: ubuntu-latest
|
|
186
|
+
steps:
|
|
187
|
+
- uses: actions/checkout@v4
|
|
188
|
+
- uses: actions/setup-node@v4
|
|
189
|
+
with:
|
|
190
|
+
node-version: '20'
|
|
191
|
+
cache: 'npm'
|
|
192
|
+
- run: npm ci
|
|
193
|
+
- name: Validate contract schema
|
|
194
|
+
run: npx agentfile validate
|
|
195
|
+
- name: Dry-run generation
|
|
196
|
+
run: npx agentfile sync --dry-run
|
|
197
|
+
`;
|
|
198
|
+
// ─── File Writer ───────────────────────────────────────────────────────────
|
|
199
|
+
function writeIfMissing(path, content, label) {
|
|
200
|
+
if (existsSync(path)) {
|
|
201
|
+
logger.warn(`${label} already exists — skipped`);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
writeFileSync(path, content, 'utf-8');
|
|
205
|
+
logger.success(`Created ${label}`);
|
|
206
|
+
}
|
|
207
|
+
// ─── Init Command ──────────────────────────────────────────────────────────
|
|
208
|
+
export async function initCommand() {
|
|
209
|
+
logger.title('agentfile init');
|
|
210
|
+
// Dynamic import — enquirer is CJS-compat but we import at runtime only
|
|
211
|
+
const { default: Enquirer } = await import('enquirer');
|
|
212
|
+
const enquirer = new Enquirer();
|
|
213
|
+
const answers = await enquirer.prompt([
|
|
214
|
+
{
|
|
215
|
+
type: 'input',
|
|
216
|
+
name: 'name',
|
|
217
|
+
message: 'Project name?',
|
|
218
|
+
initial: 'My Project'
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
type: 'list',
|
|
222
|
+
name: 'stack',
|
|
223
|
+
message: 'Tech stack? (comma-separated)',
|
|
224
|
+
initial: 'typescript, node'
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
type: 'multiselect',
|
|
228
|
+
name: 'agents',
|
|
229
|
+
message: 'Which agents does your team use?',
|
|
230
|
+
choices: ['claude', 'copilot', 'cursor', 'agents-md']
|
|
231
|
+
}
|
|
232
|
+
]);
|
|
233
|
+
const root = process.cwd();
|
|
234
|
+
console.log();
|
|
235
|
+
// ai/ directory and contract
|
|
236
|
+
mkdirSync(join(root, 'ai', 'agents', 'claude'), { recursive: true });
|
|
237
|
+
mkdirSync(join(root, 'ai', 'agents', 'copilot'), { recursive: true });
|
|
238
|
+
mkdirSync(join(root, 'ai', 'agents', 'cursor'), { recursive: true });
|
|
239
|
+
mkdirSync(join(root, 'ai', 'agents', 'agents-md'), { recursive: true });
|
|
240
|
+
mkdirSync(join(root, '.github', 'workflows'), { recursive: true });
|
|
241
|
+
writeIfMissing(join(root, 'ai', 'contract.yaml'), contractYaml(answers.name, answers.stack), 'ai/contract.yaml');
|
|
242
|
+
// Agent configs
|
|
243
|
+
const agentConfigs = {
|
|
244
|
+
claude: { name: 'Claude', output: 'CLAUDE.md', description: 'Anthropic Claude instruction file' },
|
|
245
|
+
copilot: { name: 'GitHub Copilot', output: '.github/copilot-instructions.md', description: 'GitHub Copilot workspace instruction file' },
|
|
246
|
+
cursor: { name: 'Cursor', output: '.cursor/rules/main.mdc', description: 'Cursor AI rules file' },
|
|
247
|
+
'agents-md': { name: 'AGENTS.md', output: 'AGENTS.md', description: 'Universal agent instruction file' }
|
|
248
|
+
};
|
|
249
|
+
const templates = {
|
|
250
|
+
claude: claudeTemplate,
|
|
251
|
+
copilot: copilotTemplate,
|
|
252
|
+
cursor: cursorTemplate,
|
|
253
|
+
'agents-md': agentsMdTemplate
|
|
254
|
+
};
|
|
255
|
+
for (const [agent, config] of Object.entries(agentConfigs)) {
|
|
256
|
+
const dir = join(root, 'ai', 'agents', agent);
|
|
257
|
+
const configYaml = `name: ${config.name}\noutput: ${config.output}\ndescription: ${config.description}\n`;
|
|
258
|
+
writeIfMissing(join(dir, 'config.yaml'), configYaml, `ai/agents/${agent}/config.yaml`);
|
|
259
|
+
writeIfMissing(join(dir, 'template.md'), templates[agent], `ai/agents/${agent}/template.md`);
|
|
260
|
+
}
|
|
261
|
+
// .ai-agents.example
|
|
262
|
+
writeIfMissing(join(root, '.ai-agents.example'), agentsExample, '.ai-agents.example');
|
|
263
|
+
// .ai-agents for this developer
|
|
264
|
+
if (answers.agents.length) {
|
|
265
|
+
writeIfMissing(join(root, '.ai-agents'), answers.agents.join('\n') + '\n', '.ai-agents (your personal agent selection)');
|
|
266
|
+
}
|
|
267
|
+
// CI workflow
|
|
268
|
+
writeIfMissing(join(root, '.github', 'workflows', 'ai-contract.yml'), ciWorkflow, '.github/workflows/ai-contract.yml');
|
|
269
|
+
// .gitignore hint
|
|
270
|
+
console.log();
|
|
271
|
+
logger.info('Add the following to your .gitignore:');
|
|
272
|
+
console.log(gitignoreAdditions);
|
|
273
|
+
logger.success('Done! Run `npx agentfile sync` to generate your agent files.\n');
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA0BA,wBAAsB,WAAW,CAAC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,iBAsDnE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { generate } from '@agentfile/core';
|
|
5
|
+
import { logger } from '../logger.js';
|
|
6
|
+
const AI_AGENTS_FILE = '.ai-agents';
|
|
7
|
+
const AI_AGENTS_EXAMPLE = '.ai-agents.example';
|
|
8
|
+
function readAgents(root) {
|
|
9
|
+
const agentsPath = join(root, AI_AGENTS_FILE);
|
|
10
|
+
if (!existsSync(agentsPath)) {
|
|
11
|
+
logger.warn(`No ${AI_AGENTS_FILE} file found.`);
|
|
12
|
+
if (existsSync(join(root, AI_AGENTS_EXAMPLE))) {
|
|
13
|
+
logger.info(`Copy ${AI_AGENTS_EXAMPLE} to ${AI_AGENTS_FILE} and list the agents you use.`);
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return readFileSync(agentsPath, 'utf-8')
|
|
18
|
+
.split('\n')
|
|
19
|
+
.map(l => l.trim())
|
|
20
|
+
.filter(l => l && !l.startsWith('#'));
|
|
21
|
+
}
|
|
22
|
+
export async function syncCommand(options = {}) {
|
|
23
|
+
const root = process.cwd();
|
|
24
|
+
const dryRun = options.dryRun ?? false;
|
|
25
|
+
logger.title(dryRun ? 'agentfile — dry run' : 'agentfile sync');
|
|
26
|
+
// Read agent selection
|
|
27
|
+
const agents = readAgents(root);
|
|
28
|
+
if (!agents) {
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
if (!agents.length) {
|
|
32
|
+
logger.error(`${AI_AGENTS_FILE} is empty. Add at least one agent name.`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
logger.info(`Agents: ${agents.join(', ')}\n`);
|
|
36
|
+
// Run generation
|
|
37
|
+
let result;
|
|
38
|
+
try {
|
|
39
|
+
result = generate({ root, agents, dryRun });
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger.error(err.message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
// Report results
|
|
46
|
+
for (const r of result.results) {
|
|
47
|
+
if (r.status === 'ok') {
|
|
48
|
+
const label = dryRun ? `(dry-run) ${r.agent}` : r.agent;
|
|
49
|
+
logger.success(`${label} → ${r.output}`);
|
|
50
|
+
}
|
|
51
|
+
else if (r.status === 'skipped') {
|
|
52
|
+
logger.warn(`${r.agent} skipped — ${r.reason}`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
logger.error(`${r.agent} — ${r.error.message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
console.log();
|
|
59
|
+
if (!result.success) {
|
|
60
|
+
logger.error('Sync failed. See errors above.');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
logger.success(dryRun
|
|
64
|
+
? 'Dry run passed. All templates render without errors.'
|
|
65
|
+
: 'All agent files generated successfully.');
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,kBAsBpC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { validateContract } from '@agentfile/core';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
export async function validateCommand() {
|
|
6
|
+
const root = process.cwd();
|
|
7
|
+
const contractPath = join(root, 'ai', 'contract.yaml');
|
|
8
|
+
logger.title('agentfile validate');
|
|
9
|
+
try {
|
|
10
|
+
const contract = validateContract({ contractPath });
|
|
11
|
+
logger.success(`contract.yaml is valid (version ${contract.version})`);
|
|
12
|
+
logger.success(`Project: ${contract.project.name}`);
|
|
13
|
+
logger.success(`Stack: ${contract.project.stack.join(', ')}`);
|
|
14
|
+
const ruleCount = Object.values(contract.rules)
|
|
15
|
+
.reduce((sum, rules) => sum + rules.length, 0);
|
|
16
|
+
logger.success(`Rules: ${ruleCount} total across ${Object.keys(contract.rules).length} categories`);
|
|
17
|
+
console.log();
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
logger.error(err.message);
|
|
21
|
+
console.log();
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,IAAI,GAAW,OAAO,CAAC,GAAG,EAAE,CAAA;IAClC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,CAAA;IAEtD,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;IAElC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;QACnD,MAAM,CAAC,OAAO,CAAC,mCAAmC,QAAQ,CAAC,OAAO,GAAG,CAAC,CAAA;QACtE,MAAM,CAAC,OAAO,CAAC,YAAY,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QACnD,MAAM,CAAC,OAAO,CAAC,YAAY,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAE/D,MAAM,SAAS,GAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAgB;aAC5D,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAEhD,MAAM,CAAC,OAAO,CAAC,YAAY,SAAS,iBAAiB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,aAAa,CAAC,CAAA;QACrG,OAAO,CAAC,GAAG,EAAE,CAAA;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAA;QACpC,OAAO,CAAC,GAAG,EAAE,CAAA;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM;gBACF,MAAM;mBACN,MAAM;gBACN,MAAM;iBACN,MAAM;iBACN,MAAM;;CAEtB,CAAA"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
export const logger = {
|
|
4
|
+
info: (msg) => console.log(` ${msg}`),
|
|
5
|
+
success: (msg) => console.log(`${chalk.green('✔')} ${msg}`),
|
|
6
|
+
warn: (msg) => console.log(`${chalk.yellow('⚠')} ${msg}`),
|
|
7
|
+
error: (msg) => console.log(`${chalk.red('✘')} ${msg}`),
|
|
8
|
+
title: (msg) => console.log(`\n${chalk.bold.cyan(msg)}\n`),
|
|
9
|
+
divider: () => console.log(chalk.gray('─'.repeat(40)))
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAK,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;IACjD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACnE,IAAI,EAAK,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACpE,KAAK,EAAI,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACjE,KAAK,EAAI,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACpE,OAAO,EAAE,GAAc,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;CAClE,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentfile/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for agentfile — init, sync, and validate AI agent contracts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentfile": "./dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"files": ["dist"],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"dev": "tsx src/bin.ts"
|
|
15
|
+
},
|
|
16
|
+
"keywords": ["ai", "agents", "cli", "rules", "claude", "copilot", "cursor", "agentfile"],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/dennishavermans/agentfile"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/dennishavermans/agentfile#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/dennishavermans/agentfile/issues"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@types/node": "^20.0.0",
|
|
34
|
+
"@agentfile/core": "^0.1.0",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"commander": "^12.0.0",
|
|
37
|
+
"enquirer": "^2.4.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"tsx": "^4.7.0",
|
|
41
|
+
"typescript": "^5.3.0",
|
|
42
|
+
"vitest": "^4.1.0"
|
|
43
|
+
}
|
|
44
|
+
}
|