thomas-agentkit 0.8.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 +93 -2
- package/dist/cli.js +124 -20
- package/dist/skill-install.js +125 -0
- package/package.json +3 -1
- 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
|
|
|
@@ -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
|
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",
|
|
@@ -128,7 +138,7 @@ async function collectInstallableTemplatePaths(dir, base) {
|
|
|
128
138
|
for (const entry of entries) {
|
|
129
139
|
const absolutePath = path.join(dir, entry.name);
|
|
130
140
|
if (entry.isDirectory()) {
|
|
131
|
-
if (dir === templatesDir && entry.name === "design-systems") {
|
|
141
|
+
if (dir === templatesDir && (entry.name === "design-systems" || entry.name === "skills")) {
|
|
132
142
|
continue;
|
|
133
143
|
}
|
|
134
144
|
discovered.push(...(await collectInstallableTemplatePaths(absolutePath, base)));
|
|
@@ -257,13 +267,31 @@ function readConfigPersonalization(value) {
|
|
|
257
267
|
}
|
|
258
268
|
return personalization;
|
|
259
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
|
+
}
|
|
260
280
|
function parseConfig(rawConfig, configPath) {
|
|
261
281
|
assertPlainObject(rawConfig, configFileName);
|
|
262
282
|
assertKnownKeys(rawConfig, configKeys, configFileName);
|
|
263
283
|
const preset = optionalConfigString(rawConfig, "preset");
|
|
264
284
|
const templateSet = optionalConfigString(rawConfig, "templateSet");
|
|
265
285
|
const designSystem = optionalConfigString(rawConfig, "designSystem");
|
|
286
|
+
const installMode = optionalConfigString(rawConfig, "installMode");
|
|
287
|
+
const agentkitVersion = optionalConfigString(rawConfig, "agentkitVersion");
|
|
266
288
|
const config = {};
|
|
289
|
+
if (installMode !== undefined) {
|
|
290
|
+
config.installMode = resolveInstallMode(installMode);
|
|
291
|
+
}
|
|
292
|
+
if (agentkitVersion !== undefined) {
|
|
293
|
+
config.agentkitVersion = agentkitVersion;
|
|
294
|
+
}
|
|
267
295
|
if (preset !== undefined) {
|
|
268
296
|
config.preset = resolvePreset(preset);
|
|
269
297
|
}
|
|
@@ -394,8 +422,10 @@ function cleanPersonalizationValue(value) {
|
|
|
394
422
|
const trimmed = value?.trim();
|
|
395
423
|
return trimmed ? trimmed : undefined;
|
|
396
424
|
}
|
|
397
|
-
function getResolvedConfig(options) {
|
|
425
|
+
function getResolvedConfig(options, installMode, agentkitVersion) {
|
|
398
426
|
const config = {
|
|
427
|
+
installMode,
|
|
428
|
+
agentkitVersion,
|
|
399
429
|
templateSet: options.templateSet ?? "standard",
|
|
400
430
|
aiTools: options.aiTools ?? [],
|
|
401
431
|
designSystem: effectiveDesignSystem(options.designSystem),
|
|
@@ -573,7 +603,7 @@ async function resolveInitTemplateFiles(options) {
|
|
|
573
603
|
}
|
|
574
604
|
return getSelectedTemplateFiles(options.templateSet ?? "standard", options.aiTools ?? [], allTemplateFiles);
|
|
575
605
|
}
|
|
576
|
-
async function installTemplates(targetArg, options) {
|
|
606
|
+
async function installTemplates(targetArg, options, agentkitVersion) {
|
|
577
607
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
578
608
|
const files = await resolveInitTemplateFiles(options);
|
|
579
609
|
const preset = resolvePreset(options.preset);
|
|
@@ -583,7 +613,7 @@ async function installTemplates(targetArg, options) {
|
|
|
583
613
|
await mkdir(targetDir, { recursive: true });
|
|
584
614
|
}
|
|
585
615
|
if (options.writeConfig) {
|
|
586
|
-
await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options)));
|
|
616
|
+
await installFileIfAllowed(targetDir, configFileName, options, result, () => serializeConfig(getResolvedConfig(options, "template", agentkitVersion)));
|
|
587
617
|
}
|
|
588
618
|
for (const file of files) {
|
|
589
619
|
await installFileIfAllowed(targetDir, file, options, result, async () => {
|
|
@@ -790,7 +820,23 @@ async function promptForConflictStrategy(existingFiles) {
|
|
|
790
820
|
],
|
|
791
821
|
}));
|
|
792
822
|
}
|
|
793
|
-
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) {
|
|
794
840
|
if (!providedPreset) {
|
|
795
841
|
options.preset = await promptForProjectPreset();
|
|
796
842
|
}
|
|
@@ -803,25 +849,50 @@ async function applyInteractiveSelections(resolvedTarget, providedPreset, option
|
|
|
803
849
|
if (templateSet === "standard" || templateSet === "full") {
|
|
804
850
|
options.designSystem = await promptForDesignSystem(options.designSystem);
|
|
805
851
|
}
|
|
806
|
-
|
|
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 {
|
|
807
863
|
const preset = resolvePreset(options.preset);
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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";
|
|
813
869
|
}
|
|
814
870
|
}
|
|
815
|
-
async function
|
|
871
|
+
async function runInteractiveInstall(target, options, agentkitVersion) {
|
|
872
|
+
intro("Welcome to AgentKit");
|
|
873
|
+
const bootstrapPath = await promptForBootstrapPath();
|
|
816
874
|
const providedPreset = resolvePreset(options.preset);
|
|
817
|
-
|
|
818
|
-
|
|
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;
|
|
819
883
|
}
|
|
884
|
+
const result = await installTemplates(resolvedTarget, options, agentkitVersion);
|
|
885
|
+
printInstallResult(result, Boolean(options.dryRun));
|
|
886
|
+
}
|
|
887
|
+
async function runSkillInstallInteractive(target, options, agentkitVersion) {
|
|
820
888
|
intro("Welcome to AgentKit");
|
|
889
|
+
const providedPreset = resolvePreset(options.preset);
|
|
821
890
|
const resolvedTarget = await promptForTarget(target);
|
|
822
|
-
await
|
|
891
|
+
await collectInstallOptions(resolvedTarget, providedPreset, options);
|
|
823
892
|
options.personalization = await promptForPersonalization(options.personalization);
|
|
824
|
-
|
|
893
|
+
await resolveConflictForInstall(resolvedTarget, options, "skill");
|
|
894
|
+
const result = await installSkill(resolvedTarget, options, packageRoot, agentkitVersion);
|
|
895
|
+
printSkillInstallResult(result, Boolean(options.dryRun));
|
|
825
896
|
}
|
|
826
897
|
async function main() {
|
|
827
898
|
if (process.argv.slice(2).includes("--list")) {
|
|
@@ -855,6 +926,7 @@ async function main() {
|
|
|
855
926
|
|
|
856
927
|
Examples:
|
|
857
928
|
agentkit init
|
|
929
|
+
agentkit skill install
|
|
858
930
|
agentkit update
|
|
859
931
|
agentkit init --preset next
|
|
860
932
|
agentkit init ./my-project --yes --dry-run
|
|
@@ -874,10 +946,35 @@ Examples:
|
|
|
874
946
|
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
875
947
|
.action(async (target, options) => {
|
|
876
948
|
await applyInitConfig(options, await loadConfigForTarget(target));
|
|
877
|
-
const
|
|
878
|
-
|
|
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);
|
|
879
955
|
printInstallResult(result, Boolean(options.dryRun));
|
|
880
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
|
+
});
|
|
881
978
|
program
|
|
882
979
|
.command("update")
|
|
883
980
|
.description("update AgentKit managed template blocks in a project")
|
|
@@ -886,7 +983,14 @@ Examples:
|
|
|
886
983
|
.option("--preset <name>", `update stack-specific guidance (${formatPresetList()})`)
|
|
887
984
|
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
888
985
|
.action(async (target, options) => {
|
|
889
|
-
|
|
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);
|
|
890
994
|
const result = await updateTemplates(target, options);
|
|
891
995
|
printUpdateResult(result, Boolean(options.dryRun));
|
|
892
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",
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentkit
|
|
3
|
+
description: Use when creating, syncing, auditing, repairing, or learning AgentKit-managed repository guidance and codebase changes in an agent session, especially after `agentkit skill install`, when `/agentkit init`, `/agentkit update`, `/agentkit doctor`, `/agentkit repair`, or `/agentkit learn` is requested, or when AGENTS.md, STACK.md, companion guides, managed blocks, commands, placeholders, AI tool adapters, recent diffs, or completed changes need context-aware maintenance or explanation.
|
|
4
|
+
compatibility: Requires agentkit CLI and agentkit.config.json with installMode skill, or existing AgentKit-managed files with block markers.
|
|
5
|
+
metadata:
|
|
6
|
+
author: thomas-agentkit
|
|
7
|
+
version: "1.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# AgentKit Skill
|
|
11
|
+
|
|
12
|
+
Create, sync, audit, repair, and teach AgentKit-managed repository guidance and codebase changes using live repository context.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- User ran `agentkit skill install`
|
|
17
|
+
- User asks `/agentkit init`, `/agentkit update`, `/agentkit doctor`, `/agentkit repair`, or `/agentkit learn`
|
|
18
|
+
- `AGENTS.md`, `STACK.md`, companion guides, or AI adapters are missing
|
|
19
|
+
- Guidance has stale commands, stack details, project paths, placeholders, or broken references
|
|
20
|
+
- Managed blocks need context-aware update, audit, or repair
|
|
21
|
+
- User wants to understand recent codebase changes, a completed implementation, a diff, a bug fix, or the session
|
|
22
|
+
|
|
23
|
+
## When not to use
|
|
24
|
+
|
|
25
|
+
- User wants terminal template install -> direct them to CLI `agentkit init`
|
|
26
|
+
- User wants terminal template update -> direct them to CLI `agentkit update` unless config says `installMode: skill`
|
|
27
|
+
- Generic documentation requests unrelated to AgentKit guidance
|
|
28
|
+
- Code review findings, debugging, or feature implementation requests
|
|
29
|
+
- Short summaries that do not require a guided teaching workflow
|
|
30
|
+
|
|
31
|
+
## Route
|
|
32
|
+
|
|
33
|
+
Always read `references/file-contract.md` before editing or auditing AgentKit-managed files. Do not act from `SKILL.md` alone.
|
|
34
|
+
|
|
35
|
+
1. User asks to **initialize** missing guidance files from repo context
|
|
36
|
+
→ `references/init.md`
|
|
37
|
+
|
|
38
|
+
2. User asks to **update** or **sync** existing guidance with current repo context
|
|
39
|
+
→ `references/update.md`
|
|
40
|
+
|
|
41
|
+
3. User asks to **doctor**, **audit**, **review**, **diagnose**, or **health check** guidance quality
|
|
42
|
+
→ `references/doctor.md`
|
|
43
|
+
|
|
44
|
+
4. User asks to **repair**, **fix malformed blocks**, **convert unmanaged guidance**, or **fix adapters**
|
|
45
|
+
→ `references/repair.md`
|
|
46
|
+
|
|
47
|
+
5. User asks to **learn**, **understand recent changes**, **explain the session**, **teach me what changed**, **ELI5**, **ELI14**, **explain like an intern**, or **check my understanding**
|
|
48
|
+
→ `references/learn.md`
|
|
49
|
+
|
|
50
|
+
6. Unsure which workflow applies
|
|
51
|
+
→ If no guidance files exist: `references/init.md`
|
|
52
|
+
→ If guidance exists but commands, stack, files, placeholders, adapters, or references are stale: `references/update.md`
|
|
53
|
+
→ If user wants audit, doctor, health check, diagnosis, or review: `references/doctor.md`
|
|
54
|
+
→ If managed blocks are malformed or unmanaged files need conversion: `references/repair.md`
|
|
55
|
+
→ If user wants to understand completed changes or a session: `references/learn.md`
|
|
56
|
+
|
|
57
|
+
## Non-negotiables
|
|
58
|
+
|
|
59
|
+
- `AGENTS.md` is the source of truth; AI tool adapters stay thin pointers
|
|
60
|
+
- Read the route reference and `references/file-contract.md` before file edits
|
|
61
|
+
- Preserve user content **outside** AgentKit managed blocks
|
|
62
|
+
- Skip unmanaged existing files unless conversion is explicitly requested
|
|
63
|
+
- Defer malformed managed blocks to `references/repair.md`
|
|
64
|
+
- Commands in guidance must come from `package.json` scripts or `agentkit.config.json` personalization — never invent scripts
|
|
65
|
+
- Prefer repo facts over config personalization
|
|
66
|
+
- Do not modify app source, lockfiles, package manifests, or CI config during AgentKit workflows
|
|
67
|
+
- `/agentkit learn` is read-only by default and keeps learning checklists in the conversation unless the user explicitly asks for notes
|
|
68
|
+
- CLI `agentkit init` installs **templates**; this skill's `agentkit init` **creates guidance files** — never confuse them
|
|
69
|
+
|
|
70
|
+
## Gotchas
|
|
71
|
+
|
|
72
|
+
| Gotcha | Reality |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `installMode: skill` but no `.md` files yet | Expected after `agentkit skill install`; run `/agentkit init` |
|
|
75
|
+
| `templateSet: minimal` | `AGENTS.md` only, plus selected adapters if explicitly configured |
|
|
76
|
+
| `templateSet: standard` | Core companions only; not testing/security/workflow docs |
|
|
77
|
+
| `templateSet: full` | Full guidance docs; adapters still follow `aiTools` |
|
|
78
|
+
| AI tool adapters | Thin pointers to `AGENTS.md`; never duplicate full guidance |
|
|
79
|
+
| `STACK.md` | Create/update when preset is configured, user asks, or stack is confidently inferred |
|
|
80
|
+
| Existing unmanaged files | Skip unless user asks to convert |
|
|
81
|
+
| Malformed managed blocks | Use `/agentkit repair` before update/refresh |
|
|
82
|
+
| Learning workflow | `/agentkit learn` teaches from diffs and code; it does not create notes or files by default |
|
|
83
|
+
| Docs-only guidance workflow | Does not require running project tests/builds |
|
|
84
|
+
|
|
85
|
+
## Quick reference
|
|
86
|
+
|
|
87
|
+
| User says | Load |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| "/agentkit init" / "set up AGENTS.md" | `references/init.md` |
|
|
90
|
+
| "/agentkit update" / "sync guidance" | `references/update.md` |
|
|
91
|
+
| "/agentkit doctor" / "audit AgentKit guidance" | `references/doctor.md` |
|
|
92
|
+
| "/agentkit repair" / "fix managed blocks" | `references/repair.md` |
|
|
93
|
+
| "/agentkit learn" / "teach me what changed" | `references/learn.md` |
|
|
94
|
+
| Before any file edit | `references/file-contract.md` |
|