@danieljvdm/dev-kit 0.18.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +148 -659
  2. package/package.json +8 -62
  3. package/skills/dev-kit/SKILL.md +42 -212
  4. package/skills/dev-kit/agents/openai.yaml +2 -2
  5. package/skills/dev-kit/references/cloudflare-worker-api.md +37 -0
  6. package/skills/dev-kit/references/default-typescript-repository.md +43 -0
  7. package/skills/dev-kit/references/legacy-eject.md +46 -0
  8. package/skills/dev-kit/references/repository-setup.md +53 -0
  9. package/skills/dev-kit/references/skills.md +35 -0
  10. package/src/bin/dev-kit.ts +142 -127
  11. package/src/eject.ts +715 -0
  12. package/src/legacy-project.ts +67 -0
  13. package/src/oxfmt.ts +1 -4
  14. package/src/oxlint.ts +5 -10
  15. package/src/path-digest.ts +60 -0
  16. package/src/project-skills.ts +722 -0
  17. package/src/tool-metadata.ts +0 -2
  18. package/src/vendor.ts +0 -5
  19. package/src/vite-plus.ts +1 -3
  20. package/dev-kit.example.jsonc +0 -22
  21. package/schema/dev-kit.schema.json +0 -218
  22. package/schema/skill-sources.schema.json +0 -83
  23. package/scripts/sync-anti-slop-runtime.mjs +0 -19
  24. package/src/index.ts +0 -125
  25. package/src/manifest.ts +0 -224
  26. package/src/oxfmt.js +0 -23
  27. package/src/oxlint-plugin-anti-slop/runtime.d.ts +0 -22
  28. package/src/oxlint-plugin-effect.d.ts +0 -19
  29. package/src/oxlint-plugin-style.d.ts +0 -8
  30. package/src/oxlint.js +0 -113
  31. package/src/project-state.ts +0 -122
  32. package/src/scaffold.ts +0 -79
  33. package/src/skill-manager.ts +0 -527
  34. package/src/sync.ts +0 -1935
  35. package/src/tool-ignore-patterns.js +0 -9
  36. package/src/vite-plus-dependency.ts +0 -69
  37. package/src/vite-plus-hooks.ts +0 -175
  38. package/src/vite-plus-workflow.ts +0 -82
  39. package/src/vite-plus.js +0 -88
  40. package/src/worktrunk-config.ts +0 -88
  41. package/templates/AGENTS.md +0 -11
  42. package/templates/vite-plus/github-actions-check.yml +0 -51
  43. package/templates/worktrunk/wt.toml +0 -27
@@ -11,153 +11,179 @@ import {
11
11
  import { printError } from "../cli-ui.ts";
12
12
  import { syncEffectSource } from "../effect-source.ts";
13
13
  import { patchEffectTsgo } from "../effect-tsgo.ts";
14
+ import { runEject } from "../eject.ts";
14
15
  import { patchProjectGitignore } from "../gitignore.ts";
15
16
  import { CACHE_PRUNE_AGE_DAYS, runCachePrune } from "../global-cache.ts";
16
17
  import {
17
- addSkills,
18
- chooseSkillsToAdd,
19
- chooseSkillsToRemove,
20
- initProject,
21
- listSkills,
22
- removeSkills,
23
- showDashboard,
24
- showSkill,
25
- } from "../skill-manager.ts";
26
- import { DEFAULT_MANIFEST, runProjectSkillPlan } from "../sync.ts";
18
+ addProjectSkills,
19
+ detachProjectSkills,
20
+ diffProjectSkill,
21
+ listProjectSkills,
22
+ setupProject,
23
+ showProjectSkill,
24
+ showProjectSkillsDashboard,
25
+ statusProjectSkills,
26
+ updateProjectSkills,
27
+ } from "../project-skills.ts";
27
28
  import { DEV_KIT_VERSION } from "../tool-metadata.ts";
28
29
  import { refreshSkillCatalog } from "../vendor.ts";
29
30
 
