create-invokable 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Invokable
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 ADDED
@@ -0,0 +1,57 @@
1
+ # create-invokable
2
+
3
+ Scaffolds an agent-native CLI.
4
+
5
+ ```console
6
+ $ npx create-invokable my-deployer
7
+ ? Auth server?
8
+ 1) hosted (default)
9
+ 2) self-host
10
+ ? First command? (deploy)
11
+ ? Does it spend money or need approval? [Y/n]
12
+
13
+ Created ./my-deployer
14
+ ```
15
+
16
+ Non-interactive:
17
+
18
+ ```bash
19
+ npx create-invokable my-deployer --yes --command deploy --spends --auth self-host
20
+ ```
21
+
22
+ ## What you get
23
+
24
+ ```
25
+ my-deployer/
26
+ ├── package.json bin wired, build and test scripts
27
+ ├── tsconfig.json
28
+ ├── src/tool.ts defineTool with your first command
29
+ ├── bin/my-deployer.mjs the entry point, executable
30
+ ├── README.md
31
+ └── .github/workflows/ci.yml
32
+ ```
33
+
34
+ `login`, `logout`, `whoami` and `doctor` are built in and need no code. `init`
35
+ generates agent instructions. If the first command spends money it comes with an
36
+ approval gate already wired, and `requireSpendLimit` set so `--yes` is refused
37
+ without a `--max-spend` cap.
38
+
39
+ The generated CI runs both contract checks:
40
+
41
+ ```yaml
42
+ - run: npx invokable-test node bin/my-deployer.mjs # the contract holds
43
+ - run: node bin/my-deployer.mjs init --check # instructions are current
44
+ ```
45
+
46
+ ## Options
47
+
48
+ | Option | Effect |
49
+ |---|---|
50
+ | `--command <name>` | First command. Default `deploy`. |
51
+ | `--spends` / `--no-spends` | Whether it needs an approval gate. |
52
+ | `--auth <hosted\|self-host>` | Where `login` points. Default `hosted`. |
53
+ | `-y`, `--yes` | Accept every default; never prompt. |
54
+
55
+ The name must be lowercase letters, digits and hyphens: it becomes both the
56
+ binary name and the generated skill name, and the Agent Skills spec constrains
57
+ the latter.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { createMain } from '../dist/index.js';
3
+
4
+ process.exitCode = await createMain({ argv: process.argv.slice(2) });
package/dist/cli.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { type Prompter } from './prompt.js';
2
+ export interface CreateOptions {
3
+ argv: readonly string[];
4
+ cwd?: string;
5
+ stdout?: (s: string) => void;
6
+ stderr?: (s: string) => void;
7
+ prompter?: Prompter;
8
+ }
9
+ export declare function createMain(options: CreateOptions): Promise<number>;
10
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4C,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAkBD,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAwGxE"}
package/dist/cli.js ADDED
@@ -0,0 +1,116 @@
1
+ import { chmodSync, existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { scaffold } from './template.js';
4
+ import { nonInteractivePrompter, terminalPrompter } from './prompt.js';
5
+ const USAGE = `Usage: create-invokable <name> [options]
6
+
7
+ Scaffolds an agent-native CLI.
8
+
9
+ Options:
10
+ --command <name> First command. Default: deploy.
11
+ --spends The first command spends money and needs approval.
12
+ --no-spends It does not.
13
+ --auth <mode> hosted | self-host. Default: hosted.
14
+ -y, --yes Accept every default; do not prompt.
15
+ -h, --help Show this help.
16
+ `;
17
+ /** Skill-name rules, so `init` can generate a valid SKILL.md later. */
18
+ const NAME_PATTERN = /^[a-z0-9-]{1,64}$/;
19
+ export async function createMain(options) {
20
+ const stderr = options.stderr ?? ((s) => process.stderr.write(s));
21
+ const cwd = options.cwd ?? process.cwd();
22
+ const argv = [...options.argv];
23
+ let name;
24
+ let commandName;
25
+ let spends;
26
+ let auth;
27
+ let acceptDefaults = false;
28
+ for (let i = 0; i < argv.length; i++) {
29
+ const token = argv[i];
30
+ if (token === '--help' || token === '-h') {
31
+ stderr(USAGE);
32
+ return 0;
33
+ }
34
+ else if (token === '--yes' || token === '-y') {
35
+ acceptDefaults = true;
36
+ }
37
+ else if (token === '--spends') {
38
+ spends = true;
39
+ }
40
+ else if (token === '--no-spends') {
41
+ spends = false;
42
+ }
43
+ else if (token === '--command') {
44
+ commandName = argv[++i];
45
+ }
46
+ else if (token === '--auth') {
47
+ const value = argv[++i];
48
+ if (value !== 'hosted' && value !== 'self-host') {
49
+ stderr(`error: --auth must be "hosted" or "self-host"; got ${JSON.stringify(value)}\n`);
50
+ return 2;
51
+ }
52
+ auth = value;
53
+ }
54
+ else if (token.startsWith('-')) {
55
+ stderr(`error: unknown option ${token}\n${USAGE}`);
56
+ return 2;
57
+ }
58
+ else if (name === undefined) {
59
+ name = token;
60
+ }
61
+ }
62
+ const prompter = options.prompter ??
63
+ (acceptDefaults || !process.stdin.isTTY ? nonInteractivePrompter() : terminalPrompter());
64
+ try {
65
+ if (name === undefined) {
66
+ name = await prompter.text('Tool name?', 'my-tool');
67
+ }
68
+ if (!NAME_PATTERN.test(name)) {
69
+ stderr(`error: "${name}" is not a usable tool name. Use lowercase letters, digits and ` +
70
+ 'hyphens — it becomes the binary name and the skill name.\n');
71
+ return 2;
72
+ }
73
+ const target = resolve(cwd, name);
74
+ if (existsSync(target) && readdirSync(target).length > 0) {
75
+ stderr(`error: ${target} already exists and is not empty.\n`);
76
+ return 6;
77
+ }
78
+ if (auth === undefined) {
79
+ auth = await prompter.choice('Auth server?', ['hosted', 'self-host'], 'hosted');
80
+ }
81
+ if (commandName === undefined) {
82
+ commandName = await prompter.text('First command?', 'deploy');
83
+ }
84
+ if (spends === undefined) {
85
+ spends = await prompter.confirm('Does it spend money or need approval?', true);
86
+ }
87
+ const files = scaffold({ name, command: commandName, spends, auth });
88
+ for (const file of files) {
89
+ const path = join(target, file.path);
90
+ mkdirSync(dirname(path), { recursive: true });
91
+ writeFileSync(path, file.content, 'utf8');
92
+ if (file.executable)
93
+ chmodSync(path, 0o755);
94
+ }
95
+ stderr(`\nCreated ${target}\n\n`);
96
+ for (const file of files)
97
+ stderr(` ${file.path}\n`);
98
+ stderr([
99
+ '',
100
+ 'Next:',
101
+ ` cd ${name}`,
102
+ ' npm install',
103
+ ' npm run build',
104
+ ` node bin/${name}.mjs --help`,
105
+ '',
106
+ 'Then check the contract holds:',
107
+ ` npx invokable-test node bin/${name}.mjs`,
108
+ '',
109
+ ].join('\n'));
110
+ return 0;
111
+ }
112
+ finally {
113
+ prompter.close();
114
+ }
115
+ }
116
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { createMain } from './cli.js';
2
+ export type { CreateOptions } from './cli.js';
3
+ export { scaffold } from './template.js';
4
+ export type { ScaffoldSpec, ScaffoldFile } from './template.js';
5
+ export { nonInteractivePrompter, terminalPrompter } from './prompt.js';
6
+ export type { Prompter } from './prompt.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { createMain } from './cli.js';
2
+ export { scaffold } from './template.js';
3
+ export { nonInteractivePrompter, terminalPrompter } from './prompt.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface Prompter {
2
+ text: (question: string, fallback: string) => Promise<string>;
3
+ confirm: (question: string, fallback: boolean) => Promise<boolean>;
4
+ choice: <T extends string>(question: string, options: readonly T[], fallback: T) => Promise<T>;
5
+ close: () => void;
6
+ }
7
+ /** Answers every prompt with its default; used by `--yes` and by tests. */
8
+ export declare function nonInteractivePrompter(): Prompter;
9
+ /**
10
+ * Prompts on stderr and reads stdin, so that scaffolding can be piped without
11
+ * the questions contaminating whatever the caller is capturing.
12
+ */
13
+ export declare function terminalPrompter(): Prompter;
14
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/F,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,QAAQ,CAOjD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,QAAQ,CA8B3C"}
package/dist/prompt.js ADDED
@@ -0,0 +1,44 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ /** Answers every prompt with its default; used by `--yes` and by tests. */
3
+ export function nonInteractivePrompter() {
4
+ return {
5
+ text: async (_q, fallback) => fallback,
6
+ confirm: async (_q, fallback) => fallback,
7
+ choice: async (_q, _o, fallback) => fallback,
8
+ close: () => { },
9
+ };
10
+ }
11
+ /**
12
+ * Prompts on stderr and reads stdin, so that scaffolding can be piped without
13
+ * the questions contaminating whatever the caller is capturing.
14
+ */
15
+ export function terminalPrompter() {
16
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
17
+ return {
18
+ async text(question, fallback) {
19
+ const answer = (await rl.question(`${question} (${fallback}) `)).trim();
20
+ return answer || fallback;
21
+ },
22
+ async confirm(question, fallback) {
23
+ const hint = fallback ? 'Y/n' : 'y/N';
24
+ const answer = (await rl.question(`${question} [${hint}] `)).trim();
25
+ if (!answer)
26
+ return fallback;
27
+ return /^y(es)?$/i.test(answer);
28
+ },
29
+ async choice(question, options, fallback) {
30
+ const list = options.map((o, i) => ` ${i + 1}) ${o}${o === fallback ? ' (default)' : ''}`);
31
+ const answer = (await rl.question(`${question}\n${list.join('\n')}\n> `)).trim();
32
+ if (!answer)
33
+ return fallback;
34
+ const byIndex = Number(answer);
35
+ if (Number.isInteger(byIndex) && byIndex >= 1 && byIndex <= options.length) {
36
+ return options[byIndex - 1];
37
+ }
38
+ const byName = options.find((o) => o.toLowerCase() === answer.toLowerCase());
39
+ return byName ?? fallback;
40
+ },
41
+ close: () => rl.close(),
42
+ };
43
+ }
44
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AASzD,2EAA2E;AAC3E,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACtC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACzC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ;QAC5C,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;KAChB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7E,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ;YAC3B,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACxE,OAAO,MAAM,IAAI,QAAQ,CAAC;QAC5B,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ;YAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YACtC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACpE,IAAI,CAAC,MAAM;gBAAE,OAAO,QAAQ,CAAC;YAC7B,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ;YACtC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,CACb,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CACzD,CAAC,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,MAAM;gBAAE,OAAO,QAAQ,CAAC;YAE7B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC3E,OAAO,OAAO,CAAC,OAAO,GAAG,CAAC,CAAE,CAAC;YAC/B,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7E,OAAO,MAAM,IAAI,QAAQ,CAAC;QAC5B,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface ScaffoldSpec {
2
+ /** Binary and package name. Must be a valid skill name too. */
3
+ name: string;
4
+ /** First real command, e.g. `deploy`. */
5
+ command: string;
6
+ /** Whether the first command spends money and needs an approval gate. */
7
+ spends: boolean;
8
+ /** `hosted` points at auth.invokable.dev; `self-host` at localhost. */
9
+ auth: 'hosted' | 'self-host';
10
+ version?: string;
11
+ }
12
+ export interface ScaffoldFile {
13
+ path: string;
14
+ content: string;
15
+ executable?: boolean;
16
+ }
17
+ export declare function scaffold(spec: ScaffoldSpec): ScaffoldFile[];
18
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAqMD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,EAAE,CAiG3D"}
@@ -0,0 +1,283 @@
1
+ /** `deploy-thing` -> `DeployThing`, for a generated type name. */
2
+ function pascal(value) {
3
+ return value
4
+ .split(/[^A-Za-z0-9]+/)
5
+ .filter(Boolean)
6
+ .map((part) => part[0].toUpperCase() + part.slice(1))
7
+ .join('');
8
+ }
9
+ const HOSTED_AUTH_URL = 'https://auth.invokable.dev';
10
+ function apiUrls(spec) {
11
+ return spec.auth === 'hosted'
12
+ ? { baseUrl: `https://api.${spec.name}.example.com`, authUrl: HOSTED_AUTH_URL }
13
+ : { baseUrl: 'http://127.0.0.1:8787', authUrl: 'http://127.0.0.1:8787' };
14
+ }
15
+ function toolSource(spec) {
16
+ const { baseUrl, authUrl } = apiUrls(spec);
17
+ const envPrefix = spec.name.toUpperCase().replace(/-/g, '_');
18
+ // The response type is declared rather than inferred: `client.post()` returns
19
+ // `unknown` by design, so a template that destructured it straight away would
20
+ // ship a project that does not compile.
21
+ const planType = `
22
+ /** Shape your \`/v1/${spec.command}/plan\` endpoint returns. Adjust to match. */
23
+ interface ${pascal(spec.command)}Plan {
24
+ id: string;
25
+ summary?: unknown;
26
+ credits: number;
27
+ balance: number;
28
+ }
29
+ `;
30
+ const gated = `
31
+ ${JSON.stringify(spec.command)}: command({
32
+ description: 'Describe what this does — the agent reads this to decide when to run it.',
33
+ options: {
34
+ env: {
35
+ type: 'string',
36
+ required: true,
37
+ choices: ['staging', 'prod'],
38
+ description: 'Which environment to target.',
39
+ },
40
+ },
41
+ // Marks the command as spending money: the generated SKILL.md warns the
42
+ // agent, and \`--yes\` can be refused without \`--max-spend\`.
43
+ spends: true,
44
+ run: async ({ opts, client, ctx }) => {
45
+ const plan = await client.post<${pascal(spec.command)}Plan>(
46
+ '/v1/${spec.command}/plan',
47
+ { env: opts.env },
48
+ );
49
+
50
+ // Stops here and exits 10 unless an approval fingerprint was supplied.
51
+ await checkpoint(ctx, {
52
+ gate: '${spec.command}_review',
53
+ title: '${spec.command} plan',
54
+ summary: plan.summary ?? plan,
55
+ subject: plan.id,
56
+ question: \`Run ${spec.command} against \${opts.env}?\`,
57
+ explain: 'Approving starts the work and bills the account.',
58
+ spend: { estimated: plan.credits, balance: plan.balance },
59
+ reject: \`${spec.name} ${spec.command} --env \${opts.env} --dry-run\`,
60
+ });
61
+
62
+ return client.post('/v1/${spec.command}', { planId: plan.id });
63
+ },
64
+ }),`;
65
+ const plain = `
66
+ ${JSON.stringify(spec.command)}: command({
67
+ description: 'Describe what this does — the agent reads this to decide when to run it.',
68
+ options: {
69
+ name: {
70
+ type: 'string',
71
+ required: true,
72
+ description: 'What to act on.',
73
+ },
74
+ },
75
+ run: async ({ opts, client, ctx }) => {
76
+ ctx.io.note(\`working on \${opts.name}…\`); // progress → stderr
77
+ return client.get(\`/v1/${spec.command}/\${encodeURIComponent(opts.name)}\`);
78
+ },
79
+ }),`;
80
+ return `import { command, defineTool${spec.spends ? ', checkpoint' : ''} } from '@invokable/core';
81
+ import { initCommand } from '@invokable/skills';
82
+
83
+ import pkg from '../package.json' with { type: 'json' };
84
+ ${spec.spends ? planType : ''}
85
+ export default defineTool({
86
+ name: '${spec.name}',
87
+ version: pkg.version,
88
+ description: 'One line an agent reads to decide whether this tool is relevant.',
89
+
90
+ api: {
91
+ baseUrl: process.env.${envPrefix}_API ?? '${baseUrl}',
92
+ authUrl: process.env.${envPrefix}_AUTH ?? '${authUrl}',
93
+ },
94
+ configDir: '~/.${spec.name}',
95
+ ${spec.spends ? '\n // Refuse `--yes` on spending commands unless `--max-spend` is also given.\n requireSpendLimit: true,\n' : ''}
96
+ commands: {
97
+ // Installs agent instructions into this project. login/logout/whoami/doctor
98
+ // are built in and need no declaration.
99
+ init: initCommand(),
100
+ ${spec.spends ? gated : plain}
101
+ },
102
+ });
103
+ `;
104
+ }
105
+ function readme(spec) {
106
+ const envPrefix = spec.name.toUpperCase().replace(/-/g, '_');
107
+ return `# ${spec.name}
108
+
109
+ An agent-native CLI built with [invokable](https://github.com/beinvokable/invokable).
110
+
111
+ ## Develop
112
+
113
+ \`\`\`bash
114
+ npm install
115
+ npm run build
116
+ node bin/${spec.name}.mjs --help
117
+ \`\`\`
118
+
119
+ ## Try it
120
+
121
+ \`\`\`bash
122
+ # Install agent instructions into a project
123
+ node bin/${spec.name}.mjs init
124
+
125
+ # Check connectivity and auth
126
+ node bin/${spec.name}.mjs doctor --json
127
+ \`\`\`
128
+ ${spec.auth === 'self-host'
129
+ ? `
130
+ ### Run the auth server
131
+
132
+ This project is configured for self-hosted auth. Start a server that mounts
133
+ \`@invokable/server\` on \`${apiUrls(spec).authUrl}\`, then:
134
+
135
+ \`\`\`bash
136
+ node bin/${spec.name}.mjs login
137
+ \`\`\`
138
+ `
139
+ : `
140
+ ### Sign in
141
+
142
+ Auth points at \`${HOSTED_AUTH_URL}\`. Override for local development:
143
+
144
+ \`\`\`bash
145
+ ${envPrefix}_AUTH=http://127.0.0.1:8787 node bin/${spec.name}.mjs login
146
+ \`\`\`
147
+ `}
148
+ ## The contract
149
+
150
+ Every command emits **one JSON document on stdout** with \`--json\`, and a
151
+ semantic exit code. Progress goes to stderr.
152
+
153
+ \`\`\`console
154
+ $ ${spec.name} ${spec.command} --json
155
+ {"status":"ok","data":{ ... }}
156
+
157
+ $ echo $?
158
+ 0
159
+ \`\`\`
160
+
161
+ Check it holds:
162
+
163
+ \`\`\`bash
164
+ npx invokable-test node bin/${spec.name}.mjs
165
+ \`\`\`
166
+ ${spec.spends
167
+ ? `
168
+ ## Approval gate
169
+
170
+ \`${spec.command}\` spends money, so it stops first:
171
+
172
+ \`\`\`console
173
+ $ ${spec.name} ${spec.command} --env prod --json
174
+ {"status":"checkpoint","gate":"${spec.command}_review","fingerprint":"…",
175
+ "next":{"approve":"${spec.name} ${spec.command} --env prod --json --approve ${spec.command}_review@…"}}
176
+ $ echo $?
177
+ 10
178
+ \`\`\`
179
+
180
+ The fingerprint is issued by your API, bound to the plan the user was shown,
181
+ and consumed once. Mount \`checkpointRoutes()\` and \`verifyCheckpoint()\` from
182
+ \`@invokable/server\` to issue and verify them.
183
+ `
184
+ : ''}
185
+ ## Agent instructions
186
+
187
+ \`${spec.name} init\` writes a portable \`SKILL.md\` for Claude Code, Codex, Cursor
188
+ and Gemini CLI, plus sections in \`AGENTS.md\` and Copilot instructions. Re-run it
189
+ whenever you add a command; \`init --check\` fails CI when they are stale.
190
+ `;
191
+ }
192
+ export function scaffold(spec) {
193
+ const version = spec.version ?? '0.1.0';
194
+ const pkg = {
195
+ name: spec.name,
196
+ version,
197
+ description: 'An agent-native CLI.',
198
+ type: 'module',
199
+ bin: { [spec.name]: `./bin/${spec.name}.mjs` },
200
+ files: ['bin', 'dist'],
201
+ engines: { node: '>=20' },
202
+ scripts: {
203
+ build: 'tsc -p tsconfig.json',
204
+ dev: 'tsc -p tsconfig.json --watch',
205
+ test: 'invokable-test node bin/' + spec.name + '.mjs',
206
+ prepublishOnly: 'npm run build',
207
+ },
208
+ dependencies: {
209
+ '@invokable/core': '^0.1.0',
210
+ '@invokable/skills': '^0.1.0',
211
+ },
212
+ devDependencies: {
213
+ '@invokable/conformance': '^0.1.0',
214
+ '@types/node': '^22.0.0',
215
+ typescript: '^5.9.0',
216
+ },
217
+ };
218
+ return [
219
+ { path: 'package.json', content: JSON.stringify(pkg, null, 2) + '\n' },
220
+ {
221
+ path: 'tsconfig.json',
222
+ content: JSON.stringify({
223
+ compilerOptions: {
224
+ target: 'ES2023',
225
+ module: 'NodeNext',
226
+ moduleResolution: 'NodeNext',
227
+ types: ['node'],
228
+ strict: true,
229
+ declaration: true,
230
+ resolveJsonModule: true,
231
+ outDir: 'dist',
232
+ rootDir: 'src',
233
+ },
234
+ include: ['src/**/*.ts'],
235
+ }, null, 2) + '\n',
236
+ },
237
+ { path: 'src/tool.ts', content: toolSource(spec) },
238
+ {
239
+ path: `bin/${spec.name}.mjs`,
240
+ executable: true,
241
+ content: `#!/usr/bin/env node
242
+ import { cli } from '@invokable/core';
243
+ import tool from '../dist/tool.js';
244
+
245
+ await cli(tool);
246
+ `,
247
+ },
248
+ { path: 'README.md', content: readme(spec) },
249
+ {
250
+ path: '.gitignore',
251
+ content: 'node_modules/\ndist/\n*.tsbuildinfo\n.env\n.env.*\n!.env.example\n',
252
+ },
253
+ {
254
+ path: '.github/workflows/ci.yml',
255
+ content: `name: CI
256
+
257
+ on:
258
+ push:
259
+ branches: ['**']
260
+ pull_request:
261
+
262
+ jobs:
263
+ test:
264
+ runs-on: ubuntu-latest
265
+ steps:
266
+ - uses: actions/checkout@v4
267
+ - uses: actions/setup-node@v4
268
+ with:
269
+ node-version: 22
270
+ - run: npm ci
271
+ - run: npm run build
272
+
273
+ # The contract an agent depends on.
274
+ - run: npx invokable-test node bin/${spec.name}.mjs
275
+
276
+ # Fails when a command was added but the agent instructions were not
277
+ # regenerated.
278
+ - run: node bin/${spec.name}.mjs init --check
279
+ `,
280
+ },
281
+ ];
282
+ }
283
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,KAAK;SACT,KAAK,CAAC,eAAe,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACrD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAoBD,MAAM,eAAe,GAAG,4BAA4B,CAAC;AAErD,SAAS,OAAO,CAAC,IAAkB;IACjC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAC3B,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,IAAI,CAAC,IAAI,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE;QAC/E,CAAC,CAAC,EAAE,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;AAC7E,CAAC;AAED,SAAS,UAAU,CAAC,IAAkB;IACpC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE7D,8EAA8E;IAC9E,8EAA8E;IAC9E,wCAAwC;IACxC,MAAM,QAAQ,GAAG;uBACI,IAAI,CAAC,OAAO;YACvB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;;;;;;CAM/B,CAAC;IAEA,MAAM,KAAK,GAAG;MACV,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;;;;;;;;;;;;;yCAcO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;iBAC5C,IAAI,CAAC,OAAO;;;;;;mBAMV,IAAI,CAAC,OAAO;oBACX,IAAI,CAAC,OAAO;;;4BAGJ,IAAI,CAAC,OAAO;;;sBAGlB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO;;;kCAGb,IAAI,CAAC,OAAO;;QAEtC,CAAC;IAEP,MAAM,KAAK,GAAG;MACV,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC;;;;;;;;;;;kCAWA,IAAI,CAAC,OAAO;;QAEtC,CAAC;IAEP,OAAO,+BAA+B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;;;;EAIvE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;;WAElB,IAAI,CAAC,IAAI;;;;;2BAKO,SAAS,YAAY,OAAO;2BAC5B,SAAS,aAAa,OAAO;;mBAErC,IAAI,CAAC,IAAI;EAC1B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,8GAA8G,CAAC,CAAC,CAAC,EAAE;;;;;EAKjI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;;;CAG5B,CAAC;AACF,CAAC;AAED,SAAS,MAAM,CAAC,IAAkB;IAChC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7D,OAAO,KAAK,IAAI,CAAC,IAAI;;;;;;;;;WASZ,IAAI,CAAC,IAAI;;;;;;;WAOT,IAAI,CAAC,IAAI;;;WAGT,IAAI,CAAC,IAAI;;EAGlB,IAAI,CAAC,IAAI,KAAK,WAAW;QACvB,CAAC,CAAC;;;;6BAIuB,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO;;;WAGvC,IAAI,CAAC,IAAI;;CAEnB;QACG,CAAC,CAAC;;;mBAGa,eAAe;;;EAGhC,SAAS,wCAAwC,IAAI,CAAC,IAAI;;CAG5D;;;;;;;IAOI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO;;;;;;;;;;8BAUC,IAAI,CAAC,IAAI;;EAGrC,IAAI,CAAC,MAAM;QACT,CAAC,CAAC;;;IAGF,IAAI,CAAC,OAAO;;;IAGZ,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO;iCACI,IAAI,CAAC,OAAO;sBACvB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,gCAAgC,IAAI,CAAC,OAAO;;;;;;;;CAQ1F;QACG,CAAC,CAAC,EACN;;;IAGI,IAAI,CAAC,IAAI;;;CAGZ,CAAC;AACF,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAkB;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC;IAExC,MAAM,GAAG,GAAG;QACV,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO;QACP,WAAW,EAAE,sBAAsB;QACnC,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,IAAI,CAAC,IAAI,MAAM,EAAE;QAC9C,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACzB,OAAO,EAAE;YACP,KAAK,EAAE,sBAAsB;YAC7B,GAAG,EAAE,8BAA8B;YACnC,IAAI,EAAE,0BAA0B,GAAG,IAAI,CAAC,IAAI,GAAG,MAAM;YACrD,cAAc,EAAE,eAAe;SAChC;QACD,YAAY,EAAE;YACZ,iBAAiB,EAAE,QAAQ;YAC3B,mBAAmB,EAAE,QAAQ;SAC9B;QACD,eAAe,EAAE;YACf,wBAAwB,EAAE,QAAQ;YAClC,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,QAAQ;SACrB;KACF,CAAC;IAEF,OAAO;QACL,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QACtE;YACE,IAAI,EAAE,eAAe;YACrB,OAAO,EACL,IAAI,CAAC,SAAS,CACZ;gBACE,eAAe,EAAE;oBACf,MAAM,EAAE,QAAQ;oBAChB,MAAM,EAAE,UAAU;oBAClB,gBAAgB,EAAE,UAAU;oBAC5B,KAAK,EAAE,CAAC,MAAM,CAAC;oBACf,MAAM,EAAE,IAAI;oBACZ,WAAW,EAAE,IAAI;oBACjB,iBAAiB,EAAE,IAAI;oBACvB,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,KAAK;iBACf;gBACD,OAAO,EAAE,CAAC,aAAa,CAAC;aACzB,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI;SACX;QACD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE;QAClD;YACE,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,MAAM;YAC5B,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;CAKd;SACI;QACD,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE;QAC5C;YACE,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,oEAAoE;SAC9E;QACD;YACE,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;2CAmB4B,IAAI,CAAC,IAAI;;;;wBAI5B,IAAI,CAAC,IAAI;CAChC;SACI;KACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "create-invokable",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold an agent-native CLI.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "bin": {
11
+ "create-invokable": "./bin/create-invokable.mjs"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "files": [
22
+ "dist",
23
+ "bin",
24
+ "LICENSE"
25
+ ],
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/beinvokable/invokable.git",
29
+ "directory": "packages/create-invokable"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -b",
36
+ "clean": "rm -rf dist *.tsbuildinfo"
37
+ }
38
+ }