thomas-agentkit 0.4.2 → 0.5.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 +16 -4
- package/dist/cli.js +87 -20
- package/package.json +1 -1
- /package/templates/{DESIGN-SYSTEM.md → design-systems/linear.md} +0 -0
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ Standardize install defaults with `agentkit.config.json`:
|
|
|
72
72
|
{
|
|
73
73
|
"preset": "next",
|
|
74
74
|
"templateSet": "standard",
|
|
75
|
+
"designSystem": "linear",
|
|
75
76
|
"aiTools": ["codex", "cursor", "claude"],
|
|
76
77
|
"personalization": {
|
|
77
78
|
"projectName": "Acme CRM",
|
|
@@ -109,6 +110,12 @@ List available presets:
|
|
|
109
110
|
npx thomas-agentkit --list-presets
|
|
110
111
|
```
|
|
111
112
|
|
|
113
|
+
List bundled design systems (source variants for `DESIGN-SYSTEM.md`):
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx thomas-agentkit --list-design-systems
|
|
117
|
+
```
|
|
118
|
+
|
|
112
119
|
## Installed Files
|
|
113
120
|
|
|
114
121
|
AgentKit copies these bundled files into the target project:
|
|
@@ -126,6 +133,8 @@ AgentKit copies these bundled files into the target project:
|
|
|
126
133
|
|
|
127
134
|
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.
|
|
128
135
|
|
|
136
|
+
Bundled design system guidance is stored under `templates/design-systems/` in this repository (for example `linear.md`). The CLI installs the chosen variant into `DESIGN-SYSTEM.md` in the target project; variant paths are not separate install targets.
|
|
137
|
+
|
|
129
138
|
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.
|
|
130
139
|
|
|
131
140
|
New installs wrap generated template content in AgentKit managed block markers:
|
|
@@ -140,7 +149,7 @@ Generated content
|
|
|
140
149
|
|
|
141
150
|
Interactive personalization only applies during `agentkit init` when files are created or overwritten. It does not write a config file, and `agentkit update` does not reapply personalized values.
|
|
142
151
|
|
|
143
|
-
`agentkit.config.json` can set `preset`, `templateSet`, `aiTools`, and `personalization` defaults. `templateSet` may be `minimal`, `standard`, or `full`; `aiTools` may include `codex`, `cursor`, `claude`, and `copilot`. `agentkit update`
|
|
152
|
+
`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` (currently `linear`); `aiTools` may include `codex`, `cursor`, `claude`, and `copilot`. `agentkit update` uses config `preset` and `designSystem` and continues to update all managed bundled templates.
|
|
144
153
|
|
|
145
154
|
## Presets
|
|
146
155
|
|
|
@@ -155,10 +164,11 @@ Presets add stack-specific guidance without scaffolding framework app files.
|
|
|
155
164
|
## CLI Reference
|
|
156
165
|
|
|
157
166
|
```text
|
|
158
|
-
agentkit init [target] [--force] [--dry-run] [--interactive] [--yes] [--write-config] [--preset <name>]
|
|
159
|
-
agentkit update [target] [--dry-run] [--preset <name>]
|
|
167
|
+
agentkit init [target] [--force] [--dry-run] [--interactive] [--yes] [--write-config] [--preset <name>] [--design-system <name>]
|
|
168
|
+
agentkit update [target] [--dry-run] [--preset <name>] [--design-system <name>]
|
|
160
169
|
agentkit --list
|
|
161
170
|
agentkit --list-presets
|
|
171
|
+
agentkit --list-design-systems
|
|
162
172
|
agentkit --help
|
|
163
173
|
agentkit --version
|
|
164
174
|
```
|
|
@@ -171,12 +181,14 @@ Options:
|
|
|
171
181
|
- `-y, --yes`: accept defaults without prompts
|
|
172
182
|
- `--write-config`: write resolved install defaults to `agentkit.config.json`
|
|
173
183
|
- `--preset <name>`: install stack-specific guidance (`next`, `sveltekit`, `express`, `convex`, `fullstack`)
|
|
184
|
+
- `--design-system <name>`: design system variant for `DESIGN-SYSTEM.md` (`linear`)
|
|
174
185
|
- `--list`: list bundled template files
|
|
175
186
|
- `--list-presets`: list available presets
|
|
187
|
+
- `--list-design-systems`: list available design systems
|
|
176
188
|
- `-h, --help`: show help
|
|
177
189
|
- `-v, --version`: show package version
|
|
178
190
|
|
|
179
|
-
For `agentkit update`, `--preset <name>` refreshes preset-specific managed content, including `STACK.md`.
|
|
191
|
+
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.
|
|
180
192
|
|
|
181
193
|
## Local Development
|
|
182
194
|
|
package/dist/cli.js
CHANGED
|
@@ -14,8 +14,12 @@ const validPresets = ["next", "sveltekit", "express", "convex", "fullstack"];
|
|
|
14
14
|
const validProjectTypes = ["generic", ...validPresets];
|
|
15
15
|
const validAiTools = ["codex", "cursor", "claude", "copilot"];
|
|
16
16
|
const validTemplateSets = ["minimal", "standard", "full"];
|
|
17
|
+
const validDesignSystems = ["linear"];
|
|
18
|
+
const designSystemLabels = {
|
|
19
|
+
linear: "Linear-inspired",
|
|
20
|
+
};
|
|
17
21
|
const configFileName = "agentkit.config.json";
|
|
18
|
-
const configKeys = ["preset", "templateSet", "aiTools", "personalization"];
|
|
22
|
+
const configKeys = ["preset", "templateSet", "aiTools", "designSystem", "personalization"];
|
|
19
23
|
const personalizationKeys = [
|
|
20
24
|
"projectName",
|
|
21
25
|
"projectDescription",
|
|
@@ -107,23 +111,35 @@ async function readPackageVersion() {
|
|
|
107
111
|
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
108
112
|
return packageJson.version ?? "0.0.0";
|
|
109
113
|
}
|
|
110
|
-
async function
|
|
114
|
+
async function collectInstallableTemplatePaths(dir, base) {
|
|
111
115
|
const dirStat = await stat(dir);
|
|
112
116
|
if (!dirStat.isDirectory()) {
|
|
113
117
|
throw new Error(`Bundled templates directory not found: ${templatesDir}`);
|
|
114
118
|
}
|
|
115
119
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
116
|
-
const
|
|
120
|
+
const discovered = [];
|
|
121
|
+
for (const entry of entries) {
|
|
117
122
|
const absolutePath = path.join(dir, entry.name);
|
|
118
123
|
if (entry.isDirectory()) {
|
|
119
|
-
|
|
124
|
+
if (dir === templatesDir && entry.name === "design-systems") {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
discovered.push(...(await collectInstallableTemplatePaths(absolutePath, base)));
|
|
128
|
+
continue;
|
|
120
129
|
}
|
|
121
130
|
if (!entry.isFile()) {
|
|
122
|
-
|
|
131
|
+
continue;
|
|
123
132
|
}
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
return
|
|
133
|
+
discovered.push(path.relative(base, absolutePath).split(path.sep).join("/"));
|
|
134
|
+
}
|
|
135
|
+
return discovered;
|
|
136
|
+
}
|
|
137
|
+
async function getTemplateFiles() {
|
|
138
|
+
const discovered = await collectInstallableTemplatePaths(templatesDir, templatesDir);
|
|
139
|
+
const withDesignSystem = discovered.includes("DESIGN-SYSTEM.md")
|
|
140
|
+
? discovered
|
|
141
|
+
: [...discovered, "DESIGN-SYSTEM.md"];
|
|
142
|
+
return withDesignSystem.sort();
|
|
127
143
|
}
|
|
128
144
|
function isPresetName(value) {
|
|
129
145
|
return validPresets.includes(value);
|
|
@@ -137,12 +153,32 @@ function isAiToolName(value) {
|
|
|
137
153
|
function isTemplateSetName(value) {
|
|
138
154
|
return validTemplateSets.includes(value);
|
|
139
155
|
}
|
|
156
|
+
function isDesignSystemName(value) {
|
|
157
|
+
return validDesignSystems.includes(value);
|
|
158
|
+
}
|
|
140
159
|
function formatPresetList() {
|
|
141
160
|
return validPresets.join(", ");
|
|
142
161
|
}
|
|
143
162
|
function formatTemplateSetList() {
|
|
144
163
|
return validTemplateSets.join(", ");
|
|
145
164
|
}
|
|
165
|
+
function formatDesignSystemList() {
|
|
166
|
+
return validDesignSystems.join(", ");
|
|
167
|
+
}
|
|
168
|
+
function resolveDesignSystem(name) {
|
|
169
|
+
const normalized = name.toLowerCase();
|
|
170
|
+
if (!isDesignSystemName(normalized)) {
|
|
171
|
+
throw new Error(`Unknown design system "${name}". Valid design systems: ${formatDesignSystemList()}.`);
|
|
172
|
+
}
|
|
173
|
+
return normalized;
|
|
174
|
+
}
|
|
175
|
+
function effectiveDesignSystem(name) {
|
|
176
|
+
const trimmed = name?.trim();
|
|
177
|
+
if (!trimmed) {
|
|
178
|
+
return "linear";
|
|
179
|
+
}
|
|
180
|
+
return resolveDesignSystem(trimmed);
|
|
181
|
+
}
|
|
146
182
|
function resolvePreset(preset) {
|
|
147
183
|
if (!preset) {
|
|
148
184
|
return undefined;
|
|
@@ -202,6 +238,12 @@ function parseConfig(rawConfig, configPath) {
|
|
|
202
238
|
return aiTool;
|
|
203
239
|
});
|
|
204
240
|
}
|
|
241
|
+
if (rawConfig.designSystem !== undefined) {
|
|
242
|
+
if (typeof rawConfig.designSystem !== "string") {
|
|
243
|
+
throw new Error(`${configFileName} designSystem must be a string.`);
|
|
244
|
+
}
|
|
245
|
+
config.designSystem = resolveDesignSystem(rawConfig.designSystem);
|
|
246
|
+
}
|
|
205
247
|
if (rawConfig.personalization !== undefined) {
|
|
206
248
|
assertPlainObject(rawConfig.personalization, `${configFileName} personalization`);
|
|
207
249
|
assertKnownKeys(rawConfig.personalization, personalizationKeys, `${configFileName} personalization`);
|
|
@@ -252,6 +294,7 @@ async function applyInitConfig(options, config) {
|
|
|
252
294
|
return;
|
|
253
295
|
}
|
|
254
296
|
options.preset ??= config.preset;
|
|
297
|
+
options.designSystem ??= config.designSystem;
|
|
255
298
|
options.personalization ??= config.personalization;
|
|
256
299
|
options.templateSet ??= config.templateSet;
|
|
257
300
|
options.aiTools ??= config.aiTools;
|
|
@@ -261,6 +304,7 @@ function applyUpdateConfig(options, config) {
|
|
|
261
304
|
return;
|
|
262
305
|
}
|
|
263
306
|
options.preset ??= config.preset;
|
|
307
|
+
options.designSystem ??= config.designSystem;
|
|
264
308
|
}
|
|
265
309
|
export function resolveProjectPreset(projectType) {
|
|
266
310
|
if (!projectType) {
|
|
@@ -328,6 +372,7 @@ function getResolvedConfig(options) {
|
|
|
328
372
|
const config = {
|
|
329
373
|
templateSet: options.templateSet ?? "full",
|
|
330
374
|
aiTools: options.aiTools ?? [],
|
|
375
|
+
designSystem: effectiveDesignSystem(options.designSystem),
|
|
331
376
|
};
|
|
332
377
|
const preset = resolvePreset(options.preset);
|
|
333
378
|
if (preset) {
|
|
@@ -532,8 +577,8 @@ async function promptForPersonalization(defaults) {
|
|
|
532
577
|
stackSummary,
|
|
533
578
|
};
|
|
534
579
|
}
|
|
535
|
-
async function buildInitTemplateContent(file, preset, personalization) {
|
|
536
|
-
const content = await buildTemplateContent(file, preset);
|
|
580
|
+
async function buildInitTemplateContent(file, preset, personalization, designSystem) {
|
|
581
|
+
const content = await buildTemplateContent(file, preset, designSystem);
|
|
537
582
|
return personalizeTemplateContent(file, content, personalization);
|
|
538
583
|
}
|
|
539
584
|
async function installTemplates(targetArg, options) {
|
|
@@ -544,6 +589,7 @@ async function installTemplates(targetArg, options) {
|
|
|
544
589
|
? getSelectedTemplateFiles(options.templateSet ?? "full", options.aiTools ?? [], allTemplateFiles)
|
|
545
590
|
: allTemplateFiles);
|
|
546
591
|
const preset = resolvePreset(options.preset);
|
|
592
|
+
const designSystem = effectiveDesignSystem(options.designSystem);
|
|
547
593
|
const created = [];
|
|
548
594
|
const skipped = [];
|
|
549
595
|
if (!options.dryRun) {
|
|
@@ -572,14 +618,8 @@ async function installTemplates(targetArg, options) {
|
|
|
572
618
|
created.push(file);
|
|
573
619
|
if (!options.dryRun) {
|
|
574
620
|
await mkdir(path.dirname(destination), { recursive: true });
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
await writeFile(destination, wrapManagedBlock(file, content));
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
const content = await buildInitTemplateContent(file, preset, options.personalization);
|
|
581
|
-
await writeFile(destination, wrapManagedBlock(file, content));
|
|
582
|
-
}
|
|
621
|
+
const content = await buildInitTemplateContent(file, preset, options.personalization, designSystem);
|
|
622
|
+
await writeFile(destination, wrapManagedBlock(file, content));
|
|
583
623
|
}
|
|
584
624
|
}
|
|
585
625
|
if (preset) {
|
|
@@ -614,13 +654,18 @@ function replaceManagedBlock(file, existingContent, nextContent) {
|
|
|
614
654
|
const replacement = wrapManagedBlock(file, nextContent).trimEnd();
|
|
615
655
|
return `${existingContent.slice(0, startIndex)}${replacement}${existingContent.slice(afterEndIndex)}`;
|
|
616
656
|
}
|
|
617
|
-
async function buildTemplateContent(file, preset) {
|
|
657
|
+
async function buildTemplateContent(file, preset, designSystem) {
|
|
618
658
|
if (file === "STACK.md") {
|
|
619
659
|
if (!preset) {
|
|
620
660
|
throw new Error("STACK.md requires a preset.");
|
|
621
661
|
}
|
|
622
662
|
return getStackGuidance(preset);
|
|
623
663
|
}
|
|
664
|
+
if (file === "DESIGN-SYSTEM.md") {
|
|
665
|
+
const source = path.join(templatesDir, "design-systems", `${designSystem}.md`);
|
|
666
|
+
const content = await readFile(source, "utf8");
|
|
667
|
+
return addStackReference(file, content, preset);
|
|
668
|
+
}
|
|
624
669
|
const source = path.join(templatesDir, file);
|
|
625
670
|
const content = await readFile(source, "utf8");
|
|
626
671
|
return addStackReference(file, content, preset);
|
|
@@ -628,6 +673,7 @@ async function buildTemplateContent(file, preset) {
|
|
|
628
673
|
async function updateTemplates(targetArg, options) {
|
|
629
674
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
630
675
|
const preset = resolvePreset(options.preset);
|
|
676
|
+
const designSystem = effectiveDesignSystem(options.designSystem);
|
|
631
677
|
const files = preset ? [...(await getTemplateFiles()), "STACK.md"] : await getTemplateFiles();
|
|
632
678
|
const created = [];
|
|
633
679
|
const updated = [];
|
|
@@ -636,7 +682,7 @@ async function updateTemplates(targetArg, options) {
|
|
|
636
682
|
const unchanged = [];
|
|
637
683
|
for (const file of files) {
|
|
638
684
|
const destination = path.join(targetDir, file);
|
|
639
|
-
const nextContent = await buildTemplateContent(file, preset);
|
|
685
|
+
const nextContent = await buildTemplateContent(file, preset, designSystem);
|
|
640
686
|
const destinationExists = await exists(destination);
|
|
641
687
|
if (!destinationExists) {
|
|
642
688
|
created.push(file);
|
|
@@ -777,6 +823,17 @@ async function resolveInteractiveTarget(target, options) {
|
|
|
777
823
|
options.templateSet = templateSetResponse;
|
|
778
824
|
options.aiTools = aiToolResponse;
|
|
779
825
|
options.files = getSelectedTemplateFiles(templateSetResponse, aiToolResponse, templateFiles);
|
|
826
|
+
if (templateSetResponse === "standard" || templateSetResponse === "full") {
|
|
827
|
+
const designSystemResponse = await select({
|
|
828
|
+
message: "Which design system guidance?",
|
|
829
|
+
initialValue: effectiveDesignSystem(options.designSystem),
|
|
830
|
+
options: validDesignSystems.map((value) => ({ label: designSystemLabels[value], value })),
|
|
831
|
+
});
|
|
832
|
+
if (isCancel(designSystemResponse)) {
|
|
833
|
+
process.exit(130);
|
|
834
|
+
}
|
|
835
|
+
options.designSystem = designSystemResponse;
|
|
836
|
+
}
|
|
780
837
|
if (!options.force) {
|
|
781
838
|
const preset = resolvePreset(options.preset);
|
|
782
839
|
const installFiles = preset ? [...options.files, "STACK.md"] : options.files;
|
|
@@ -819,6 +876,12 @@ async function main() {
|
|
|
819
876
|
}
|
|
820
877
|
return;
|
|
821
878
|
}
|
|
879
|
+
if (process.argv.slice(2).includes("--list-design-systems")) {
|
|
880
|
+
for (const designSystem of validDesignSystems) {
|
|
881
|
+
console.log(designSystem);
|
|
882
|
+
}
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
822
885
|
const program = new Command();
|
|
823
886
|
program
|
|
824
887
|
.name("agentkit")
|
|
@@ -826,6 +889,7 @@ async function main() {
|
|
|
826
889
|
.version(await readPackageVersion(), "-v, --version")
|
|
827
890
|
.option("--list", "list bundled template files")
|
|
828
891
|
.option("--list-presets", "list available presets")
|
|
892
|
+
.option("--list-design-systems", "list available design systems")
|
|
829
893
|
.addHelpText("after", `
|
|
830
894
|
|
|
831
895
|
Examples:
|
|
@@ -834,6 +898,7 @@ Examples:
|
|
|
834
898
|
agentkit init --preset next
|
|
835
899
|
agentkit init ./my-project --yes --dry-run
|
|
836
900
|
agentkit --list-presets
|
|
901
|
+
agentkit --list-design-systems
|
|
837
902
|
agentkit --list`);
|
|
838
903
|
program
|
|
839
904
|
.command("init")
|
|
@@ -845,6 +910,7 @@ Examples:
|
|
|
845
910
|
.option("-y, --yes", "accept defaults for non-interactive runs")
|
|
846
911
|
.option("--write-config", "write resolved install defaults to agentkit.config.json")
|
|
847
912
|
.option("--preset <name>", `install stack-specific guidance (${formatPresetList()})`)
|
|
913
|
+
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
848
914
|
.action(async (target, options) => {
|
|
849
915
|
await applyInitConfig(options, await loadConfigForTarget(target));
|
|
850
916
|
const resolvedTarget = await resolveInteractiveTarget(target, options);
|
|
@@ -857,6 +923,7 @@ Examples:
|
|
|
857
923
|
.argument("[target]", "target project directory", ".")
|
|
858
924
|
.option("--dry-run", "print planned changes without writing files")
|
|
859
925
|
.option("--preset <name>", `update stack-specific guidance (${formatPresetList()})`)
|
|
926
|
+
.option("--design-system <name>", `design system guidance for DESIGN-SYSTEM.md (${formatDesignSystemList()})`)
|
|
860
927
|
.action(async (target, options) => {
|
|
861
928
|
applyUpdateConfig(options, await loadConfigForTarget(target));
|
|
862
929
|
const result = await updateTemplates(target, options);
|
package/package.json
CHANGED
|
File without changes
|