thomas-agentkit 0.8.0 → 0.9.0-alpha.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.
Files changed (29) hide show
  1. package/README.md +101 -9
  2. package/dist/cli.js +145 -32
  3. package/dist/skill-install.js +125 -0
  4. package/package.json +3 -1
  5. package/templates/.cursor/rules/agentkit.md +1 -1
  6. package/templates/.github/copilot-instructions.md +1 -1
  7. package/templates/AGENTS.md +1 -1
  8. package/templates/WORKFLOWS.md +1 -1
  9. package/templates/design-systems/apple.md +74 -209
  10. package/templates/design-systems/cursor.md +95 -0
  11. package/templates/design-systems/framer.md +95 -0
  12. package/templates/design-systems/linear.md +95 -207
  13. package/templates/design-systems/notion.md +94 -0
  14. package/templates/design-systems/warp.md +89 -0
  15. package/templates/skills/agentkit/SKILL.md +101 -0
  16. package/templates/skills/agentkit/agents/openai.yaml +4 -0
  17. package/templates/skills/agentkit/references/design-baselines/apple.md +101 -0
  18. package/templates/skills/agentkit/references/design-baselines/cursor.md +95 -0
  19. package/templates/skills/agentkit/references/design-baselines/framer.md +95 -0
  20. package/templates/skills/agentkit/references/design-baselines/linear.md +117 -0
  21. package/templates/skills/agentkit/references/design-baselines/notion.md +94 -0
  22. package/templates/skills/agentkit/references/design-baselines/warp.md +89 -0
  23. package/templates/skills/agentkit/references/design.md +100 -0
  24. package/templates/skills/agentkit/references/doctor.md +133 -0
  25. package/templates/skills/agentkit/references/file-contract.md +164 -0
  26. package/templates/skills/agentkit/references/init.md +213 -0
  27. package/templates/skills/agentkit/references/learn.md +149 -0
  28. package/templates/skills/agentkit/references/repair.md +119 -0
  29. package/templates/skills/agentkit/references/update.md +202 -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
- Config values are validated when loaded. Unknown config keys, invalid preset/template/design-system names, invalid AI tool names, and non-string personalization values exit with an error.
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
 
@@ -119,7 +190,7 @@ List available presets:
119
190
  npx thomas-agentkit --list-presets
120
191
  ```
121
192
 
122
- List bundled design systems (source variants for `DESIGN-SYSTEM.md`):
193
+ List bundled design baselines (source variants for `DESIGN.md`):
123
194
 
124
195
  ```bash
125
196
  npx thomas-agentkit --list-design-systems
@@ -133,7 +204,7 @@ AgentKit can copy these bundled files into the target project:
133
204
  - `CHANGE-EXPLANATION.md`
134
205
  - `CLAUDE.md`
135
206
  - `CODE-QUALITY.md`
136
- - `DESIGN-SYSTEM.md`
207
+ - `DESIGN.md`
137
208
  - `IMPLEMENTATION-BRIEF-TEMPLATE.md`
138
209
  - `PRD-TEMPLATE.md`
139
210
  - `SECURITY-CHECKLIST.md`
@@ -145,7 +216,7 @@ AgentKit can copy these bundled files into the target project:
145
216
 
146
217
  When a preset is selected, AgentKit also installs `STACK.md` and adds a note in `AGENTS.md` telling agents to read it before changing stack-specific code.
147
218
 
148
- Bundled design system guidance is stored under `templates/design-systems/` in this repository (for example `linear.md`, `apple.md`). The CLI installs the chosen variant into `DESIGN-SYSTEM.md` in the target project; variant paths are not separate install targets.
219
+ Bundled design baselines are stored under `templates/design-systems/` in this repository (`linear`, `apple`, `cursor`, `framer`, `notion`, `warp`). The CLI installs the chosen variant into `DESIGN.md` in the target project; variant paths are not separate install targets. The bundled AgentKit skill also ships copies under `references/design-baselines/` for `/agentkit design`.
149
220
 
