thomas-agentkit 0.7.0 → 0.9.0-alpha.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 +96 -3
- package/dist/cli.js +124 -21
- package/dist/skill-install.js +125 -0
- package/package.json +3 -1
- package/templates/.cursor/rules/agentkit.md +11 -10
- package/templates/.github/copilot-instructions.md +1 -9
- package/templates/AGENTS.md +67 -32
- package/templates/CHANGE-EXPLANATION.md +20 -4
- package/templates/CLAUDE.md +2 -12
- package/templates/CODE-QUALITY.md +5 -15
- package/templates/IMPLEMENTATION-BRIEF-TEMPLATE.md +2 -0
- package/templates/PRD-TEMPLATE.md +2 -0
- package/templates/SECURITY-CHECKLIST.md +2 -2
- package/templates/TESTING.md +1 -1
- package/templates/WORKFLOWS.md +13 -86
- package/templates/skills/agentkit/SKILL.md +94 -0
- package/templates/skills/agentkit/agents/openai.yaml +4 -0
- package/templates/skills/agentkit/references/doctor.md +133 -0
- package/templates/skills/agentkit/references/file-contract.md +163 -0
- package/templates/skills/agentkit/references/init.md +212 -0
- package/templates/skills/agentkit/references/learn.md +149 -0
- package/templates/skills/agentkit/references/repair.md +119 -0
- package/templates/skills/agentkit/references/update.md +201 -0
package/README.md
CHANGED
|
@@ -6,14 +6,81 @@ It installs reusable agent instructions, workflow guides, quality checklists, de
|
|
|
6
6
|
|
|
7
7
|
AgentKit is not an AI agent. It is a small scaffolding tool for making repositories easier and safer to work on with AI-assisted development.
|
|
8
8
|
|
|
9
|
+
## Bootstrap paths
|
|
10
|
+
|
|
11
|
+
AgentKit supports two first-time setup paths. Pick one — they are not interchangeable.
|
|
12
|
+
|
|
13
|
+
| | Template path | Skill path |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| **CLI command** | `agentkit init` | `agentkit skill install` |
|
|
16
|
+
| **When to use** | Immediate offline setup; you want files now | Agent-guided setup; guidance created from your repo in a later session |
|
|
17
|
+
| **What you get** | Bundled `.md` templates copied into the project | Bundled `agentkit` Agent Skill installed; no guidance `.md` files yet |
|
|
18
|
+
| **Ongoing maintenance** | CLI `agentkit update` (managed-block merge) | Skill routes in your agent: `/agentkit update`, `/agentkit doctor`, `/agentkit repair`, `/agentkit learn` |
|
|
19
|
+
| **Config** | `installMode: template` | `installMode: skill` |
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
FIRST-TIME SETUP (terminal)
|
|
23
|
+
├── agentkit init → copies templates, installMode: template
|
|
24
|
+
└── agentkit skill install → copies skill to .agents/skills/agentkit/, installMode: skill
|
|
25
|
+
|
|
26
|
+
ONGOING WORK (agent + skill path only)
|
|
27
|
+
├── /agentkit init → agent creates AGENTS.md and companion files from repo context
|
|
28
|
+
├── /agentkit update → agent syncs guidance after code changes
|
|
29
|
+
├── /agentkit doctor → agent audits guidance quality
|
|
30
|
+
├── /agentkit repair → agent repairs guidance structure when explicitly requested
|
|
31
|
+
└── /agentkit learn → agent teaches what changed after implementation
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Interactive `agentkit init` asks whether to copy templates or install the AgentKit skill, then runs the chosen path in the same session.
|
|
35
|
+
|
|
9
36
|
## Usage
|
|
10
37
|
|
|
38
|
+
### Template path
|
|
39
|
+
|
|
11
40
|
Install templates into the current directory:
|
|
12
41
|
|
|
13
42
|
```bash
|
|
14
43
|
npx thomas-agentkit init
|
|
15
44
|
```
|
|
16
45
|
|
|
46
|
+
### Skill path
|
|
47
|
+
|
|
48
|
+
Install the bundled AgentKit skill (v0.9.x+). This does **not** create `AGENTS.md` or other guidance files — run `/agentkit init` in your agent afterward:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx thomas-agentkit skill install
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Preview skill install without writing files:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx thomas-agentkit skill install --dry-run
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Overwrite an existing skill install:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx thomas-agentkit skill install --force
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
After install, the CLI prints:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
Installed AgentKit skill in .agents/skills/agentkit/
|
|
70
|
+
Wrote agentkit.config.json (installMode: skill)
|
|
71
|
+
|
|
72
|
+
Next step: In your agent, run agentkit init.
|
|
73
|
+
The skill will create AGENTS.md and companion files from your repository.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
After skill install, use the project-local skill from your agent:
|
|
77
|
+
|
|
78
|
+
- `/agentkit init` creates missing guidance files from repository context.
|
|
79
|
+
- `/agentkit update` syncs managed guidance with current repository context.
|
|
80
|
+
- `/agentkit doctor` audits guidance quality without editing by default.
|
|
81
|
+
- `/agentkit repair` repairs guidance structure, such as malformed managed blocks or thick AI adapters, after an explicit request.
|
|
82
|
+
- `/agentkit learn` teaches recent codebase changes, design decisions, edge cases, validation, and impact without writing files by default.
|
|
83
|
+
|
|
17
84
|
If the package is installed in a project, use the local `agentkit` binary:
|
|
18
85
|
|
|
19
86
|
```bash
|
|
@@ -77,6 +144,8 @@ Standardize install defaults with `agentkit.config.json`:
|
|
|
77
144
|
|
|
78
145
|
```json
|
|
79
146
|
{
|
|
147
|
+
"installMode": "template",
|
|
148
|
+
"agentkitVersion": "0.9.0",
|
|
80
149
|
"preset": "next",
|
|
81
150
|
"templateSet": "standard",
|
|
82
151
|
"designSystem": "linear",
|
|
@@ -105,7 +174,9 @@ npx thomas-agentkit init --write-config
|
|
|
105
174
|
|
|
106
175
|
`--write-config` writes `agentkit.config.json` in the target directory. Existing config files are skipped by default; use `--force` to overwrite one intentionally.
|
|
107
176
|
|
|
108
|
-
|
|
177
|
+
`installMode` is `"template"` or `"skill"` and records how the project was bootstrapped. `agentkitVersion` records the package version at install time. Configs without `installMode` are treated as template-path installs.
|
|
178
|
+
|
|
179
|
+
Config values are validated when loaded. Unknown config keys, invalid preset/template/design-system names, invalid AI tool names, invalid `installMode` values, and non-string personalization values exit with an error.
|
|
109
180
|
|
|
110
181
|
List bundled templates:
|
|
111
182
|
|
|
@@ -166,7 +237,7 @@ Interactive personalization only applies during `agentkit init` when files are c
|
|
|
166
237
|
Template set mappings:
|
|
167
238
|
|
|
168
239
|
- `minimal`: `AGENTS.md`
|
|
169
|
-
- `standard`: `AGENTS.md`, `CHANGE-EXPLANATION.md`, `CODE-QUALITY.md`, `DESIGN-SYSTEM.md`,
|
|
240
|
+
- `standard`: `AGENTS.md`, `CHANGE-EXPLANATION.md`, `CODE-QUALITY.md`, `DESIGN-SYSTEM.md`, `.github/pull_request_template.md`
|
|
170
241
|
- `full`: all bundled templates, including AI tool adapters and planning/testing/security guides
|
|
171
242
|
|
|
172
243
|
AI tool mappings:
|
|
@@ -188,10 +259,30 @@ Presets add stack-specific guidance without scaffolding framework app files.
|
|
|
188
259
|
- `convex`
|
|
189
260
|
- `fullstack` (`Next.js` + `Convex`)
|
|
190
261
|
|
|
262
|
+
## CLI vs agent commands
|
|
263
|
+
|
|
264
|
+
The same names mean different things in the terminal vs in an agent session:
|
|
265
|
+
|
|
266
|
+
| Name | Where | What |
|
|
267
|
+
| --- | --- | --- |
|
|
268
|
+
| `agentkit init` | Terminal | Install **templates** |
|
|
269
|
+
| `agentkit skill install` | Terminal | Install **bundled skill** + config |
|
|
270
|
+
| `agentkit init` | Agent | Create **guidance files** (skill path) |
|
|
271
|
+
| `agentkit update` | Terminal | Template-path managed-block merge only |
|
|
272
|
+
| `agentkit update` | Agent | Sync guidance to repo changes |
|
|
273
|
+
| `agentkit doctor` | Agent | Audit guidance quality |
|
|
274
|
+
| `agentkit repair` | Agent | Repair guidance structure after explicit request |
|
|
275
|
+
| `agentkit learn` | Agent | Teach recent codebase changes and check understanding |
|
|
276
|
+
|
|
277
|
+
Never use CLI `agentkit init` for skill installation.
|
|
278
|
+
|
|
279
|
+
On skill-path repos (`installMode: skill`), CLI `agentkit update` prints an informational message and does not modify guidance files. Use `/agentkit update` in your agent for skill-path guidance sync.
|
|
280
|
+
|
|
191
281
|
## CLI Reference
|
|
192
282
|
|
|
193
283
|
```text
|
|
194
284
|
agentkit init [target] [--force] [--dry-run] [--interactive] [--yes] [--write-config] [--preset <name>] [--design-system <name>]
|
|
285
|
+
agentkit skill install [target] [--force] [--dry-run] [--yes] [--preset <name>] [--design-system <name>]
|
|
195
286
|
agentkit update [target] [--dry-run] [--preset <name>] [--design-system <name>]
|
|
196
287
|
agentkit --list
|
|
197
288
|
agentkit --list-presets
|
|
@@ -206,7 +297,7 @@ Options:
|
|
|
206
297
|
- `--dry-run`: print planned changes without writing files
|
|
207
298
|
- `-i, --interactive`: explicitly prompt for install options
|
|
208
299
|
- `-y, --yes`: accept defaults without prompts
|
|
209
|
-
- `--write-config`: write resolved install defaults to `agentkit.config.json`
|
|
300
|
+
- `--write-config`: write resolved template install defaults to `agentkit.config.json`
|
|
210
301
|
- `--preset <name>`: install stack-specific guidance (`next`, `sveltekit`, `express`, `convex`, `fullstack`)
|
|
211
302
|
- `--design-system <name>`: design system variant for `DESIGN-SYSTEM.md` (`linear`, `apple`)
|
|
212
303
|
- `--list`: list bundled template files
|
|
@@ -268,3 +359,5 @@ AgentKit should stay:
|
|
|
268
359
|
- safe by default
|
|
269
360
|
- useful immediately
|
|
270
361
|
- not overengineered
|
|
362
|
+
|
|
363
|
+
Installed guidance is **AGENTS-first**: `AGENTS.md` is enough for daily coding, including required change explanations after file edits. Companion files are loaded on explicit triggers (UI, review, security, stack, planning when requested), not on every task. The `full` template set adds optional guides such as `WORKFLOWS.md`, `TESTING.md`, and planning templates.
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import { constants as fsConstants, realpathSync } from "node:fs";
|
|
|
5
5
|
import { access, mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { getSkillDestinationPaths, getSkillSourceDir, installSkill, listSkillFiles, printSkillInstallResult, } from "./skill-install.js";
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = path.dirname(__filename);
|
|
10
11
|
const packageRoot = path.resolve(__dirname, "..");
|
|
@@ -20,7 +21,16 @@ const designSystemLabels = {
|
|
|
20
21
|
apple: "Apple-inspired",
|
|
21
22
|
};
|
|
22
23
|
const configFileName = "agentkit.config.json";
|
|
23
|
-
const configKeys = [
|
|
24
|
+
const configKeys = [
|
|
25
|
+
"installMode",
|
|
26
|
+
"agentkitVersion",
|
|
27
|
+
"preset",
|
|
28
|
+
"templateSet",
|
|
29
|
+
"aiTools",
|
|
30
|
+
"designSystem",
|
|
31
|
+
"personalization",
|
|
32
|
+
];
|
|
33
|
+
const validInstallModes = ["template", "skill"];
|
|
24
34
|
const personalizationKeys = [
|
|
25
35
|
"projectName",
|
|
26
36
|
"projectDescription",
|
|
@@ -52,7 +62,6 @@ const templateSetFiles = {
|
|
|
52
62
|
"CHANGE-EXPLANATION.md",
|
|
53
63
|
"CODE-QUALITY.md",
|
|
54
64
|
"DESIGN-SYSTEM.md",
|
|
55
|
-
"WORKFLOWS.md",
|
|
56
65
|
".github/pull_request_template.md",
|
|
57
66
|
],
|
|
58
67
|
full: [],
|
|
@@ -129,7 +138,7 @@ async function collectInstallableTemplatePaths(dir, base) {
|
|
|
129
138
|
for (const entry of entries) {
|
|
130
139
|
const absolutePath = path.join(dir, entry.name);
|
|
131
140
|
if (entry.isDirectory()) {
|
|
132
|
-
if (dir === templatesDir && entry.name === "design-systems") {
|
|
141
|
+
if (dir === templatesDir && (entry.name === "design-systems" || entry.name === "skills")) {
|
|
133
142
|
continue;
|
|
134
143
|
}
|
|
135
144
|
discovered.push(...(await collectInstallableTemplatePaths(absolutePath, base)));
|
|
@@ -258,13 +267,31 @@ function readConfigPersonalization(value) {
|
|
|
258
267
|
}
|
|
259
268
|
return personalization;
|
|
260
269
|
}
|
|
270
|
+
function resolveInstallMode(installMode) {
|
|
271
|
+
const normalizedInstallMode = installMode.toLowerCase();
|
|
272
|
+
if (!validInstallModes.includes(normalizedInstallMode)) {
|
|
273
|
+
throw new Error(`Unknown install mode "${installMode}". Valid install modes: ${validInstallModes.join(", ")}.`);
|
|
274
|
+
}
|
|
275
|
+
return normalizedInstallMode;
|
|
276
|
+
}
|
|
277
|
+
export function getInstallMode(config) {
|
|
278
|
+
return config?.installMode ?? "template";
|
|
279
|
+
}
|
|
261
280
|
function parseConfig(rawConfig, configPath) {
|
|
262
281
|
assertPlainObject(rawConfig, configFileName);
|
|
263
282
|
assertKnownKeys(rawConfig, configKeys, configFileName);
|
|
264
283
|
const preset = optionalConfigString(rawConfig, "preset");
|
|
265
284
|
const templateSet = optionalConfigString(rawConfig, "templateSet");
|
|
266
285
|
const designSystem = optionalConfigString(rawConfig, "designSystem");
|
|
286
|
+
const installMode = optionalConfigString(rawConfig, "installMode");
|
|
287
|
+
const agentkitVersion = optionalConfigString(rawConfig, "agentkitVersion");
|
|
267
288
|
const config = {};
|
|
289
|
+
if (installMode !== undefined) {
|
|
290
|
+
config.installMode = resolveInstallMode(installMode);
|
|
291
|
+
}
|
|
292
|
+
if (agentkitVersion !== undefined) {
|
|
293
|
+
config.agentkitVersion = agentkitVersion;
|
|
294
|
+
}
|
|
268
295
|
if (preset !== undefined) {
|
|
269
296
|
config.preset = resolvePreset(preset);
|
|
270
297
|
}
|
|
@@ -395,8 +422,10 @@ function cleanPersonalizationValue(value) {
|
|
|
395
422
|
const trimmed = value?.trim();
|
|
396
423
|
return trimmed ? trimmed : undefined;
|
|
397
424
|
}
|
|
398
|
-
function getResolvedConfig(options) {
|
|
425
|
+
function getResolvedConfig(options, installMode, agentkitVersion) {
|
|
399
426
|
const config = {
|
|
427
|
+
installMode,
|
|
428
|
+
agentkitVersion,
|
|
400
429
|
templateSet: options.templateSet ?? "standard",
|
|
401
430
|
aiTools: options.aiTools ?? [],
|
|
402
431
|
designSystem: effectiveDesignSystem(options.designSystem),
|
|
@@ -574,7 +603,7 @@ async function resolveInitTemplateFiles(options) {
|
|
|
574
603
|
}
|
|
575
604
|
return getSelectedTemplateFiles(options.templateSet ?? "standard", options.aiTools ?? [], allTemplateFiles);
|
|
576
605
|
}
|
|
577
|
-
async function installTemplates(targetArg, options) {
|
|
606
|
+
async function installTemplates(targetArg, options, agentkitVersion) {
|
|
578
607
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
579
608
|
const files = await resolveInitTemplateFiles(options);
|
|
580
609
|
const preset = resolvePreset(options.preset);
|
|
@@ -584,7 +613,7 @@ async function installTemplates(targetArg, options) {
|
|
|
584
613
|
await mkdir(targetDir, { recursive: true });
|
|
585
614
|
}
|
|
586
615
|
if (options.writeConfig) {
|
|
587
|
-
await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options)));
|
|
616
|
+
await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options, "template", agentkitVersion)));
|
|
588
617
|
}
|
|
589
618
|
for (const file of files) {
|
|
590
619
|
await installFileIfAllowed(targetDir, file, options, result, async () => {
|
|
@@ -791,7 +820,23 @@ async function promptForConflictStrategy(existingFiles) {
|
|
|
791
820
|
],
|
|
792
821
|
}));
|
|
793
822
|
}
|
|
794
|
-
async function
|
|
823
|
+
async function promptForBootstrapPath() {
|
|
824
|
+
return resolvePrompt(await select({
|
|
825
|
+
message: "How do you want to set up AgentKit?",
|
|
826
|
+
initialValue: "template",
|
|
827
|
+
options: [
|
|
828
|
+
{
|
|
829
|
+
label: "Copy templates now (install AGENTS.md and companion files)",
|
|
830
|
+
value: "template",
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
label: "Install AgentKit skill (create guidance files later in your agent)",
|
|
834
|
+
value: "skill",
|
|
835
|
+
},
|
|
836
|
+
],
|
|
837
|
+
}));
|
|
838
|
+
}
|
|
839
|
+
async function collectInstallOptions(resolvedTarget, providedPreset, options) {
|
|
795
840
|
if (!providedPreset) {
|
|
796
841
|
options.preset = await promptForProjectPreset();
|
|
797
842
|
}
|
|
@@ -804,25 +849,50 @@ async function applyInteractiveSelections(resolvedTarget, providedPreset, option
|
|
|
804
849
|
if (templateSet === "standard" || templateSet === "full") {
|
|
805
850
|
options.designSystem = await promptForDesignSystem(options.designSystem);
|
|
806
851
|
}
|
|
807
|
-
|
|
852
|
+
}
|
|
853
|
+
async function resolveConflictForInstall(resolvedTarget, options, bootstrapPath) {
|
|
854
|
+
if (options.force) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
let installFiles;
|
|
858
|
+
if (bootstrapPath === "skill") {
|
|
859
|
+
const skillFiles = await listSkillFiles(getSkillSourceDir(packageRoot));
|
|
860
|
+
installFiles = [...getSkillDestinationPaths(skillFiles), configFileName];
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
808
863
|
const preset = resolvePreset(options.preset);
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
864
|
+
installFiles = preset ? [...(options.files ?? []), "STACK.md"] : (options.files ?? []);
|
|
865
|
+
}
|
|
866
|
+
const existingFiles = await findExistingInstallFiles(resolvedTarget, installFiles);
|
|
867
|
+
if (existingFiles.length > 0) {
|
|
868
|
+
options.force = (await promptForConflictStrategy(existingFiles)) === "overwrite";
|
|
814
869
|
}
|
|
815
870
|
}
|
|
816
|
-
async function
|
|
871
|
+
async function runInteractiveInstall(target, options, agentkitVersion) {
|
|
872
|
+
intro("Welcome to AgentKit");
|
|
873
|
+
const bootstrapPath = await promptForBootstrapPath();
|
|
817
874
|
const providedPreset = resolvePreset(options.preset);
|
|
818
|
-
|
|
819
|
-
|
|
875
|
+
const resolvedTarget = await promptForTarget(target);
|
|
876
|
+
await collectInstallOptions(resolvedTarget, providedPreset, options);
|
|
877
|
+
options.personalization = await promptForPersonalization(options.personalization);
|
|
878
|
+
await resolveConflictForInstall(resolvedTarget, options, bootstrapPath);
|
|
879
|
+
if (bootstrapPath === "skill") {
|
|
880
|
+
const result = await installSkill(resolvedTarget, options, packageRoot, agentkitVersion);
|
|
881
|
+
printSkillInstallResult(result, Boolean(options.dryRun));
|
|
882
|
+
return;
|
|
820
883
|
}
|
|
884
|
+
const result = await installTemplates(resolvedTarget, options, agentkitVersion);
|
|
885
|
+
printInstallResult(result, Boolean(options.dryRun));
|
|
886
|
+
}
|
|
887
|
+
async function runSkillInstallInteractive(target, options, agentkitVersion) {
|
|
821
888
|
intro("Welcome to AgentKit");
|
|
889
|
+
const providedPreset = resolvePreset(options.preset);
|
|
822
890
|
const resolvedTarget = await promptForTarget(target);
|
|
823
|
-
await
|
|
891
|
+
await collectInstallOptions(resolvedTarget, providedPreset, options);
|
|
824
892
|
options.personalization = await promptForPersonalization(options.personalization);
|
|
825
|
-
|
|
893
|
+
await resolveConflictForInstall(resolvedTarget, options, "skill");
|
|
894
|
+
const result = await installSkill(resolvedTarget, options, packageRoot, agentkitVersion);
|
|
895
|
+
printSkillInstallResult(result, Boolean(options.dryRun));
|
|
826
896
|
}
|
|
827
897
|
async function main() {
|
|
828
898
|
if (process.argv.slice(2).includes("--list")) {
|
|
@@ -856,6 +926,7 @@ async function main() {
|
|
|
856
926
|
|
|
857
927
|
Examples:
|
|
858
928
|
agentkit init
|
|
929
|
+
agentkit skill install
|
|
859
930
|
agentkit update
|
|
860
931
|
agentkit init --preset next
|
|
861
932
|
agentkit init ./my-project --yes --dry-run
|
|
@@ -875,10 +946,35 @@ Examples:
|
|
|
875
946
|
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
876
947
|
.action(async (target, options) => {
|
|
877
948
|
await applyInitConfig(options, await loadConfigForTarget(target));
|
|
878
|
-
const
|
|
879
|
-
|
|
949
|
+
const agentkitVersion = await readPackageVersion();
|
|
950
|
+
if (shouldPromptForInit(options, process)) {
|
|
951
|
+
await runInteractiveInstall(target, options, agentkitVersion);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const result = await installTemplates(target, options, agentkitVersion);
|
|
880
955
|
printInstallResult(result, Boolean(options.dryRun));
|
|
881
956
|
});
|
|
957
|
+
const skill = program.command("skill").description("install the bundled AgentKit Agent Skill");
|
|
958
|
+
skill
|
|
959
|
+
.command("install")
|
|
960
|
+
.description("install the bundled agentkit skill and write agentkit.config.json")
|
|
961
|
+
.argument("[target]", "target project directory", ".")
|
|
962
|
+
.option("--force", "overwrite existing skill files and config")
|
|
963
|
+
.option("--dry-run", "print planned changes without writing files")
|
|
964
|
+
.option("-i, --interactive", "prompt for install options")
|
|
965
|
+
.option("-y, --yes", "accept defaults for non-interactive runs")
|
|
966
|
+
.option("--preset <name>", `store stack preset in config (${formatPresetList()})`)
|
|
967
|
+
.option("--design-system <name>", `store design system choice in config (${formatDesignSystemList()})`)
|
|
968
|
+
.action(async (target, options) => {
|
|
969
|
+
await applyInitConfig(options, await loadConfigForTarget(target));
|
|
970
|
+
const agentkitVersion = await readPackageVersion();
|
|
971
|
+
if (shouldPromptForInit(options, process)) {
|
|
972
|
+
await runSkillInstallInteractive(target, options, agentkitVersion);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const result = await installSkill(target, options, packageRoot, agentkitVersion);
|
|
976
|
+
printSkillInstallResult(result, Boolean(options.dryRun));
|
|
977
|
+
});
|
|
882
978
|
program
|
|
883
979
|
.command("update")
|
|
884
980
|
.description("update AgentKit managed template blocks in a project")
|
|
@@ -887,7 +983,14 @@ Examples:
|
|
|
887
983
|
.option("--preset <name>", `update stack-specific guidance (${formatPresetList()})`)
|
|
888
984
|
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
889
985
|
.action(async (target, options) => {
|
|
890
|
-
|
|
986
|
+
const config = await loadConfigForTarget(target);
|
|
987
|
+
if (getInstallMode(config) === "skill") {
|
|
988
|
+
console.log("This project uses installMode: skill.");
|
|
989
|
+
console.log("Run agentkit update in your agent to sync guidance files.");
|
|
990
|
+
console.log("(CLI agentkit update applies to template-path installs.)");
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
applyUpdateConfig(options, config);
|
|
891
994
|
const result = await updateTemplates(target, options);
|
|
892
995
|
printUpdateResult(result, Boolean(options.dryRun));
|
|
893
996
|
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { constants as fsConstants } from "node:fs";
|
|
2
|
+
import { access, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export const SKILL_DEST_DIR = ".agents/skills/agentkit";
|
|
5
|
+
export const CONFIG_FILE_NAME = "agentkit.config.json";
|
|
6
|
+
export function getSkillSourceDir(packageRoot) {
|
|
7
|
+
return path.join(packageRoot, "templates", "skills", "agentkit");
|
|
8
|
+
}
|
|
9
|
+
export async function listSkillFiles(sourceDir) {
|
|
10
|
+
const files = [];
|
|
11
|
+
async function walk(dir, prefix) {
|
|
12
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
15
|
+
const fullPath = path.join(dir, entry.name);
|
|
16
|
+
if (entry.isDirectory()) {
|
|
17
|
+
await walk(fullPath, relative);
|
|
18
|
+
}
|
|
19
|
+
else if (entry.isFile()) {
|
|
20
|
+
files.push(relative);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
await walk(sourceDir, "");
|
|
25
|
+
return files.sort();
|
|
26
|
+
}
|
|
27
|
+
export function buildSkillConfig(options, agentkitVersion) {
|
|
28
|
+
const config = {
|
|
29
|
+
installMode: "skill",
|
|
30
|
+
agentkitVersion,
|
|
31
|
+
templateSet: options.templateSet ?? "standard",
|
|
32
|
+
aiTools: options.aiTools ?? [],
|
|
33
|
+
designSystem: options.designSystem ?? "linear",
|
|
34
|
+
};
|
|
35
|
+
if (options.preset) {
|
|
36
|
+
config.preset = options.preset;
|
|
37
|
+
}
|
|
38
|
+
if (options.personalization) {
|
|
39
|
+
const personalization = {};
|
|
40
|
+
for (const [key, value] of Object.entries(options.personalization)) {
|
|
41
|
+
const trimmed = value?.trim();
|
|
42
|
+
if (trimmed) {
|
|
43
|
+
personalization[key] = trimmed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (Object.keys(personalization).length > 0) {
|
|
47
|
+
config.personalization = personalization;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return config;
|
|
51
|
+
}
|
|
52
|
+
export function getSkillDestinationPaths(skillFiles) {
|
|
53
|
+
return skillFiles.map((file) => path.posix.join(SKILL_DEST_DIR, file.replace(/\\/g, "/")));
|
|
54
|
+
}
|
|
55
|
+
async function pathExists(filePath) {
|
|
56
|
+
try {
|
|
57
|
+
await access(filePath, fsConstants.F_OK);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function installSkill(targetArg, options, packageRoot, agentkitVersion) {
|
|
65
|
+
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
66
|
+
const sourceDir = getSkillSourceDir(packageRoot);
|
|
67
|
+
const skillFiles = await listSkillFiles(sourceDir);
|
|
68
|
+
const result = { targetDir, created: [], skipped: [] };
|
|
69
|
+
if (!options.dryRun) {
|
|
70
|
+
await mkdir(targetDir, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
for (const file of skillFiles) {
|
|
73
|
+
const destination = path.join(targetDir, SKILL_DEST_DIR, file);
|
|
74
|
+
const destinationRelative = path.posix.join(SKILL_DEST_DIR, file.replace(/\\/g, "/"));
|
|
75
|
+
if ((await pathExists(destination)) && !options.force) {
|
|
76
|
+
result.skipped.push(destinationRelative);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
result.created.push(destinationRelative);
|
|
80
|
+
if (!options.dryRun) {
|
|
81
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
82
|
+
const content = await readFile(path.join(sourceDir, file), "utf8");
|
|
83
|
+
await writeFile(destination, content);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const configPath = path.join(targetDir, CONFIG_FILE_NAME);
|
|
87
|
+
const configRelative = CONFIG_FILE_NAME;
|
|
88
|
+
if ((await pathExists(configPath)) && !options.force) {
|
|
89
|
+
if (!result.skipped.includes(configRelative)) {
|
|
90
|
+
result.skipped.push(configRelative);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (!result.created.includes(configRelative)) {
|
|
95
|
+
result.created.push(configRelative);
|
|
96
|
+
}
|
|
97
|
+
if (!options.dryRun) {
|
|
98
|
+
const configContent = `${JSON.stringify(buildSkillConfig(options, agentkitVersion), null, 2)}\n`;
|
|
99
|
+
await writeFile(configPath, configContent);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
export function printSkillInstallResult(result, dryRun = false) {
|
|
105
|
+
if (dryRun) {
|
|
106
|
+
console.log(`Would install AgentKit skill in ${SKILL_DEST_DIR}/`);
|
|
107
|
+
if (result.created.length > 0) {
|
|
108
|
+
console.log(`Would create: ${result.created.join(", ")}`);
|
|
109
|
+
}
|
|
110
|
+
if (result.skipped.length > 0) {
|
|
111
|
+
console.log(`Would skip existing: ${result.skipped.join(", ")}`);
|
|
112
|
+
console.log("Use --force to overwrite existing files.");
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
console.log(`Installed AgentKit skill in ${SKILL_DEST_DIR}/`);
|
|
117
|
+
console.log(`Wrote ${CONFIG_FILE_NAME} (installMode: skill)`);
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log("Next step: In your agent, run agentkit init.");
|
|
120
|
+
console.log("The skill will create AGENTS.md and companion files from your repository.");
|
|
121
|
+
if (result.skipped.length > 0) {
|
|
122
|
+
console.log(`Skipped existing: ${result.skipped.join(", ")}`);
|
|
123
|
+
console.log("Use --force to overwrite existing files.");
|
|
124
|
+
}
|
|
125
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thomas-agentkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-alpha.0",
|
|
4
4
|
"description": "Install AI-agent-ready development templates into a project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"build": "tsc",
|
|
34
34
|
"dev": "tsx src/cli.ts",
|
|
35
35
|
"test": "vitest run",
|
|
36
|
+
"validate:skill": "skills-ref validate ./templates/skills/agentkit",
|
|
36
37
|
"prepack": "npm run build"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"commander": "^12.1.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
44
|
+
"skills-ref": "^0.1.5",
|
|
43
45
|
"@types/node": "^22.10.2",
|
|
44
46
|
"tsx": "^4.19.2",
|
|
45
47
|
"typescript": "^5.7.2",
|
|
@@ -6,21 +6,22 @@ Use this rule as a repository guidance router for Cursor agents and composer wor
|
|
|
6
6
|
|
|
7
7
|
- Follow `AGENTS.md` first.
|
|
8
8
|
- Treat `AGENTS.md` as the source of truth for repository-wide agent behavior.
|
|
9
|
-
-
|
|
9
|
+
- Do not load companion files for routine coding unless a trigger in `AGENTS.md` applies or the user asks.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## When Relevant
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
- `
|
|
15
|
-
-
|
|
16
|
-
- `
|
|
17
|
-
-
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
13
|
+
- **File edits (final message):** change-explanation format in `AGENTS.md` and `CHANGE-EXPLANATION.md`.
|
|
14
|
+
- **UI / styling / layout:** `DESIGN-SYSTEM.md` or the project design-system path from `AGENTS.md`.
|
|
15
|
+
- **Review / refactor / dependencies:** `CODE-QUALITY.md`.
|
|
16
|
+
- **Tests / QA strategy:** `TESTING.md` if present.
|
|
17
|
+
- **Auth / secrets / PII:** `SECURITY-CHECKLIST.md` if present.
|
|
18
|
+
- **Stack-specific code:** `STACK.md` if present.
|
|
19
|
+
- **Planning docs requested:** create from `PRD-TEMPLATE.md` or `IMPLEMENTATION-BRIEF-TEMPLATE.md` under the project's briefs path.
|
|
20
|
+
- **Process map (optional):** `WORKFLOWS.md` if present.
|
|
20
21
|
|
|
21
22
|
## Cursor Behavior
|
|
22
23
|
|
|
23
24
|
- Prefer existing repository patterns over generic generated patterns.
|
|
24
25
|
- Keep changes scoped and reviewable.
|
|
25
26
|
- Do not change foundational architecture, schema, dependencies, or theme primitives without explicit approval.
|
|
26
|
-
-
|
|
27
|
+
- After modifying files, end every task with a change explanation per `AGENTS.md` (summary, what changed, verification, risks, review focus). Scale depth to the change; do not skip for small fixes.
|
|
@@ -2,15 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Follow `AGENTS.md` first. It is the primary source of truth for this repository's AI-agent guidance.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- `CODE-QUALITY.md`
|
|
8
|
-
- `WORKFLOWS.md`
|
|
9
|
-
- `CHANGE-EXPLANATION.md`
|
|
10
|
-
- `DESIGN-SYSTEM.md`
|
|
11
|
-
- `TESTING.md`
|
|
12
|
-
- `SECURITY-CHECKLIST.md`
|
|
13
|
-
- `STACK.md`
|
|
5
|
+
Do not load companion files for routine coding. Use `AGENTS.md` triggers: change explanation after file edits; `CODE-QUALITY.md` for review/refactors; design-system path or `DESIGN-SYSTEM.md` for UI; `TESTING.md`, `SECURITY-CHECKLIST.md`, or `STACK.md` when present and relevant; planning templates only when explicitly requested.
|
|
14
6
|
|
|
15
7
|
For files covered by additional GitHub instructions under `.github/instructions/`, apply those path-specific instructions together with this file.
|
|
16
8
|
|