thomas-agentkit 0.1.0 → 0.3.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/LICENSE +21 -0
- package/README.md +82 -1
- package/dist/cli.js +261 -3
- package/package.json +18 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Howard Thomas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -32,18 +32,42 @@ Overwrite existing files:
|
|
|
32
32
|
npx thomas-agentkit init --force
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Update AgentKit-managed template sections:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx thomas-agentkit update
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Preview updates without writing files:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx thomas-agentkit update --dry-run
|
|
45
|
+
```
|
|
46
|
+
|
|
35
47
|
Use the optional interactive flow:
|
|
36
48
|
|
|
37
49
|
```bash
|
|
38
50
|
npx thomas-agentkit init --interactive
|
|
39
51
|
```
|
|
40
52
|
|
|
53
|
+
Install stack-specific agent guidance:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx thomas-agentkit init --preset next
|
|
57
|
+
```
|
|
58
|
+
|
|
41
59
|
List bundled templates:
|
|
42
60
|
|
|
43
61
|
```bash
|
|
44
62
|
npx thomas-agentkit --list
|
|
45
63
|
```
|
|
46
64
|
|
|
65
|
+
List available presets:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx thomas-agentkit --list-presets
|
|
69
|
+
```
|
|
70
|
+
|
|
47
71
|
## Installed Files
|
|
48
72
|
|
|
49
73
|
AgentKit copies these bundled files into the target project:
|
|
@@ -59,13 +83,37 @@ AgentKit copies these bundled files into the target project:
|
|
|
59
83
|
- `.github/copilot-instructions.md`
|
|
60
84
|
- `.github/pull_request_template.md`
|
|
61
85
|
|
|
86
|
+
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.
|
|
87
|
+
|
|
62
88
|
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.
|
|
63
89
|
|
|
90
|
+
New installs wrap generated template content in AgentKit managed block markers:
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<!-- agentkit:start agents -->
|
|
94
|
+
Generated content
|
|
95
|
+
<!-- agentkit:end agents -->
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`agentkit update` only replaces content inside matching managed blocks. User edits before or after those blocks are preserved. Existing legacy files without managed blocks are reported as unmanaged and left untouched.
|
|
99
|
+
|
|
100
|
+
## Presets
|
|
101
|
+
|
|
102
|
+
Presets add stack-specific guidance without scaffolding framework app files.
|
|
103
|
+
|
|
104
|
+
- `next`
|
|
105
|
+
- `sveltekit`
|
|
106
|
+
- `express`
|
|
107
|
+
- `convex`
|
|
108
|
+
- `fullstack` (`Next.js` + `Convex`)
|
|
109
|
+
|
|
64
110
|
## CLI Reference
|
|
65
111
|
|
|
66
112
|
```text
|
|
67
|
-
agentkit init [target] [--force] [--dry-run] [--interactive] [--yes]
|
|
113
|
+
agentkit init [target] [--force] [--dry-run] [--interactive] [--yes] [--preset <name>]
|
|
114
|
+
agentkit update [target] [--dry-run] [--preset <name>]
|
|
68
115
|
agentkit --list
|
|
116
|
+
agentkit --list-presets
|
|
69
117
|
agentkit --help
|
|
70
118
|
agentkit --version
|
|
71
119
|
```
|
|
@@ -76,10 +124,14 @@ Options:
|
|
|
76
124
|
- `--dry-run`: print planned changes without writing files
|
|
77
125
|
- `-i, --interactive`: prompt for install options
|
|
78
126
|
- `-y, --yes`: accept defaults for non-interactive runs
|
|
127
|
+
- `--preset <name>`: install stack-specific guidance (`next`, `sveltekit`, `express`, `convex`, `fullstack`)
|
|
79
128
|
- `--list`: list bundled template files
|
|
129
|
+
- `--list-presets`: list available presets
|
|
80
130
|
- `-h, --help`: show help
|
|
81
131
|
- `-v, --version`: show package version
|
|
82
132
|
|
|
133
|
+
For `agentkit update`, `--preset <name>` refreshes preset-specific managed content, including `STACK.md`.
|
|
134
|
+
|
|
83
135
|
## Local Development
|
|
84
136
|
|
|
85
137
|
```bash
|
|
@@ -91,6 +143,35 @@ npm test
|
|
|
91
143
|
|
|
92
144
|
The npm package is `thomas-agentkit`. The installed CLI command is `agentkit`, backed by the compiled TypeScript entrypoint at `dist/cli.js`.
|
|
93
145
|
|
|
146
|
+
## Release
|
|
147
|
+
|
|
148
|
+
Before publishing a new package version:
|
|
149
|
+
|
|
150
|
+
1. Update the version in `package.json` intentionally.
|
|
151
|
+
2. Run the full test suite:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm test
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
3. Run the package build step:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm run prepack
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
4. Inspect the publish contents:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npm pack --dry-run
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
5. Publish to npm:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npm publish
|
|
173
|
+
```
|
|
174
|
+
|
|
94
175
|
## Philosophy
|
|
95
176
|
|
|
96
177
|
AgentKit should stay:
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { confirm, isCancel, text } from "@clack/prompts";
|
|
2
|
+
import { confirm, isCancel, select, text } from "@clack/prompts";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { constants as fsConstants } from "node:fs";
|
|
5
|
-
import { access,
|
|
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
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -10,6 +10,63 @@ const __dirname = path.dirname(__filename);
|
|
|
10
10
|
const packageRoot = path.resolve(__dirname, "..");
|
|
11
11
|
const templatesDir = path.join(packageRoot, "templates");
|
|
12
12
|
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
13
|
+
const validPresets = ["next", "sveltekit", "express", "convex", "fullstack"];
|
|
14
|
+
const presetLabels = {
|
|
15
|
+
next: "Next.js",
|
|
16
|
+
sveltekit: "SvelteKit",
|
|
17
|
+
express: "Express",
|
|
18
|
+
convex: "Convex",
|
|
19
|
+
fullstack: "Fullstack",
|
|
20
|
+
};
|
|
21
|
+
const stackGuidance = {
|
|
22
|
+
next: `# Stack Guidance
|
|
23
|
+
|
|
24
|
+
## Next.js
|
|
25
|
+
|
|
26
|
+
- Follow the app's existing routing model before adding new routes or layouts.
|
|
27
|
+
- Keep server and client component boundaries explicit.
|
|
28
|
+
- Prefer server components for data loading unless interactivity requires a client component.
|
|
29
|
+
- Keep mutations in server actions, route handlers, or existing API layers based on local patterns.
|
|
30
|
+
- Use established styling primitives and design tokens before adding new UI conventions.
|
|
31
|
+
- Validate external input at route, action, and API boundaries.
|
|
32
|
+
- Run the project's Next.js build or typecheck before handoff when touching routing, rendering, or data loading.
|
|
33
|
+
`,
|
|
34
|
+
sveltekit: `# Stack Guidance
|
|
35
|
+
|
|
36
|
+
## SvelteKit
|
|
37
|
+
|
|
38
|
+
- Follow the existing route, load, action, and server module patterns before adding new files.
|
|
39
|
+
- Keep browser-only code out of server load functions and server modules.
|
|
40
|
+
- Use SvelteKit form actions and load functions where they fit the workflow.
|
|
41
|
+
- Validate external input at action, endpoint, and server boundary entrypoints.
|
|
42
|
+
- Reuse existing stores, components, and styling conventions before creating new ones.
|
|
43
|
+
- Run the project's SvelteKit check or build before handoff when touching routes, rendering, or data loading.
|
|
44
|
+
`,
|
|
45
|
+
express: `# Stack Guidance
|
|
46
|
+
|
|
47
|
+
## Express
|
|
48
|
+
|
|
49
|
+
- Keep route handlers small and move repeated business logic only when duplication is real.
|
|
50
|
+
- Validate request params, query strings, and bodies at the route boundary.
|
|
51
|
+
- Return explicit status codes and predictable response shapes.
|
|
52
|
+
- Use the project's existing middleware order and error handling pattern.
|
|
53
|
+
- Avoid adding global middleware or dependencies for narrow endpoint changes.
|
|
54
|
+
- Add focused tests for route behavior, validation failures, and error paths.
|
|
55
|
+
`,
|
|
56
|
+
convex: `# Stack Guidance
|
|
57
|
+
|
|
58
|
+
## Convex
|
|
59
|
+
|
|
60
|
+
- Follow generated Convex types and local function patterns before editing schema or functions.
|
|
61
|
+
- Keep queries, mutations, and actions focused on one clear responsibility.
|
|
62
|
+
- Validate arguments with Convex validators at public function boundaries.
|
|
63
|
+
- Preserve explicit authorization checks for user-scoped data.
|
|
64
|
+
- Prefer indexes and schema changes that match real query needs.
|
|
65
|
+
- Run Convex codegen or the project's Convex validation command after schema or function changes.
|
|
66
|
+
`,
|
|
67
|
+
};
|
|
68
|
+
const fullstackGuidance = `${stackGuidance.next}
|
|
69
|
+
${stackGuidance.convex.replace("# Stack Guidance\n\n", "")}`;
|
|
13
70
|
async function exists(filePath) {
|
|
14
71
|
try {
|
|
15
72
|
await access(filePath, fsConstants.F_OK);
|
|
@@ -41,9 +98,52 @@ async function getTemplateFiles(dir = templatesDir, base = templatesDir) {
|
|
|
41
98
|
}));
|
|
42
99
|
return files.flat().sort();
|
|
43
100
|
}
|
|
101
|
+
function isPresetName(value) {
|
|
102
|
+
return validPresets.includes(value);
|
|
103
|
+
}
|
|
104
|
+
function formatPresetList() {
|
|
105
|
+
return validPresets.join(", ");
|
|
106
|
+
}
|
|
107
|
+
function resolvePreset(preset) {
|
|
108
|
+
if (!preset) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const normalizedPreset = preset.toLowerCase();
|
|
112
|
+
if (!isPresetName(normalizedPreset)) {
|
|
113
|
+
throw new Error(`Unknown preset "${preset}". Valid presets: ${formatPresetList()}.`);
|
|
114
|
+
}
|
|
115
|
+
return normalizedPreset;
|
|
116
|
+
}
|
|
117
|
+
function getStackGuidance(preset) {
|
|
118
|
+
return preset === "fullstack" ? fullstackGuidance : stackGuidance[preset];
|
|
119
|
+
}
|
|
120
|
+
function getTemplateId(file) {
|
|
121
|
+
return file
|
|
122
|
+
.replace(/\.[^/.]+$/, "")
|
|
123
|
+
.replace(/^\./, "")
|
|
124
|
+
.split("/")
|
|
125
|
+
.filter(Boolean)
|
|
126
|
+
.join("-")
|
|
127
|
+
.toLowerCase();
|
|
128
|
+
}
|
|
129
|
+
function wrapManagedBlock(file, content) {
|
|
130
|
+
const id = getTemplateId(file);
|
|
131
|
+
return `<!-- agentkit:start ${id} -->\n${content.trimEnd()}\n<!-- agentkit:end ${id} -->\n`;
|
|
132
|
+
}
|
|
133
|
+
function addStackReference(file, content, preset) {
|
|
134
|
+
if (file !== "AGENTS.md" || !preset) {
|
|
135
|
+
return content;
|
|
136
|
+
}
|
|
137
|
+
const stackNote = `\nPreset: ${presetLabels[preset]}. Agents must read \`STACK.md\` before changing stack-specific code.\n`;
|
|
138
|
+
if (content.includes("## Guidelines")) {
|
|
139
|
+
return content.replace("\n## Guidelines", `${stackNote}\n## Guidelines`);
|
|
140
|
+
}
|
|
141
|
+
return `${content.trimEnd()}\n${stackNote}`;
|
|
142
|
+
}
|
|
44
143
|
async function installTemplates(targetArg, options) {
|
|
45
144
|
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
46
145
|
const files = await getTemplateFiles();
|
|
146
|
+
const preset = resolvePreset(options.preset);
|
|
47
147
|
const created = [];
|
|
48
148
|
const skipped = [];
|
|
49
149
|
if (!options.dryRun) {
|
|
@@ -60,11 +160,104 @@ async function installTemplates(targetArg, options) {
|
|
|
60
160
|
created.push(file);
|
|
61
161
|
if (!options.dryRun) {
|
|
62
162
|
await mkdir(path.dirname(destination), { recursive: true });
|
|
63
|
-
|
|
163
|
+
if (preset && file === "AGENTS.md") {
|
|
164
|
+
const content = await readFile(source, "utf8");
|
|
165
|
+
await writeFile(destination, wrapManagedBlock(file, addStackReference(file, content, preset)));
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const content = await readFile(source, "utf8");
|
|
169
|
+
await writeFile(destination, wrapManagedBlock(file, content));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (preset) {
|
|
174
|
+
const stackFile = "STACK.md";
|
|
175
|
+
const destination = path.join(targetDir, stackFile);
|
|
176
|
+
const destinationExists = await exists(destination);
|
|
177
|
+
if (destinationExists && !options.force) {
|
|
178
|
+
skipped.push(stackFile);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
created.push(stackFile);
|
|
182
|
+
if (!options.dryRun) {
|
|
183
|
+
await writeFile(destination, wrapManagedBlock(stackFile, getStackGuidance(preset)));
|
|
184
|
+
}
|
|
64
185
|
}
|
|
65
186
|
}
|
|
66
187
|
return { targetDir, created, skipped };
|
|
67
188
|
}
|
|
189
|
+
function replaceManagedBlock(file, existingContent, nextContent) {
|
|
190
|
+
const id = getTemplateId(file);
|
|
191
|
+
const startMarker = `<!-- agentkit:start ${id} -->`;
|
|
192
|
+
const endMarker = `<!-- agentkit:end ${id} -->`;
|
|
193
|
+
const startIndex = existingContent.indexOf(startMarker);
|
|
194
|
+
const endIndex = existingContent.indexOf(endMarker);
|
|
195
|
+
if (startIndex === -1 && endIndex === -1) {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
199
|
+
throw new Error(`Malformed managed block in ${file}.`);
|
|
200
|
+
}
|
|
201
|
+
const afterEndIndex = endIndex + endMarker.length;
|
|
202
|
+
const replacement = wrapManagedBlock(file, nextContent).trimEnd();
|
|
203
|
+
return `${existingContent.slice(0, startIndex)}${replacement}${existingContent.slice(afterEndIndex)}`;
|
|
204
|
+
}
|
|
205
|
+
async function buildTemplateContent(file, preset) {
|
|
206
|
+
if (file === "STACK.md") {
|
|
207
|
+
if (!preset) {
|
|
208
|
+
throw new Error("STACK.md requires a preset.");
|
|
209
|
+
}
|
|
210
|
+
return getStackGuidance(preset);
|
|
211
|
+
}
|
|
212
|
+
const source = path.join(templatesDir, file);
|
|
213
|
+
const content = await readFile(source, "utf8");
|
|
214
|
+
return addStackReference(file, content, preset);
|
|
215
|
+
}
|
|
216
|
+
async function updateTemplates(targetArg, options) {
|
|
217
|
+
const targetDir = path.resolve(process.cwd(), targetArg || ".");
|
|
218
|
+
const preset = resolvePreset(options.preset);
|
|
219
|
+
const files = preset ? [...(await getTemplateFiles()), "STACK.md"] : await getTemplateFiles();
|
|
220
|
+
const created = [];
|
|
221
|
+
const updated = [];
|
|
222
|
+
const skipped = [];
|
|
223
|
+
const malformed = [];
|
|
224
|
+
const unchanged = [];
|
|
225
|
+
for (const file of files) {
|
|
226
|
+
const destination = path.join(targetDir, file);
|
|
227
|
+
const nextContent = await buildTemplateContent(file, preset);
|
|
228
|
+
const destinationExists = await exists(destination);
|
|
229
|
+
if (!destinationExists) {
|
|
230
|
+
created.push(file);
|
|
231
|
+
if (!options.dryRun) {
|
|
232
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
233
|
+
await writeFile(destination, wrapManagedBlock(file, nextContent));
|
|
234
|
+
}
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const existingContent = await readFile(destination, "utf8");
|
|
238
|
+
let updatedContent;
|
|
239
|
+
try {
|
|
240
|
+
updatedContent = replaceManagedBlock(file, existingContent, nextContent);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
malformed.push(file);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (updatedContent === undefined) {
|
|
247
|
+
skipped.push(file);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (updatedContent === existingContent) {
|
|
251
|
+
unchanged.push(file);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
updated.push(file);
|
|
255
|
+
if (!options.dryRun) {
|
|
256
|
+
await writeFile(destination, updatedContent);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { targetDir, created, updated, skipped, malformed, unchanged };
|
|
260
|
+
}
|
|
68
261
|
function printInstallResult(result, dryRun = false) {
|
|
69
262
|
const action = dryRun ? "Would install" : "Installed";
|
|
70
263
|
console.log(`${action} AgentKit files in ${result.targetDir}`);
|
|
@@ -79,7 +272,35 @@ function printInstallResult(result, dryRun = false) {
|
|
|
79
272
|
console.log("No bundled templates found.");
|
|
80
273
|
}
|
|
81
274
|
}
|
|
275
|
+
function printUpdateResult(result, dryRun = false) {
|
|
276
|
+
const action = dryRun ? "Would update" : "Updated";
|
|
277
|
+
console.log(`${action} AgentKit files in ${result.targetDir}`);
|
|
278
|
+
if (result.created.length > 0) {
|
|
279
|
+
console.log(`${dryRun ? "Would create" : "Created"}: ${result.created.join(", ")}`);
|
|
280
|
+
}
|
|
281
|
+
if (result.updated.length > 0) {
|
|
282
|
+
console.log(`${dryRun ? "Would update" : "Updated"}: ${result.updated.join(", ")}`);
|
|
283
|
+
}
|
|
284
|
+
if (result.unchanged.length > 0) {
|
|
285
|
+
console.log(`Already current: ${result.unchanged.join(", ")}`);
|
|
286
|
+
}
|
|
287
|
+
if (result.skipped.length > 0) {
|
|
288
|
+
console.log(`Skipped unmanaged: ${result.skipped.join(", ")}`);
|
|
289
|
+
console.log("Add AgentKit managed block markers before updating these files.");
|
|
290
|
+
}
|
|
291
|
+
if (result.malformed.length > 0) {
|
|
292
|
+
console.log(`Skipped malformed: ${result.malformed.join(", ")}`);
|
|
293
|
+
console.log("Fix AgentKit managed block markers before updating these files.");
|
|
294
|
+
}
|
|
295
|
+
if (result.created.length === 0 &&
|
|
296
|
+
result.updated.length === 0 &&
|
|
297
|
+
result.skipped.length === 0 &&
|
|
298
|
+
result.malformed.length === 0) {
|
|
299
|
+
console.log("All managed AgentKit files are current.");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
82
302
|
async function resolveInteractiveTarget(target, options) {
|
|
303
|
+
const providedPreset = resolvePreset(options.preset);
|
|
83
304
|
if (!options.interactive) {
|
|
84
305
|
return target;
|
|
85
306
|
}
|
|
@@ -98,6 +319,22 @@ async function resolveInteractiveTarget(target, options) {
|
|
|
98
319
|
if (isCancel(forceResponse)) {
|
|
99
320
|
process.exit(130);
|
|
100
321
|
}
|
|
322
|
+
const presetResponse = await select({
|
|
323
|
+
message: "Which preset should AgentKit use?",
|
|
324
|
+
initialValue: providedPreset || "generic",
|
|
325
|
+
options: [
|
|
326
|
+
{ label: "Generic", value: "generic" },
|
|
327
|
+
{ label: "Next.js", value: "next" },
|
|
328
|
+
{ label: "SvelteKit", value: "sveltekit" },
|
|
329
|
+
{ label: "Express", value: "express" },
|
|
330
|
+
{ label: "Convex", value: "convex" },
|
|
331
|
+
{ label: "Fullstack", value: "fullstack" },
|
|
332
|
+
],
|
|
333
|
+
});
|
|
334
|
+
if (isCancel(presetResponse)) {
|
|
335
|
+
process.exit(130);
|
|
336
|
+
}
|
|
337
|
+
options.preset = presetResponse === "generic" ? undefined : presetResponse;
|
|
101
338
|
options.force = forceResponse;
|
|
102
339
|
return targetResponse || ".";
|
|
103
340
|
}
|
|
@@ -109,17 +346,27 @@ async function main() {
|
|
|
109
346
|
}
|
|
110
347
|
return;
|
|
111
348
|
}
|
|
349
|
+
if (process.argv.slice(2).includes("--list-presets")) {
|
|
350
|
+
for (const preset of validPresets) {
|
|
351
|
+
console.log(preset);
|
|
352
|
+
}
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
112
355
|
const program = new Command();
|
|
113
356
|
program
|
|
114
357
|
.name("agentkit")
|
|
115
358
|
.description("Bootstrap AI-agent-ready repository docs and workflow templates.")
|
|
116
359
|
.version(await readPackageVersion(), "-v, --version")
|
|
117
360
|
.option("--list", "list bundled template files")
|
|
361
|
+
.option("--list-presets", "list available presets")
|
|
118
362
|
.addHelpText("after", `
|
|
119
363
|
|
|
120
364
|
Examples:
|
|
121
365
|
agentkit init
|
|
366
|
+
agentkit update
|
|
367
|
+
agentkit init --preset next
|
|
122
368
|
agentkit init ./my-project --dry-run
|
|
369
|
+
agentkit --list-presets
|
|
123
370
|
agentkit --list`);
|
|
124
371
|
program
|
|
125
372
|
.command("init")
|
|
@@ -129,11 +376,22 @@ Examples:
|
|
|
129
376
|
.option("--dry-run", "print planned changes without writing files")
|
|
130
377
|
.option("-i, --interactive", "prompt for install options")
|
|
131
378
|
.option("-y, --yes", "accept defaults for non-interactive runs")
|
|
379
|
+
.option("--preset <name>", `install stack-specific guidance (${formatPresetList()})`)
|
|
132
380
|
.action(async (target, options) => {
|
|
133
381
|
const resolvedTarget = await resolveInteractiveTarget(target, options);
|
|
134
382
|
const result = await installTemplates(resolvedTarget, options);
|
|
135
383
|
printInstallResult(result, Boolean(options.dryRun));
|
|
136
384
|
});
|
|
385
|
+
program
|
|
386
|
+
.command("update")
|
|
387
|
+
.description("update AgentKit managed template blocks in a project")
|
|
388
|
+
.argument("[target]", "target project directory", ".")
|
|
389
|
+
.option("--dry-run", "print planned changes without writing files")
|
|
390
|
+
.option("--preset <name>", `update stack-specific guidance (${formatPresetList()})`)
|
|
391
|
+
.action(async (target, options) => {
|
|
392
|
+
const result = await updateTemplates(target, options);
|
|
393
|
+
printUpdateResult(result, Boolean(options.dryRun));
|
|
394
|
+
});
|
|
137
395
|
await program.parseAsync(process.argv);
|
|
138
396
|
}
|
|
139
397
|
main().catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thomas-agentkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Install AI-agent-ready development templates into a project.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/howie1329/Howard-AgentKit.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/howie1329/Howard-AgentKit#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/howie1329/Howard-AgentKit/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"agentkit",
|
|
16
|
+
"ai",
|
|
17
|
+
"agents",
|
|
18
|
+
"codex",
|
|
19
|
+
"cli",
|
|
20
|
+
"scaffolding",
|
|
21
|
+
"templates"
|
|
22
|
+
],
|
|
6
23
|
"type": "module",
|
|
7
24
|
"bin": {
|
|
8
25
|
"agentkit": "./dist/cli.js"
|