30
- const projectFlags = {
31
- manifest: Flag.string("manifest").pipe(
32
- Flag.withDefault(DEFAULT_MANIFEST),
33
- Flag.withDescription("Project-relative manifest path."),
34
- ),
31
+ const repositorySkillFlags = {
35
32
  projectDir: Flag.string("project-dir").pipe(
36
33
  Flag.withDefault("."),
37
34
  Flag.withDescription("Project directory (defaults to the current directory)."),
38
35
  ),
36
+ target: Flag.string("target").pipe(
37
+ Flag.withDefault(".agents/skills"),
38
+ Flag.withDescription("Project-relative skills directory."),
39
+ ),
39
40
  };
40
41
 
41
- const initCommand = CliCommand.make("init", projectFlags, ({ manifest, projectDir }) =>
42
- initProject({ manifestPath: manifest, projectDir }),
43
- ).pipe(CliCommand.withDescription("Initialize skill management in this project."));
42
+ const setupCommand = CliCommand.make(
43
+ "setup",
44
+ {
45
+ dryRun: Flag.boolean("dry-run").pipe(Flag.withDescription("Preview without writing.")),
46
+ ...repositorySkillFlags,
47
+ },
48
+ ({ dryRun, projectDir, target }) => setupProject({ dryRun, projectDir, target }),
49
+ ).pipe(
50
+ CliCommand.withDescription(
51
+ "Copy the agent-led Dev Kit setup skill into a repository without adding a dependency.",
52
+ ),
53
+ );
44
54
 
45
- const addCommand = CliCommand.make(
46
- "add",
55
+ const ejectCommand = CliCommand.make(
56
+ "eject",
47
57
  {
48
- skills: Argument.string("skills").pipe(Argument.variadic()),
49
- noApply: Flag.boolean("no-apply").pipe(
50
- Flag.withDescription("Update the manifest without installing yet."),
58
+ dryRun: Flag.boolean("dry-run").pipe(Flag.withDescription("Preview without writing.")),
59
+ lockfile: Flag.string("lockfile").pipe(
60
+ Flag.withDefault("dev-kit.lock.json"),
61
+ Flag.withDescription("Project-relative legacy lock path."),
62
+ ),
63
+ manifest: Flag.string("manifest").pipe(
64
+ Flag.withDefault("dev-kit.jsonc"),
65
+ Flag.withDescription("Project-relative legacy manifest path."),
66
+ ),
67
+ projectDir: Flag.string("project-dir").pipe(
68
+ Flag.withDefault("."),
69
+ Flag.withDescription("Legacy project directory."),
70
+ ),
71
+ state: Flag.string("state").pipe(
72
+ Flag.withDefault(".dev-kit/state.json"),
73
+ Flag.withDescription("Project-relative legacy ownership receipt."),
74
+ ),
75
+ target: Flag.string("target").pipe(
76
+ Flag.withDefault(".agents/skills"),
77
+ Flag.withDescription("Project-relative destination for ejected skills."),
51
78
  ),
52
- ...projectFlags,
53
79
  },
54
- ({ skills, noApply, manifest, projectDir }) =>
55
- skills.length === 0
56
- ? chooseSkillsToAdd({ apply: !noApply, manifestPath: manifest, projectDir })
57
- : addSkills(skills, { apply: !noApply, manifestPath: manifest, projectDir }),
58
- ).pipe(CliCommand.withDescription("Select and install one or more available skills."));
80
+ ({ dryRun, lockfile, manifest, projectDir, state, target }) =>
81
+ runEject({
82
+ dryRun,
83
+ lockfilePath: lockfile,
84
+ manifestPath: manifest,
85
+ projectDir,
86
+ statePath: state,
87
+ target,
88
+ }),
89
+ ).pipe(
90
+ CliCommand.withDescription(
91
+ "Release a legacy managed project into repo-owned files after persistent helpers are materialized.",
92
+ ),
93
+ );
59
94
 
60
- const removeCommand = CliCommand.make(
61
- "remove",
95
+ const projectSkillsAddCommand = CliCommand.make(
96
+ "add",
62
97
  {
63
- skills: Argument.string("skills").pipe(Argument.variadic()),
64
- noApply: Flag.boolean("no-apply").pipe(
65
- Flag.withDescription("Update the manifest without uninstalling yet."),
66
- ),
67
- ...projectFlags,
98
+ skills: Argument.string("skills").pipe(Argument.variadic({ min: 1 })),
99
+ dryRun: Flag.boolean("dry-run").pipe(Flag.withDescription("Preview without writing.")),
100
+ ...repositorySkillFlags,
68
101
  },
69
- ({ skills, noApply, manifest, projectDir }) =>
70
- skills.length === 0
71
- ? chooseSkillsToRemove({ apply: !noApply, manifestPath: manifest, projectDir })
72
- : removeSkills(skills, { apply: !noApply, manifestPath: manifest, projectDir }),
73
- ).pipe(CliCommand.withDescription("Deselect and uninstall one or more skills."));
102
+ ({ skills, dryRun, projectDir, target }) =>
103
+ addProjectSkills(skills, { dryRun, projectDir, target }),
104
+ ).pipe(CliCommand.withDescription("Copy repo-owned skills from the approved catalog."));
74
105
 
75
- const listCommand = CliCommand.make(
106
+ const projectSkillsListCommand = CliCommand.make(
76
107
  "list",
77
108
  {
78
- all: Flag.boolean("all").pipe(Flag.withDescription("Include unselected skills.")),
79
- ...projectFlags,
109
+ all: Flag.boolean("all").pipe(Flag.withDescription("Include uninstalled skills.")),
110
+ ...repositorySkillFlags,
80
111
  },
81
- ({ all, manifest, projectDir }) => listSkills({ all, manifestPath: manifest, projectDir }),
82
- ).pipe(CliCommand.withDescription("List selected skills; use --all to browse the catalog."));
112
+ ({ all, projectDir, target }) => listProjectSkills({ all, projectDir, target }),
113
+ ).pipe(CliCommand.withDescription("List installed skills or browse the catalog."));
83
114
 
84
- const searchCommand = CliCommand.make(
115
+ const projectSkillsSearchCommand = CliCommand.make(
85
116
  "search",
86
- { query: Argument.string("query").pipe(Argument.variadic({ min: 1 })), ...projectFlags },
87
- ({ query, manifest, projectDir }) =>
88
- listSkills({ all: true, query: query.join(" "), manifestPath: manifest, projectDir }),
89
- ).pipe(CliCommand.withDescription("Search available skill names and descriptions."));
117
+ {
118
+ query: Argument.string("query").pipe(Argument.variadic({ min: 1 })),
119
+ ...repositorySkillFlags,
120
+ },
121
+ ({ query, projectDir, target }) =>
122
+ listProjectSkills({ all: true, projectDir, query: query.join(" "), target }),
123
+ ).pipe(CliCommand.withDescription("Search the approved skill catalog."));
90
124
 
91
- const infoCommand = CliCommand.make(
125
+ const projectSkillsInfoCommand = CliCommand.make(
92
126
  "info",
93
- { skill: Argument.string("skill"), ...projectFlags },
94
- ({ skill, manifest, projectDir }) => showSkill(skill, { manifestPath: manifest, projectDir }),
95
- ).pipe(CliCommand.withDescription("Show provenance and details for an available skill."));
127
+ { skill: Argument.string("skill"), ...repositorySkillFlags },
128
+ ({ skill, projectDir, target }) => showProjectSkill(skill, { projectDir, target }),
129
+ ).pipe(CliCommand.withDescription("Show one skill's description and provenance."));
96
130
 
97
- const planCommand = CliCommand.make(
98
- "plan",
99
- {
100
- locked: Flag.boolean("locked"),
101
- lockfile: Flag.string("lockfile").pipe(Flag.withDefault("dev-kit.lock.json")),
102
- manifest: Flag.string("manifest").pipe(Flag.withDefault(DEFAULT_MANIFEST)),
103
- projectDir: Flag.string("project-dir").pipe(Flag.withDefault(".")),
104
- },
105
- ({ locked, lockfile, manifest, projectDir }) =>
106
- runProjectSkillPlan({
107
- dryRun: true,
108
- locked,
109
- lockfilePath: lockfile,
110
- manifestPath: manifest,
111
- projectDir,
112
- }),
113
- ).pipe(
114
- CliCommand.withDescription("Plan ownership-safe project skill changes without writing files."),
115
- );
131
+ const projectSkillsStatusCommand = CliCommand.make(
132
+ "status",
133
+ repositorySkillFlags,
134
+ ({ projectDir, target }) => statusProjectSkills({ projectDir, target }),
135
+ ).pipe(CliCommand.withDescription("Compare tracked skills with their approved upstream copies."));
116
136
 
117
- const applyCommand = CliCommand.make(
118
- "apply",
137
+ const projectSkillsUpdateCommand = CliCommand.make(
138
+ "update",
119
139
  {
120
- locked: Flag.boolean("locked"),
121
- lockfile: Flag.string("lockfile").pipe(Flag.withDefault("dev-kit.lock.json")),
122
- manifest: Flag.string("manifest").pipe(Flag.withDefault(DEFAULT_MANIFEST)),
123
- projectDir: Flag.string("project-dir").pipe(Flag.withDefault(".")),
140
+ skills: Argument.string("skills").pipe(Argument.variadic()),
141
+ acceptLocal: Flag.boolean("accept-local").pipe(
142
+ Flag.withDescription(
143
+ "After an agent merge, keep local content and accept the latest upstream base.",
144
+ ),
145
+ ),
146
+ dryRun: Flag.boolean("dry-run").pipe(Flag.withDescription("Preview without writing.")),
147
+ ...repositorySkillFlags,
124
148
  },
125
- ({ locked, lockfile, manifest, projectDir }) =>
126
- runProjectSkillPlan({
127
- locked,
128
- lockfilePath: lockfile,
129
- manifestPath: manifest,
130
- projectDir,
131
- }),
149
+ ({ skills, acceptLocal, dryRun, projectDir, target }) =>
150
+ updateProjectSkills(skills, { acceptLocal, dryRun, projectDir, target }),
132
151
  ).pipe(
133
- CliCommand.withDescription("Apply ownership-safe project skill changes and update the lock."),
152
+ CliCommand.withDescription(
153
+ "Fast-forward unmodified tracked skills; preserve locally edited copies for an agent merge.",
154
+ ),
134
155
  );
135
156
 
136
- const syncCommand = CliCommand.make(
137
- "sync",
138
- {
139
- locked: Flag.boolean("locked"),
140
- lockfile: Flag.string("lockfile").pipe(Flag.withDefault("dev-kit.lock.json")),
141
- ...projectFlags,
142
- },
143
- ({ locked, lockfile, manifest, projectDir }) =>
144
- runProjectSkillPlan({ locked, lockfilePath: lockfile, manifestPath: manifest, projectDir }),
145
- ).pipe(CliCommand.withDescription("Install the skills selected in dev-kit.jsonc."));
157
+ const projectSkillsDiffCommand = CliCommand.make(
158
+ "diff",
159
+ { skill: Argument.string("skill"), ...repositorySkillFlags },
160
+ ({ skill, projectDir, target }) => diffProjectSkill(skill, { projectDir, target }),
161
+ ).pipe(CliCommand.withDescription("Diff a tracked skill against its approved upstream copy."));
146
162
 
147
- const statusCommand = CliCommand.make(
148
- "status",
163
+ const projectSkillsDetachCommand = CliCommand.make(
164
+ "detach",
149
165
  {
150
- lockfile: Flag.string("lockfile").pipe(Flag.withDefault("dev-kit.lock.json")),
151
- ...projectFlags,
166
+ skills: Argument.string("skills").pipe(Argument.variadic({ min: 1 })),
167
+ dryRun: Flag.boolean("dry-run").pipe(Flag.withDescription("Preview without writing.")),
168
+ ...repositorySkillFlags,
152
169
  },
153
- ({ lockfile, manifest, projectDir }) =>
154
- runProjectSkillPlan({
155
- dryRun: true,
156
- lockfilePath: lockfile,
157
- manifestPath: manifest,
158
- projectDir,
159
- }),
160
- ).pipe(CliCommand.withDescription("Check whether selected skills match the project."));
170
+ ({ skills, dryRun, projectDir, target }) =>
171
+ detachProjectSkills(skills, { dryRun, projectDir, target }),
172
+ ).pipe(CliCommand.withDescription("Remove upstream receipts while leaving skill content intact."));
173
+
174
+ const projectSkillsCommand = CliCommand.make("skills").pipe(
175
+ CliCommand.withDescription("Copy and optionally refresh repo-owned agent skills."),
176
+ CliCommand.withSubcommands([
177
+ projectSkillsAddCommand,
178
+ projectSkillsListCommand,
179
+ projectSkillsSearchCommand,
180
+ projectSkillsInfoCommand,
181
+ projectSkillsStatusCommand,
182
+ projectSkillsUpdateCommand,
183
+ projectSkillsDiffCommand,
184
+ projectSkillsDetachCommand,
185
+ ] as const),
186
+ );
161
187
 
162
188
  const gitignoreCommand = CliCommand.make(
163
189
  "gitignore",
@@ -387,27 +413,16 @@ const catalogCommand = CliCommand.make("catalog").pipe(
387
413
  ] as const),
388
414
  );
389
415
 
390
- const command = CliCommand.make("dev-kit", projectFlags, ({ manifest, projectDir }) =>
391
- showDashboard({ manifestPath: manifest, projectDir }),
392
- ).pipe(
393
- CliCommand.withDescription("Your approved skill catalog for coding agents."),
416
+ const command = CliCommand.make("dev-kit", {}, () => showProjectSkillsDashboard()).pipe(
417
+ CliCommand.withDescription("Agent-led repository setup and an approved skill catalog."),
394
418
  CliCommand.withSubcommands([
395
419
  {
396
- group: "Skills",
397
- commands: [initCommand, addCommand, removeCommand, listCommand, searchCommand, infoCommand],
420
+ group: "Repository",
421
+ commands: [setupCommand, projectSkillsCommand, ejectCommand],
398
422
  },
399
- { group: "Project", commands: [statusCommand, syncCommand] },
400
423
  {
401
- group: "Advanced",
402
- commands: [
403
- planCommand,
404
- applyCommand,
405
- gitignoreCommand,
406
- effectCommand,
407
- tsgoCommand,
408
- catalogCommand,
409
- cacheCommand,
410
- ],
424
+ group: "Toolbox",
425
+ commands: [gitignoreCommand, effectCommand, tsgoCommand, catalogCommand, cacheCommand],
411
426
  },
412
427
  ] as const),
413
428
  );