argsbarg 6.1.10 → 6.2.2
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/CHANGELOG.md +22 -1
- package/README.md +49 -49
- package/docs/README.md +5 -4
- package/docs/ai-skills.md +36 -23
- package/docs/bundled-docs.md +1 -1
- package/docs/cli-program.md +19 -20
- package/docs/config-schema.md +3 -3
- package/docs/configure.md +12 -16
- package/docs/developing.md +9 -9
- package/docs/mcp.md +21 -57
- package/docs/output-schema.md +3 -3
- package/examples/formats.ts +5 -6
- package/examples/full-example/AGENTS.md +75 -0
- package/examples/full-example/CLAUDE.md +1 -0
- package/examples/full-example/README.md +7 -69
- package/examples/full-example/docs/README.md +1 -1
- package/examples/full-example/docs/cli-schema.json +1 -1659
- package/examples/full-example/docs/cli.md +2 -1538
- package/examples/full-example/docs/http.md +0 -7
- package/examples/full-example/docs/mcp.md +23 -59
- package/examples/full-example/docs/openapi.json +2 -782
- package/examples/full-example/docs/skill.md +18 -14
- package/examples/full-example/justfile +5 -17
- package/examples/full-example/scripts/create-identity.ts +2 -1
- package/examples/full-example/src/commands/status/command.test.ts +2 -2
- package/examples/full-example/src/commands/status/command.ts +7 -6
- package/examples/full-example/src/program.ts +4 -10
- package/examples/full-example-json/AGENTS.md +86 -0
- package/examples/full-example-json/CLAUDE.md +1 -0
- package/examples/full-example-json/Formula/.gitkeep +0 -0
- package/examples/full-example-json/Formula/full-example-json.rb +35 -0
- package/examples/full-example-json/README.md +27 -0
- package/examples/full-example-json/biome.json +22 -0
- package/examples/full-example-json/bun.lock +48 -0
- package/examples/full-example-json/docs/README.md +27 -0
- package/examples/full-example-json/docs/cli-schema.json +2145 -0
- package/examples/full-example-json/docs/cli.md +1990 -0
- package/examples/full-example-json/docs/http.md +92 -0
- package/examples/full-example-json/docs/mcp.md +116 -0
- package/examples/full-example-json/docs/openapi.json +1246 -0
- package/examples/full-example-json/docs/skill.md +57 -0
- package/examples/full-example-json/justfile +171 -0
- package/examples/full-example-json/package.json +22 -0
- package/examples/full-example-json/scripts/create-identity.ts +12 -0
- package/examples/full-example-json/scripts/dev-formula.ts +97 -0
- package/examples/full-example-json/scripts/formula-shared.test.ts +68 -0
- package/examples/full-example-json/scripts/formula-shared.ts +170 -0
- package/examples/full-example-json/scripts/print-identity.ts +28 -0
- package/examples/full-example-json/scripts/release.ts +212 -0
- package/examples/full-example-json/src/commands/echo/command.ts +26 -0
- package/examples/full-example-json/src/commands/status/command.test.ts +10 -0
- package/examples/full-example-json/src/commands/status/command.ts +28 -0
- package/examples/full-example-json/src/index.ts +10 -0
- package/examples/full-example-json/src/program.ts +33 -0
- package/examples/full-example-json/src/types/md.d.ts +4 -0
- package/examples/full-example-json/tsconfig.json +17 -0
- package/examples/minimal.ts +17 -17
- package/examples/nested.ts +10 -10
- package/examples/option-required.ts +13 -13
- package/examples/servers.ts +10 -10
- package/index.d.ts +17 -43
- package/package.json +1 -1
- package/src/cli-tool/create.test.ts +44 -68
- package/src/cli-tool/create.ts +81 -17
- package/src/cli-tool/full-example-capabilities.test.ts +33 -18
- package/src/cli-tool/post-create.ts +31 -17
- package/src/cli-tool/program.ts +16 -7
- package/src/cli-tool/prompt.ts +27 -0
- package/src/cli-tool/run-create.ts +19 -7
- package/src/cli-tool/schemagen/schemagen.test.ts +3 -3
- package/src/configure/artifacts/install-validate.test.ts +20 -33
- package/src/configure/artifacts/paths.ts +9 -53
- package/src/configure/artifacts/status.test.ts +13 -16
- package/src/configure/artifacts/status.ts +5 -22
- package/src/configure/artifacts/target-base.ts +6 -15
- package/src/configure/artifacts/target-effective.ts +16 -54
- package/src/configure/artifacts/target-mcp-json.ts +2 -5
- package/src/configure/artifacts/target-registry.ts +0 -7
- package/src/configure/artifacts/target-scope.ts +7 -17
- package/src/configure/artifacts/target-skill.ts +6 -15
- package/src/configure/artifacts/target-types.ts +6 -54
- package/src/configure/artifacts/targets/agents-mcp.ts +11 -0
- package/src/configure/artifacts/targets/configure.ts +1 -5
- package/src/configure/artifacts/targets/index.ts +4 -44
- package/src/configure/artifacts/targets/skill.ts +12 -0
- package/src/configure/artifacts/targets.test.ts +21 -59
- package/src/configure/configure.test.ts +35 -46
- package/src/configure/index.ts +19 -19
- package/src/configure/prompt.ts +2 -12
- package/src/core/parse.test.ts +21 -32
- package/src/core/types.ts +18 -44
- package/src/core/validate.ts +28 -45
- package/src/docs/docs.test.ts +4 -4
- package/src/docs/mcp-guide.ts +41 -71
- package/src/docs/resolve.ts +1 -1
- package/src/exports/cli.ts +1 -1
- package/src/index.ts +1 -1
- package/src/skill/generate.ts +26 -45
- package/src/skill/install.ts +18 -38
- package/src/skill/naming.ts +3 -27
- package/src/test/integration/config.test.ts +3 -3
- package/src/test/integration/mcp.test.ts +4 -4
- package/{examples/mcp-test.ts → src/test/mcp-integration-fixture.ts} +20 -22
- package/src/configure/artifacts/target-mcp-cli.ts +0 -127
- package/src/configure/artifacts/targets/chatgpt-mcp.ts +0 -12
- package/src/configure/artifacts/targets/claude-code-mcp.ts +0 -15
- package/src/configure/artifacts/targets/claude-desktop-mcp.ts +0 -12
- package/src/configure/artifacts/targets/claude-skill.ts +0 -16
- package/src/configure/artifacts/targets/codex-mcp.ts +0 -25
- package/src/configure/artifacts/targets/codex-skill.ts +0 -14
- package/src/configure/artifacts/targets/cursor-mcp.ts +0 -15
- package/src/configure/artifacts/targets/cursor-skill.ts +0 -16
- package/src/configure/artifacts/targets/openclaw-mcp.ts +0 -25
- package/src/configure/artifacts/targets/openclaw-skill.ts +0 -17
- package/src/configure/artifacts/targets/opencode-mcp.ts +0 -96
- package/src/configure/artifacts/targets/opencode-skill.ts +0 -15
- /package/examples/{full-example → full-example-json}/src/commands/render-json/__generated__/RenderJsonInputSchema.json +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/render-json/__generated__/index.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/render-json/command.test.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/render-json/command.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/render-json/types.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/status/__generated__/StatusJsonOutputSchema.json +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/status/__generated__/index.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/status/types.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/workspaces/__generated__/index.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/workspaces/command.test.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/workspaces/command.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/commands/workspaces/types.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/db/index.test.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/db/index.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/db/migrate.test.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/db/migrate.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/db/migrations/001_workspaces.sql +0 -0
- /package/examples/{full-example → full-example-json}/src/db/tables/workspaces.ts +0 -0
- /package/examples/{full-example → full-example-json}/src/types/argsbarg.d.ts +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/** Bump version, build, publish zip release; optional `--purge` to drop stale GitHub releases. */
|
|
3
|
+
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
6
|
+
import * as readline from "node:readline/promises";
|
|
7
|
+
import { $ } from "bun";
|
|
8
|
+
import { createIdentity } from "./create-identity.ts";
|
|
9
|
+
import {
|
|
10
|
+
buildReleaseArchive,
|
|
11
|
+
type ReleaseTag,
|
|
12
|
+
releaseRepoSlug,
|
|
13
|
+
renderReleaseFormula,
|
|
14
|
+
selectStaleReleaseTags,
|
|
15
|
+
} from "./formula-shared.ts";
|
|
16
|
+
|
|
17
|
+
const { key } = createIdentity;
|
|
18
|
+
const formulaPath = `Formula/${key}.rb`;
|
|
19
|
+
const binaryPath = `dist/${key}`;
|
|
20
|
+
const programPath = "src/program.ts";
|
|
21
|
+
|
|
22
|
+
/** Allowed semver bump kinds for `scripts/release.ts`. */
|
|
23
|
+
type Bump = "major" | "minor" | "patch";
|
|
24
|
+
|
|
25
|
+
interface ReleaseOptions {
|
|
26
|
+
bump?: Bump;
|
|
27
|
+
purge: boolean;
|
|
28
|
+
yes: boolean;
|
|
29
|
+
dryRun: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Entry point: release bump, purge-only, or release then purge. */
|
|
33
|
+
async function main(): Promise<void> {
|
|
34
|
+
const options = parseOptions(process.argv.slice(2));
|
|
35
|
+
if (options.purge && !options.bump) {
|
|
36
|
+
await purgeStaleReleases(options);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!options.bump) {
|
|
40
|
+
usage();
|
|
41
|
+
}
|
|
42
|
+
await runRelease(options.bump, options);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Prints usage and exits. */
|
|
46
|
+
function usage(): never {
|
|
47
|
+
process.stderr.write(
|
|
48
|
+
"Usage:\n" +
|
|
49
|
+
" bun scripts/release.ts <major|minor|patch> [--purge]\n" +
|
|
50
|
+
" bun scripts/release.ts --purge [--yes] [--dry-run]\n",
|
|
51
|
+
);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Parses argv into release options. */
|
|
56
|
+
function parseOptions(argv: string[]): ReleaseOptions {
|
|
57
|
+
const yes = argv.includes("--yes");
|
|
58
|
+
const dryRun = argv.includes("--dry-run");
|
|
59
|
+
const purge = argv.includes("--purge");
|
|
60
|
+
const bump = argv.find((a): a is Bump => a === "major" || a === "minor" || a === "patch");
|
|
61
|
+
for (const arg of argv) {
|
|
62
|
+
if (arg.startsWith("--") && arg !== "--purge" && arg !== "--yes" && arg !== "--dry-run") {
|
|
63
|
+
usage();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!purge && !bump) {
|
|
67
|
+
usage();
|
|
68
|
+
}
|
|
69
|
+
return { bump, purge, yes, dryRun };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Full release pipeline for a semver bump. */
|
|
73
|
+
async function runRelease(bump: Bump, options: ReleaseOptions): Promise<void> {
|
|
74
|
+
const testResult = await $`just test`.nothrow();
|
|
75
|
+
if (testResult.exitCode !== 0) process.exit(testResult.exitCode);
|
|
76
|
+
|
|
77
|
+
const currentVersion = readCurrentVersion();
|
|
78
|
+
const newVersion = applyBump(currentVersion, bump);
|
|
79
|
+
console.log(`Releasing ${currentVersion} → ${newVersion}`);
|
|
80
|
+
|
|
81
|
+
updateVersion(newVersion);
|
|
82
|
+
updateChangelog(newVersion);
|
|
83
|
+
|
|
84
|
+
const buildResult = await $`just build`.nothrow();
|
|
85
|
+
if (buildResult.exitCode !== 0) process.exit(buildResult.exitCode);
|
|
86
|
+
|
|
87
|
+
const archivePath = await updateReleaseFormula(newVersion);
|
|
88
|
+
|
|
89
|
+
const docgenResult = await $`just docgen`.nothrow();
|
|
90
|
+
if (docgenResult.exitCode !== 0) process.exit(docgenResult.exitCode);
|
|
91
|
+
|
|
92
|
+
await commitAndTag(newVersion);
|
|
93
|
+
await createGithubRelease(`v${newVersion}`, archivePath);
|
|
94
|
+
|
|
95
|
+
console.log(`Released v${newVersion}`);
|
|
96
|
+
|
|
97
|
+
if (options.purge) {
|
|
98
|
+
await purgeStaleReleases(options);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Applies a semver bump to `current` and returns the new version string. */
|
|
103
|
+
function applyBump(current: string, bump: Bump): string {
|
|
104
|
+
const [major, minor, patch] = current.split(".").map(Number) as [number, number, number];
|
|
105
|
+
if (bump === "major") return `${major + 1}.0.0`;
|
|
106
|
+
if (bump === "minor") return `${major}.${minor + 1}.0`;
|
|
107
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Commits all staged changes, creates an annotated tag, and pushes both to origin. */
|
|
111
|
+
async function commitAndTag(newVersion: string): Promise<void> {
|
|
112
|
+
await $`git add -A`;
|
|
113
|
+
await $`git commit -m ${`chore: release v${newVersion}`}`;
|
|
114
|
+
await $`git tag v${newVersion}`;
|
|
115
|
+
await $`git push`;
|
|
116
|
+
await $`git push origin v${newVersion}`;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Creates a GitHub release for `tag` with the zip archive attached. */
|
|
120
|
+
async function createGithubRelease(tag: string, archivePath: string): Promise<void> {
|
|
121
|
+
await $`gh release create ${tag} ${archivePath} --title ${tag} --generate-notes`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Reads the CLI version from `src/program.ts`. */
|
|
125
|
+
function readCurrentVersion(): string {
|
|
126
|
+
const content = fs.readFileSync(programPath, "utf-8");
|
|
127
|
+
const match = /version:\s*"([^"]+)"/.exec(content);
|
|
128
|
+
if (!match) {
|
|
129
|
+
process.stderr.write(`Could not read version from ${programPath}\n`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
const version = match[1];
|
|
133
|
+
if (!version) {
|
|
134
|
+
process.stderr.write(`Could not read version from ${programPath}\n`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
const parts = version.split(".").map(Number);
|
|
138
|
+
if (parts.length !== 3 || parts.some(Number.isNaN)) {
|
|
139
|
+
process.stderr.write(`Invalid semver in ${programPath}: ${version}\n`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
return version;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Promotes `[Unreleased]` to a dated version section in `CHANGELOG.md`. */
|
|
146
|
+
function updateChangelog(newVersion: string): void {
|
|
147
|
+
const changelogPath = "CHANGELOG.md";
|
|
148
|
+
const content = fs.readFileSync(changelogPath, "utf-8");
|
|
149
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
150
|
+
fs.writeFileSync(
|
|
151
|
+
changelogPath,
|
|
152
|
+
content.replace(/^## \[Unreleased\]/m, `## [Unreleased]\n\n## [${newVersion}] - ${date}`),
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Overwrites the version literal in `src/program.ts`. */
|
|
157
|
+
function updateVersion(newVersion: string): void {
|
|
158
|
+
const content = fs.readFileSync(programPath, "utf-8");
|
|
159
|
+
fs.writeFileSync(programPath, content.replace(/version:\s*"[^"]+"/, `version: "${newVersion}"`));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Writes the release formula with zip URL and archive sha256; returns the archive path. */
|
|
163
|
+
async function updateReleaseFormula(version: string): Promise<string> {
|
|
164
|
+
const { archivePath, sha256 } = await buildReleaseArchive(binaryPath);
|
|
165
|
+
fs.writeFileSync(formulaPath, renderReleaseFormula(version, sha256));
|
|
166
|
+
return archivePath;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Deletes all GitHub releases except the most recent. */
|
|
170
|
+
async function purgeStaleReleases(options: ReleaseOptions): Promise<void> {
|
|
171
|
+
const list = await $`gh release list -R ${releaseRepoSlug} --json tagName,publishedAt`.nothrow();
|
|
172
|
+
if (list.exitCode !== 0) process.exit(list.exitCode);
|
|
173
|
+
|
|
174
|
+
const releases = JSON.parse(list.stdout.toString()) as ReleaseTag[];
|
|
175
|
+
const toDelete = selectStaleReleaseTags(releases);
|
|
176
|
+
|
|
177
|
+
if (toDelete.length === 0) {
|
|
178
|
+
console.log("No stale releases to delete.");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log(`Will delete ${toDelete.length} release(s):`);
|
|
183
|
+
for (const tag of toDelete) {
|
|
184
|
+
console.log(` ${tag}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (options.dryRun) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!options.yes) {
|
|
192
|
+
if (!input.isTTY) {
|
|
193
|
+
process.stderr.write("Not a TTY; pass --yes to confirm purge.\n");
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
const rl = readline.createInterface({ input, output });
|
|
197
|
+
const answer = await rl.question("Delete these releases? [y/N] ");
|
|
198
|
+
rl.close();
|
|
199
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
200
|
+
console.log("Aborted.");
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (const tag of toDelete) {
|
|
206
|
+
const del = await $`gh release delete ${tag} -R ${releaseRepoSlug} --yes`.nothrow();
|
|
207
|
+
if (del.exitCode !== 0) process.exit(del.exitCode);
|
|
208
|
+
console.log(`Deleted ${tag}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
await main();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Echo leaf — minimal MCP-friendly command.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type CliLeaf, CliOptionKind } from "argsbarg";
|
|
6
|
+
|
|
7
|
+
export const echoCommand = {
|
|
8
|
+
key: "echo",
|
|
9
|
+
description: "Echo a message (MCP-friendly leaf).",
|
|
10
|
+
options: [
|
|
11
|
+
{
|
|
12
|
+
name: "message",
|
|
13
|
+
description: "Text to print.",
|
|
14
|
+
kind: CliOptionKind.String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
handler: (ctx) => {
|
|
19
|
+
const message = ctx.stringOpt("message") ?? "";
|
|
20
|
+
if (ctx.invocation === "cli") {
|
|
21
|
+
console.log(message);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
return message;
|
|
25
|
+
},
|
|
26
|
+
} satisfies CliLeaf;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { statusCommand } from "./command.ts";
|
|
3
|
+
|
|
4
|
+
describe("status command", () => {
|
|
5
|
+
test("exports outputSchema and json option", () => {
|
|
6
|
+
expect(statusCommand.key).toBe("status");
|
|
7
|
+
expect(statusCommand.outputSchema).toBeDefined();
|
|
8
|
+
expect(statusCommand.options?.some((o) => o.name === "json")).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Status leaf — demonstrates outputSchema.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type CliLeaf, CliOptionKind } from "argsbarg";
|
|
6
|
+
import { StatusJsonOutputSchema } from "./__generated__";
|
|
7
|
+
import type { StatusJsonOutput } from "./types.ts";
|
|
8
|
+
|
|
9
|
+
export const statusCommand = {
|
|
10
|
+
key: "status",
|
|
11
|
+
description: "Show app version.",
|
|
12
|
+
options: [
|
|
13
|
+
{
|
|
14
|
+
name: "json",
|
|
15
|
+
description: "Emit JSON.",
|
|
16
|
+
kind: CliOptionKind.Presence,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
outputSchema: StatusJsonOutputSchema,
|
|
20
|
+
handler: (ctx) => {
|
|
21
|
+
const out: StatusJsonOutput = { version: ctx.program.version };
|
|
22
|
+
if (ctx.hasFlag("json")) {
|
|
23
|
+
console.log(JSON.stringify(out, null, 2));
|
|
24
|
+
} else {
|
|
25
|
+
console.log(`version=${out.version}`);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
} satisfies CliLeaf;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Reference CliProgram — builtins on; command registration only.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CliProgram } from "argsbarg";
|
|
6
|
+
import readmeText from "../README.md" with { type: "text" };
|
|
7
|
+
import { createIdentity } from "../scripts/create-identity.ts";
|
|
8
|
+
import { echoCommand } from "./commands/echo/command.ts";
|
|
9
|
+
import { renderJsonCommand } from "./commands/render-json/command.ts";
|
|
10
|
+
import { statusCommand } from "./commands/status/command.ts";
|
|
11
|
+
import { workspacesCommand } from "./commands/workspaces/command.ts";
|
|
12
|
+
import { AppDb } from "./db";
|
|
13
|
+
|
|
14
|
+
export const program = {
|
|
15
|
+
commands: [echoCommand, renderJsonCommand, statusCommand, workspacesCommand],
|
|
16
|
+
description: createIdentity.desc,
|
|
17
|
+
docs: {
|
|
18
|
+
topics: {
|
|
19
|
+
readme: {
|
|
20
|
+
text: readmeText,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
hooks: {
|
|
25
|
+
beforeInvoke: AppDb.attach,
|
|
26
|
+
},
|
|
27
|
+
httpServer: { enabled: true },
|
|
28
|
+
key: createIdentity.key,
|
|
29
|
+
mcpServer: { enabled: true },
|
|
30
|
+
readiness: AppDb.checkReadiness,
|
|
31
|
+
skill: { enabled: true },
|
|
32
|
+
version: "1.0.0",
|
|
33
|
+
} satisfies CliProgram;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"allowImportingTsExtensions": true,
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"types": ["bun"],
|
|
12
|
+
"paths": {
|
|
13
|
+
"~/*": ["./src/*"]
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts", "src/**/*.d.ts", "scripts/**/*.ts"]
|
|
17
|
+
}
|
package/examples/minimal.ts
CHANGED
|
@@ -11,9 +11,23 @@ import pkg from "../package.json" with { type: "json" };
|
|
|
11
11
|
import { Cli, CliOptionKind, type CliProgram } from "../src/index";
|
|
12
12
|
|
|
13
13
|
const program = {
|
|
14
|
-
key: "minimal.ts",
|
|
15
|
-
version: pkg.version,
|
|
16
14
|
description: "Tiny demo.",
|
|
15
|
+
handler: (ctx) => {
|
|
16
|
+
const name = ctx.args[0] ?? "world";
|
|
17
|
+
if (ctx.hasFlag("verbose")) {
|
|
18
|
+
console.log("verbose mode");
|
|
19
|
+
}
|
|
20
|
+
console.log(`hello ${name}`);
|
|
21
|
+
},
|
|
22
|
+
key: "minimal.ts",
|
|
23
|
+
options: [
|
|
24
|
+
{
|
|
25
|
+
name: "verbose",
|
|
26
|
+
description: "Enable extra logging.",
|
|
27
|
+
kind: CliOptionKind.Presence,
|
|
28
|
+
shortName: "v",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
17
31
|
positionals: [
|
|
18
32
|
{
|
|
19
33
|
name: "name",
|
|
@@ -23,21 +37,7 @@ const program = {
|
|
|
23
37
|
argMax: 1,
|
|
24
38
|
},
|
|
25
39
|
],
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
name: "verbose",
|
|
29
|
-
description: "Enable extra logging.",
|
|
30
|
-
kind: CliOptionKind.Presence,
|
|
31
|
-
shortName: "v",
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
handler: (ctx) => {
|
|
35
|
-
const name = ctx.args[0] ?? "world";
|
|
36
|
-
if (ctx.hasFlag("verbose")) {
|
|
37
|
-
console.log("verbose mode");
|
|
38
|
-
}
|
|
39
|
-
console.log(`hello ${name}`);
|
|
40
|
-
},
|
|
40
|
+
version: pkg.version,
|
|
41
41
|
} satisfies CliProgram;
|
|
42
42
|
|
|
43
43
|
const cli = new Cli(program);
|
package/examples/nested.ts
CHANGED
|
@@ -11,16 +11,6 @@ import pkg from "../package.json" with { type: "json" };
|
|
|
11
11
|
import { Cli, CliFallbackMode, CliOptionKind, type CliProgram } from "../src/index";
|
|
12
12
|
|
|
13
13
|
const program = {
|
|
14
|
-
key: "nested.ts",
|
|
15
|
-
version: pkg.version,
|
|
16
|
-
description: "Nested groups demo.",
|
|
17
|
-
mcpServer: { enabled: true },
|
|
18
|
-
docs: {
|
|
19
|
-
topics: {
|
|
20
|
-
readme: { text: "# nested.ts\n\nNested groups demo.\n" },
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
configure: {},
|
|
24
14
|
commands: [
|
|
25
15
|
{
|
|
26
16
|
key: "stat",
|
|
@@ -112,8 +102,18 @@ const program = {
|
|
|
112
102
|
},
|
|
113
103
|
},
|
|
114
104
|
],
|
|
105
|
+
configure: {},
|
|
106
|
+
description: "Nested groups demo.",
|
|
107
|
+
docs: {
|
|
108
|
+
topics: {
|
|
109
|
+
readme: { text: "# nested.ts\n\nNested groups demo.\n" },
|
|
110
|
+
},
|
|
111
|
+
},
|
|
115
112
|
fallbackCommand: "read",
|
|
116
113
|
fallbackMode: CliFallbackMode.MissingOrUnknown,
|
|
114
|
+
key: "nested.ts",
|
|
115
|
+
mcpServer: { enabled: true },
|
|
116
|
+
version: pkg.version,
|
|
117
117
|
} satisfies CliProgram;
|
|
118
118
|
|
|
119
119
|
const cli = new Cli(program);
|
|
@@ -11,9 +11,19 @@ import pkg from "../package.json" with { type: "json" };
|
|
|
11
11
|
import { Cli, CliOptionKind, type CliProgram, isInteractiveTty } from "../src/index";
|
|
12
12
|
|
|
13
13
|
const program = {
|
|
14
|
-
key: "option-required.ts",
|
|
15
|
-
version: pkg.version,
|
|
16
14
|
description: "Demo of a required option.",
|
|
15
|
+
handler: (ctx) => {
|
|
16
|
+
const requiredAlways = ctx.stringOpt("requiredAlways");
|
|
17
|
+
if (requiredAlways === undefined) {
|
|
18
|
+
throw new Error("requiredAlways missing after validation");
|
|
19
|
+
}
|
|
20
|
+
const requiredNonTty = ctx.stringOpt("requiredNonTty") ?? "valueWhenOmitted";
|
|
21
|
+
const optional = ctx.stringOpt("optional") ?? "valueWhenOmitted";
|
|
22
|
+
console.log(`requiredAlways: ${requiredAlways}`);
|
|
23
|
+
console.log(`requiredNonTty: ${requiredNonTty}`);
|
|
24
|
+
console.log(`optional: ${optional}`);
|
|
25
|
+
},
|
|
26
|
+
key: "option-required.ts",
|
|
17
27
|
options: [
|
|
18
28
|
{
|
|
19
29
|
name: "requiredAlways",
|
|
@@ -36,17 +46,7 @@ const program = {
|
|
|
36
46
|
shortName: "o",
|
|
37
47
|
},
|
|
38
48
|
],
|
|
39
|
-
|
|
40
|
-
const requiredAlways = ctx.stringOpt("requiredAlways");
|
|
41
|
-
if (requiredAlways === undefined) {
|
|
42
|
-
throw new Error("requiredAlways missing after validation");
|
|
43
|
-
}
|
|
44
|
-
const requiredNonTty = ctx.stringOpt("requiredNonTty") ?? "valueWhenOmitted";
|
|
45
|
-
const optional = ctx.stringOpt("optional") ?? "valueWhenOmitted";
|
|
46
|
-
console.log(`requiredAlways: ${requiredAlways}`);
|
|
47
|
-
console.log(`requiredNonTty: ${requiredNonTty}`);
|
|
48
|
-
console.log(`optional: ${optional}`);
|
|
49
|
-
},
|
|
49
|
+
version: pkg.version,
|
|
50
50
|
} satisfies CliProgram;
|
|
51
51
|
|
|
52
52
|
const cli = new Cli(program);
|
package/examples/servers.ts
CHANGED
|
@@ -20,16 +20,6 @@ import pkg from "../package.json" with { type: "json" };
|
|
|
20
20
|
import { Cli, CliOptionKind, type CliProgram } from "../src/index";
|
|
21
21
|
|
|
22
22
|
const program = {
|
|
23
|
-
key: "servers.ts",
|
|
24
|
-
version: pkg.version,
|
|
25
|
-
description: "Tiny demo.",
|
|
26
|
-
mcpServer: { enabled: true },
|
|
27
|
-
httpServer: { enabled: true },
|
|
28
|
-
docs: {
|
|
29
|
-
topics: {
|
|
30
|
-
readme: { text: "# servers.ts\n\nServers demo.\n" },
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
23
|
commands: [
|
|
34
24
|
{
|
|
35
25
|
key: "hello",
|
|
@@ -65,6 +55,16 @@ const program = {
|
|
|
65
55
|
},
|
|
66
56
|
},
|
|
67
57
|
],
|
|
58
|
+
description: "Tiny demo.",
|
|
59
|
+
docs: {
|
|
60
|
+
topics: {
|
|
61
|
+
readme: { text: "# servers.ts\n\nServers demo.\n" },
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
httpServer: { enabled: true },
|
|
65
|
+
key: "servers.ts",
|
|
66
|
+
mcpServer: { enabled: true },
|
|
67
|
+
version: pkg.version,
|
|
68
68
|
} satisfies CliProgram;
|
|
69
69
|
|
|
70
70
|
const cli = new Cli(program);
|
package/index.d.ts
CHANGED
|
@@ -533,22 +533,18 @@ export interface CliCompletionConfig {
|
|
|
533
533
|
/** When `false`, hide/disable `completion` (default: enabled). */
|
|
534
534
|
enabled?: boolean;
|
|
535
535
|
}
|
|
536
|
+
/** Opt-in agent skill install to `~/.agents/skills/<key>/` (default: disabled). */
|
|
537
|
+
export interface CliSkillConfig {
|
|
538
|
+
/** When `true`, install and sync the agent skill via `configure --sync`. Default false when omitted. */
|
|
539
|
+
enabled?: boolean;
|
|
540
|
+
}
|
|
536
541
|
/** @experimental */
|
|
537
542
|
export interface CliConfigureConfig {
|
|
538
543
|
/** When `false`, hide/disable `configure` (default: enabled). */
|
|
539
544
|
enabled?: boolean;
|
|
540
|
-
/**
|
|
541
|
-
* Default agent integration for sync (`configure --sync`).
|
|
542
|
-
* - `'mcp'` when `mcpServer.enabled` (default): MCP targets in sync; paired skills excluded.
|
|
543
|
-
* - `'skill'` when MCP is off (default): skill targets in sync; paired MCP excluded.
|
|
544
|
-
* - `'both'`: sync MCP and skill for the same host when both are available.
|
|
545
|
-
*/
|
|
546
|
-
agentIntegration?: InstallAgentIntegration;
|
|
547
545
|
/** Per-artifact gates for configure sync and interactive wizard. See {@link resolveEffectiveInstallTargets}. */
|
|
548
546
|
targets?: CliConfigureTargets;
|
|
549
547
|
}
|
|
550
|
-
/** Agent integration mode for install — MCP vs shell skill per host. */
|
|
551
|
-
export type InstallAgentIntegration = "mcp" | "skill" | "both";
|
|
552
548
|
/** Boolean or structured gate for one install artifact. */
|
|
553
549
|
export type InstallTargetSpec = boolean | {
|
|
554
550
|
/** When false, artifact is never installed (even with scoped CLI flags). Default true. */
|
|
@@ -564,32 +560,8 @@ export interface ResolvedInstallTarget {
|
|
|
564
560
|
export interface CliConfigureTargets {
|
|
565
561
|
/** App binary status only (Homebrew PATH); no self-install. */
|
|
566
562
|
app?: InstallTargetSpec;
|
|
567
|
-
/** ChatGPT desktop MCP. Default false. */
|
|
568
|
-
chatgptMcp?: InstallTargetSpec;
|
|
569
|
-
/** Claude Code MCP (`~/.claude.json`). Default false. */
|
|
570
|
-
claudeCodeMcp?: InstallTargetSpec;
|
|
571
|
-
/** Claude Desktop MCP. Default false. */
|
|
572
|
-
claudeDesktopMcp?: InstallTargetSpec;
|
|
573
|
-
/** Claude Code skill. Default false. */
|
|
574
|
-
claudeSkill?: InstallTargetSpec;
|
|
575
|
-
/** Codex MCP (`codex mcp add`). Default false. */
|
|
576
|
-
codexMcp?: InstallTargetSpec;
|
|
577
|
-
/** Codex skill. Default false. */
|
|
578
|
-
codexSkill?: InstallTargetSpec;
|
|
579
563
|
/** App config: interactive wizard step in `configure`. Default not in sync. */
|
|
580
564
|
configure?: InstallTargetSpec;
|
|
581
|
-
/** Cursor MCP. Default false. */
|
|
582
|
-
cursorMcp?: InstallTargetSpec;
|
|
583
|
-
/** Cursor skill. Default false. */
|
|
584
|
-
cursorSkill?: InstallTargetSpec;
|
|
585
|
-
/** OpenClaw MCP. Default false. */
|
|
586
|
-
openclawMcp?: InstallTargetSpec;
|
|
587
|
-
/** OpenClaw skill. Default false. */
|
|
588
|
-
openclawSkill?: InstallTargetSpec;
|
|
589
|
-
/** OpenCode MCP. Default false. */
|
|
590
|
-
opencodeMcp?: InstallTargetSpec;
|
|
591
|
-
/** OpenCode skill. Default false. */
|
|
592
|
-
opencodeSkill?: InstallTargetSpec;
|
|
593
565
|
}
|
|
594
566
|
/**
|
|
595
567
|
* One bundled documentation topic for the `docs` built-in (program root only).
|
|
@@ -802,26 +774,28 @@ export interface CliLogConfig {
|
|
|
802
774
|
* May be a leaf or router, plus optional program-level MCP and install config.
|
|
803
775
|
*/
|
|
804
776
|
export type CliProgram = CliNode & {
|
|
805
|
-
/** Program version (printed by the `version` built-in and MCP serverInfo). */
|
|
806
|
-
version: string;
|
|
807
777
|
/** Schema-driven app config file, bootstrap, and MCP metadata. */
|
|
808
778
|
appConfig?: CliAppConfig;
|
|
809
|
-
/** When set with `enabled: true`, enables the `mcp` built-in subcommand. */
|
|
810
|
-
mcpServer?: CliMcpServerConfig;
|
|
811
|
-
/** When set with `enabled: true`, enables the `http` built-in HTTP server. */
|
|
812
|
-
httpServer?: CliHttpServerConfig;
|
|
813
|
-
/** Opt-out and defaults for `configure`. */
|
|
814
|
-
configure?: CliConfigureConfig;
|
|
815
779
|
/** Opt-out for shell completion generation (`completion bash|zsh|fish`). */
|
|
816
780
|
completion?: CliCompletionConfig;
|
|
781
|
+
/** Opt-out and defaults for `configure`. */
|
|
782
|
+
configure?: CliConfigureConfig;
|
|
817
783
|
/** Opt-out and optional topics for the `docs` built-in (default: enabled). */
|
|
818
784
|
docs?: CliDocsConfig;
|
|
819
785
|
/** Invoke and error hooks for user commands on CLI, HTTP, and MCP. */
|
|
820
786
|
hooks?: CliProgramHooks;
|
|
821
|
-
/**
|
|
822
|
-
|
|
787
|
+
/** When set with `enabled: true`, enables the `http` built-in HTTP server. */
|
|
788
|
+
httpServer?: CliHttpServerConfig;
|
|
823
789
|
/** Framework logging (stderr + optional file). */
|
|
824
790
|
log?: CliLogConfig;
|
|
791
|
+
/** When set with `enabled: true`, enables the `mcp` built-in subcommand. */
|
|
792
|
+
mcpServer?: CliMcpServerConfig;
|
|
793
|
+
/** Optional readiness probe for HTTP/MCP `GET /health/readiness` only. */
|
|
794
|
+
readiness?: (ctx: ReadinessContext) => boolean | Promise<boolean>;
|
|
795
|
+
/** Opt-in agent skill (`~/.agents/skills/<key>/`). Default disabled when omitted. */
|
|
796
|
+
skill?: CliSkillConfig;
|
|
797
|
+
/** Program version (printed by the `version` built-in and MCP serverInfo). */
|
|
798
|
+
version: string;
|
|
825
799
|
};
|
|
826
800
|
/** True when the leaf accepts a pure JSON body (no CLI flags). */
|
|
827
801
|
export declare function isJsonLeaf(leaf: CliLeaf): boolean;
|