150
221
  Existing files are skipped by default so local edits are preserved. Use `--force` when you intentionally want to refresh files from the bundled package version.
151
222
 
@@ -161,12 +232,12 @@ Generated content
161
232
 
162
233
  Interactive personalization only applies during `agentkit init` when files are created or overwritten. It does not write a config file unless `--write-config` is passed, and `agentkit update` does not reapply personalized values.
163
234
 
164
- `agentkit.config.json` can set `preset`, `templateSet`, `designSystem`, `aiTools`, and `personalization` defaults. `templateSet` may be `minimal`, `standard`, or `full`; `designSystem` selects which bundled design-system variant fills `DESIGN-SYSTEM.md` (`linear` or `apple`); `aiTools` may include `codex`, `cursor`, `claude`, and `copilot`. `agentkit update` uses config `preset` and `designSystem` and continues to update all managed bundled templates.
235
+ `agentkit.config.json` can set `preset`, `templateSet`, `designSystem`, `aiTools`, and `personalization` defaults. `templateSet` may be `minimal`, `standard`, or `full`; `designSystem` selects which bundled baseline fills `DESIGN.md` (`linear`, `apple`, `cursor`, `framer`, `notion`, or `warp`); `aiTools` may include `codex`, `cursor`, `claude`, and `copilot`. `agentkit update` uses config `preset` and `designSystem` and continues to update all managed bundled templates.
165
236
 
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`, `.github/pull_request_template.md`
240
+ - `standard`: `AGENTS.md`, `CHANGE-EXPLANATION.md`, `CODE-QUALITY.md`, `DESIGN.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,31 @@ 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
+ | `agentkit design` | Agent | Create or refresh `DESIGN.md` from a bundled baseline |
277
+
278
+ Never use CLI `agentkit init` for skill installation.
279
+
280
+ 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.
281
+
191
282
  ## CLI Reference
192
283
 
193
284
  ```text
194
285
  agentkit init [target] [--force] [--dry-run] [--interactive] [--yes] [--write-config] [--preset <name>] [--design-system <name>]
286
+ agentkit skill install [target] [--force] [--dry-run] [--yes] [--preset <name>] [--design-system <name>]
195
287
  agentkit update [target] [--dry-run] [--preset <name>] [--design-system <name>]
196
288
  agentkit --list
197
289
  agentkit --list-presets
@@ -206,16 +298,16 @@ Options:
206
298
  - `--dry-run`: print planned changes without writing files
207
299
  - `-i, --interactive`: explicitly prompt for install options
208
300
  - `-y, --yes`: accept defaults without prompts
209
- - `--write-config`: write resolved install defaults to `agentkit.config.json`
301
+ - `--write-config`: write resolved template install defaults to `agentkit.config.json`
210
302
  - `--preset <name>`: install stack-specific guidance (`next`, `sveltekit`, `express`, `convex`, `fullstack`)
211
- - `--design-system <name>`: design system variant for `DESIGN-SYSTEM.md` (`linear`, `apple`)
303
+ - `--design-system <name>`: design baseline for `DESIGN.md` (`linear`, `apple`, `cursor`, `framer`, `notion`, `warp`)
212
304
  - `--list`: list bundled template files
213
305
  - `--list-presets`: list available presets
214
306
  - `--list-design-systems`: list available design systems
215
307
  - `-h, --help`: show help
216
308
  - `-v, --version`: show package version
217
309
 
218
- For `agentkit update`, `--preset <name>` refreshes preset-specific managed content, including `STACK.md`. `--design-system <name>` refreshes the managed `DESIGN-SYSTEM.md` body from the matching bundled variant.
310
+ For `agentkit update`, `--preset <name>` refreshes preset-specific managed content, including `STACK.md`. `--design-system <name>` refreshes the managed `DESIGN.md` body from the matching bundled baseline.
219
311
 
220
312
  ## Local Development
221
313
 
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, "..");
@@ -14,13 +15,33 @@ const validPresets = ["next", "sveltekit", "express", "convex", "fullstack"];
14
15
  const validProjectTypes = ["generic", ...validPresets];
15
16
  const validAiTools = ["codex", "cursor", "claude", "copilot"];
16
17
  const validTemplateSets = ["minimal", "standard", "full"];
17
- const validDesignSystems = ["linear", "apple"];
18
+ const validDesignSystems = [
19
+ "linear",
20
+ "apple",
21
+ "cursor",
22
+ "framer",
23
+ "notion",
24
+ "warp",
25
+ ];
18
26
  const designSystemLabels = {
19
- linear: "Linear-inspired",
20
- apple: "Apple-inspired",
27
+ linear: "Linear",
28
+ apple: "Apple",
29
+ cursor: "Cursor",
30
+ framer: "Framer",
31
+ notion: "Notion",
32
+ warp: "Warp",
21
33
  };
22
34
  const configFileName = "agentkit.config.json";
23
- const configKeys = ["preset", "templateSet", "aiTools", "designSystem", "personalization"];
35
+ const configKeys = [
36
+ "installMode",
37
+ "agentkitVersion",
38
+ "preset",
39
+ "templateSet",
40
+ "aiTools",
41
+ "designSystem",
42
+ "personalization",
43
+ ];
44
+ const validInstallModes = ["template", "skill"];
24
45
  const personalizationKeys = [
25
46
  "projectName",
26
47
  "projectDescription",
@@ -51,7 +72,7 @@ const templateSetFiles = {
51
72
  "AGENTS.md",
52
73
  "CHANGE-EXPLANATION.md",
53
74
  "CODE-QUALITY.md",
54
- "DESIGN-SYSTEM.md",
75
+ "DESIGN.md",
55
76
  ".github/pull_request_template.md",
56
77
  ],
57
78
  full: [],
@@ -128,7 +149,7 @@ async function collectInstallableTemplatePaths(dir, base) {
128
149
  for (const entry of entries) {
129
150
  const absolutePath = path.join(dir, entry.name);
130
151
  if (entry.isDirectory()) {
131
- if (dir === templatesDir && entry.name === "design-systems") {
152
+ if (dir === templatesDir && (entry.name === "design-systems" || entry.name === "skills")) {
132
153
  continue;
133
154
  }
134
155
  discovered.push(...(await collectInstallableTemplatePaths(absolutePath, base)));
@@ -143,10 +164,8 @@ async function collectInstallableTemplatePaths(dir, base) {
143
164
  }
144
165
  async function getTemplateFiles() {
145
166
  const discovered = await collectInstallableTemplatePaths(templatesDir, templatesDir);
146
- const withDesignSystem = discovered.includes("DESIGN-SYSTEM.md")
147
- ? discovered
148
- : [...discovered, "DESIGN-SYSTEM.md"];
149
- return withDesignSystem.sort();
167
+ const withDesign = discovered.includes("DESIGN.md") ? discovered : [...discovered, "DESIGN.md"];
168
+ return withDesign.sort();
150
169
  }
151
170
  function isPresetName(value) {
152
171
  return validPresets.includes(value);
@@ -257,13 +276,31 @@ function readConfigPersonalization(value) {
257
276
  }
258
277
  return personalization;
259
278
  }
279
+ function resolveInstallMode(installMode) {
280
+ const normalizedInstallMode = installMode.toLowerCase();
281
+ if (!validInstallModes.includes(normalizedInstallMode)) {
282
+ throw new Error(`Unknown install mode "${installMode}". Valid install modes: ${validInstallModes.join(", ")}.`);
283
+ }
284
+ return normalizedInstallMode;
285
+ }
286
+ export function getInstallMode(config) {
287
+ return config?.installMode ?? "template";
288
+ }
260
289
  function parseConfig(rawConfig, configPath) {
261
290
  assertPlainObject(rawConfig, configFileName);
262
291
  assertKnownKeys(rawConfig, configKeys, configFileName);
263
292
  const preset = optionalConfigString(rawConfig, "preset");
264
293
  const templateSet = optionalConfigString(rawConfig, "templateSet");
265
294
  const designSystem = optionalConfigString(rawConfig, "designSystem");
295
+ const installMode = optionalConfigString(rawConfig, "installMode");
296
+ const agentkitVersion = optionalConfigString(rawConfig, "agentkitVersion");
266
297
  const config = {};
298
+ if (installMode !== undefined) {
299
+ config.installMode = resolveInstallMode(installMode);
300
+ }
301
+ if (agentkitVersion !== undefined) {
302
+ config.agentkitVersion = agentkitVersion;
303
+ }
267
304
  if (preset !== undefined) {
268
305
  config.preset = resolvePreset(preset);
269
306
  }
@@ -394,8 +431,10 @@ function cleanPersonalizationValue(value) {
394
431
  const trimmed = value?.trim();
395
432
  return trimmed ? trimmed : undefined;
396
433
  }
397
- function getResolvedConfig(options) {
434
+ function getResolvedConfig(options, installMode, agentkitVersion) {
398
435
  const config = {
436
+ installMode,
437
+ agentkitVersion,
399
438
  templateSet: options.templateSet ?? "standard",
400
439
  aiTools: options.aiTools ?? [],
401
440
  designSystem: effectiveDesignSystem(options.designSystem),
@@ -488,7 +527,7 @@ export function personalizeTemplateContent(file, content, values) {
488
527
  return content;
489
528
  }
490
529
  let personalized = content;
491
- if (file === "AGENTS.md" || file === "DESIGN-SYSTEM.md") {
530
+ if (file === "AGENTS.md" || file === "DESIGN.md") {
492
531
  personalized = replaceIfProvided(personalized, "[Project Name]", values.projectName);
493
532
  }
494
533
  if (file === "AGENTS.md") {
@@ -573,7 +612,7 @@ async function resolveInitTemplateFiles(options) {
573
612
  }
574
613
  return getSelectedTemplateFiles(options.templateSet ?? "standard", options.aiTools ?? [], allTemplateFiles);
575
614
  }
576
- async function installTemplates(targetArg, options) {
615
+ async function installTemplates(targetArg, options, agentkitVersion) {
577
616
  const targetDir = path.resolve(process.cwd(), targetArg || ".");
578
617
  const files = await resolveInitTemplateFiles(options);
579
618
  const preset = resolvePreset(options.preset);
@@ -583,7 +622,7 @@ async function installTemplates(targetArg, options) {
583
622
  await mkdir(targetDir, { recursive: true });
584
623
  }
585
624
  if (options.writeConfig) {
586
- await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options)));
625
+ await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options, "template", agentkitVersion)));
587
626
  }
588
627
  for (const file of files) {
589
628
  await installFileIfAllowed(targetDir, file, options, result, async () => {
@@ -619,7 +658,7 @@ async function buildTemplateContent(file, preset, designSystem) {
619
658
  }
620
659
  return getStackGuidance(preset);
621
660
  }
622
- if (file === "DESIGN-SYSTEM.md") {
661
+ if (file === "DESIGN.md") {
623
662
  const source = path.join(templatesDir, "design-systems", `${designSystem}.md`);
624
663
  const content = await readFile(source, "utf8");
625
664
  return addStackReference(file, content, preset);
@@ -790,7 +829,23 @@ async function promptForConflictStrategy(existingFiles) {
790
829
  ],
791
830
  }));
792
831
  }
793
- async function applyInteractiveSelections(resolvedTarget, providedPreset, options) {
832
+ async function promptForBootstrapPath() {
833
+ return resolvePrompt(await select({
834
+ message: "How do you want to set up AgentKit?",
835
+ initialValue: "template",
836
+ options: [
837
+ {
838
+ label: "Copy templates now (install AGENTS.md and companion files)",
839
+ value: "template",
840
+ },
841
+ {
842
+ label: "Install AgentKit skill (create guidance files later in your agent)",
843
+ value: "skill",
844
+ },
845
+ ],
846
+ }));
847
+ }
848
+ async function collectInstallOptions(resolvedTarget, providedPreset, options) {
794
849
  if (!providedPreset) {
795
850
  options.preset = await promptForProjectPreset();
796
851
  }
@@ -803,25 +858,50 @@ async function applyInteractiveSelections(resolvedTarget, providedPreset, option
803
858
  if (templateSet === "standard" || templateSet === "full") {
804
859
  options.designSystem = await promptForDesignSystem(options.designSystem);
805
860
  }
806
- if (!options.force) {
861
+ }
862
+ async function resolveConflictForInstall(resolvedTarget, options, bootstrapPath) {
863
+ if (options.force) {
864
+ return;
865
+ }
866
+ let installFiles;
867
+ if (bootstrapPath === "skill") {
868
+ const skillFiles = await listSkillFiles(getSkillSourceDir(packageRoot));
869
+ installFiles = [...getSkillDestinationPaths(skillFiles), configFileName];
870
+ }
871
+ else {
807
872
  const preset = resolvePreset(options.preset);
808
- const installFiles = preset ? [...options.files, "STACK.md"] : options.files;
809
- const existingFiles = await findExistingInstallFiles(resolvedTarget, installFiles);
810
- if (existingFiles.length > 0) {
811
- options.force = (await promptForConflictStrategy(existingFiles)) === "overwrite";
812
- }
873
+ installFiles = preset ? [...(options.files ?? []), "STACK.md"] : (options.files ?? []);
874
+ }
875
+ const existingFiles = await findExistingInstallFiles(resolvedTarget, installFiles);
876
+ if (existingFiles.length > 0) {
877
+ options.force = (await promptForConflictStrategy(existingFiles)) === "overwrite";
813
878
  }
814
879
  }
815
- async function resolveInteractiveTarget(target, options) {
880
+ async function runInteractiveInstall(target, options, agentkitVersion) {
881
+ intro("Welcome to AgentKit");
882
+ const bootstrapPath = await promptForBootstrapPath();
816
883
  const providedPreset = resolvePreset(options.preset);
817
- if (!shouldPromptForInit(options, process)) {
818
- return target;
884
+ const resolvedTarget = await promptForTarget(target);
885
+ await collectInstallOptions(resolvedTarget, providedPreset, options);
886
+ options.personalization = await promptForPersonalization(options.personalization);
887
+ await resolveConflictForInstall(resolvedTarget, options, bootstrapPath);
888
+ if (bootstrapPath === "skill") {
889
+ const result = await installSkill(resolvedTarget, options, packageRoot, agentkitVersion);
890
+ printSkillInstallResult(result, Boolean(options.dryRun));
891
+ return;
819
892
  }
893
+ const result = await installTemplates(resolvedTarget, options, agentkitVersion);
894
+ printInstallResult(result, Boolean(options.dryRun));
895
+ }
896
+ async function runSkillInstallInteractive(target, options, agentkitVersion) {
820
897
  intro("Welcome to AgentKit");
898
+ const providedPreset = resolvePreset(options.preset);
821
899
  const resolvedTarget = await promptForTarget(target);
822
- await applyInteractiveSelections(resolvedTarget, providedPreset, options);
900
+ await collectInstallOptions(resolvedTarget, providedPreset, options);
823
901
  options.personalization = await promptForPersonalization(options.personalization);
824
- return resolvedTarget;
902
+ await resolveConflictForInstall(resolvedTarget, options, "skill");
903
+ const result = await installSkill(resolvedTarget, options, packageRoot, agentkitVersion);
904
+ printSkillInstallResult(result, Boolean(options.dryRun));
825
905
  }
826
906
  async function main() {
827
907
  if (process.argv.slice(2).includes("--list")) {
@@ -855,6 +935,7 @@ async function main() {
855
935
 
856
936
  Examples:
857
937
  agentkit init
938
+ agentkit skill install
858
939
  agentkit update
859
940
  agentkit init --preset next
860
941
  agentkit init ./my-project --yes --dry-run
@@ -871,22 +952,54 @@ Examples:
871
952
  .option("-y, --yes", "accept defaults for non-interactive runs")
872
953
  .option("--write-config", "write resolved install defaults to agentkit.config.json")
873
954
  .option("--preset <name>", `install stack-specific guidance (${formatPresetList()})`)
874
- .option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
955
+ .option("--design-system <name>", `design baseline for DESIGN.md (${formatDesignSystemList()})`)
875
956
  .action(async (target, options) => {
876
957
  await applyInitConfig(options, await loadConfigForTarget(target));
877
- const resolvedTarget = await resolveInteractiveTarget(target, options);
878
- const result = await installTemplates(resolvedTarget, options);
958
+ const agentkitVersion = await readPackageVersion();
959
+ if (shouldPromptForInit(options, process)) {
960
+ await runInteractiveInstall(target, options, agentkitVersion);
961
+ return;
962
+ }
963
+ const result = await installTemplates(target, options, agentkitVersion);
879
964
  printInstallResult(result, Boolean(options.dryRun));
880
965
  });
966
+ const skill = program.command("skill").description("install the bundled AgentKit Agent Skill");
967
+ skill
968
+ .command("install")
969
+ .description("install the bundled agentkit skill and write agentkit.config.json")
970
+ .argument("[target]", "target project directory", ".")
971
+ .option("--force", "overwrite existing skill files and config")
972
+ .option("--dry-run", "print planned changes without writing files")
973
+ .option("-i, --interactive", "prompt for install options")
974
+ .option("-y, --yes", "accept defaults for non-interactive runs")
975
+ .option("--preset <name>", `store stack preset in config (${formatPresetList()})`)
976
+ .option("--design-system <name>", `store design system choice in config (${formatDesignSystemList()})`)
977
+ .action(async (target, options) => {
978
+ await applyInitConfig(options, await loadConfigForTarget(target));
979
+ const agentkitVersion = await readPackageVersion();
980
+ if (shouldPromptForInit(options, process)) {
981
+ await runSkillInstallInteractive(target, options, agentkitVersion);
982
+ return;
983
+ }
984
+ const result = await installSkill(target, options, packageRoot, agentkitVersion);
985
+ printSkillInstallResult(result, Boolean(options.dryRun));
986
+ });
881
987
  program
882
988
  .command("update")
883
989
  .description("update AgentKit managed template blocks in a project")
884
990
  .argument("[target]", "target project directory", ".")
885
991
  .option("--dry-run", "print planned changes without writing files")
886
992
  .option("--preset <name>", `update stack-specific guidance (${formatPresetList()})`)
887
- .option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
993
+ .option("--design-system <name>", `design baseline for DESIGN.md (${formatDesignSystemList()})`)
888
994
  .action(async (target, options) => {
889
- applyUpdateConfig(options, await loadConfigForTarget(target));
995
+ const config = await loadConfigForTarget(target);
996
+ if (getInstallMode(config) === "skill") {
997
+ console.log("This project uses installMode: skill.");
998
+ console.log("Run agentkit update in your agent to sync guidance files.");
999
+ console.log("(CLI agentkit update applies to template-path installs.)");
1000
+ return;
1001
+ }
1002
+ applyUpdateConfig(options, config);
890
1003
  const result = await updateTemplates(target, options);
891
1004
  printUpdateResult(result, Boolean(options.dryRun));
892
1005
  });
@@ -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.8.0",
3
+ "version": "0.9.0-alpha.1",
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",
@@ -11,7 +11,7 @@ Use this rule as a repository guidance router for Cursor agents and composer wor
11
11
  ## When Relevant
12
12
 
13
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`.
14
+ - **UI / styling / layout:** `DESIGN.md` or the project design path from `AGENTS.md`.
15
15
  - **Review / refactor / dependencies:** `CODE-QUALITY.md`.
16
16
  - **Tests / QA strategy:** `TESTING.md` if present.
17
17
  - **Auth / secrets / PII:** `SECURITY-CHECKLIST.md` if present.