@stamn/cli 0.1.0-alpha.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 ADDED
@@ -0,0 +1,62 @@
1
+ # @stamn/cli
2
+
3
+ Stamn CLI for managing agents.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @stamn/cli
9
+ ```
10
+
11
+ ### From source
12
+
13
+ ```bash
14
+ git clone https://github.com/stamnhq/sdk.git stamn-sdk
15
+ git clone https://github.com/stamnhq/cli.git stamn-cli
16
+ cd stamn-sdk && npm install && cd ..
17
+ cd stamn-cli && npm install && npm link
18
+ ```
19
+
20
+ ## Commands
21
+
22
+ ### `stamn agent login`
23
+
24
+ Authenticate and register an agent using device login flow.
25
+
26
+ ```bash
27
+ stamn agent login --name my-agent
28
+ ```
29
+
30
+ ### `stamn agent config`
31
+
32
+ View or update agent configuration.
33
+
34
+ ```bash
35
+ stamn agent config --name my-agent
36
+ stamn agent config --personality # opens $EDITOR
37
+ stamn agent config # show current config
38
+ ```
39
+
40
+ ### `stamn status`
41
+
42
+ Show current agent connection status and server health.
43
+
44
+ ```bash
45
+ stamn status
46
+ ```
47
+
48
+ ### `stamn uninstall`
49
+
50
+ Remove CLI.
51
+
52
+ ```bash
53
+ stamn uninstall
54
+ ```
55
+
56
+ ## Configuration
57
+
58
+ Config is stored at `~/.stamn/config.json`. `login` command writes credentials automatically.
59
+
60
+ ## License
61
+
62
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/bin.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ createDefaultAdapter,
4
+ handleConfig,
5
+ handleLogin,
6
+ handleStatus,
7
+ handleUninstall
8
+ } from "./chunk-7DSOXMQ6.js";
9
+
10
+ // src/bin.ts
11
+ import { Command } from "commander";
12
+ var adapter = createDefaultAdapter();
13
+ var program = new Command();
14
+ program.name("stamn").description("Stamn CLI").version("0.1.0-alpha.0");
15
+ var agent = program.command("agent").description("Agent management");
16
+ agent.command("login").description("Authenticate and register an agent").option("--name <name>", "Agent name").action((opts) => handleLogin(opts, adapter));
17
+ agent.command("config").description("View or update agent configuration").option("--name <name>", "Agent display name").option("--personality", "Open editor to set agent personality").action(
18
+ (opts) => handleConfig(opts, adapter)
19
+ );
20
+ program.command("status").description("Show connection status and server health").action(() => handleStatus(adapter));
21
+ program.command("uninstall").description("Remove CLI").action(() => handleUninstall(adapter));
22
+ program.parse();
23
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport {\n handleLogin,\n handleConfig,\n handleStatus,\n handleUninstall,\n} from \"@/commands\";\nimport { createDefaultAdapter } from \"@/config\";\n\nconst adapter = createDefaultAdapter();\n\nconst program = new Command();\n\nprogram.name(\"stamn\").description(\"Stamn CLI\").version(\"0.1.0-alpha.0\");\n\nconst agent = program.command(\"agent\").description(\"Agent management\");\n\nagent\n .command(\"login\")\n .description(\"Authenticate and register an agent\")\n .option(\"--name <name>\", \"Agent name\")\n .action((opts: { name?: string }) => handleLogin(opts, adapter));\n\nagent\n .command(\"config\")\n .description(\"View or update agent configuration\")\n .option(\"--name <name>\", \"Agent display name\")\n .option(\"--personality\", \"Open editor to set agent personality\")\n .action((opts: { name?: string; personality?: boolean }) =>\n handleConfig(opts, adapter),\n );\n\nprogram\n .command(\"status\")\n .description(\"Show connection status and server health\")\n .action(() => handleStatus(adapter));\n\nprogram\n .command(\"uninstall\")\n .description(\"Remove CLI\")\n .action(() => handleUninstall(adapter));\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;AACA,SAAS,eAAe;AASxB,IAAM,UAAU,qBAAqB;AAErC,IAAM,UAAU,IAAI,QAAQ;AAE5B,QAAQ,KAAK,OAAO,EAAE,YAAY,WAAW,EAAE,QAAQ,eAAe;AAEtE,IAAM,QAAQ,QAAQ,QAAQ,OAAO,EAAE,YAAY,kBAAkB;AAErE,MACG,QAAQ,OAAO,EACf,YAAY,oCAAoC,EAChD,OAAO,iBAAiB,YAAY,EACpC,OAAO,CAAC,SAA4B,YAAY,MAAM,OAAO,CAAC;AAEjE,MACG,QAAQ,QAAQ,EAChB,YAAY,oCAAoC,EAChD,OAAO,iBAAiB,oBAAoB,EAC5C,OAAO,iBAAiB,sCAAsC,EAC9D;AAAA,EAAO,CAAC,SACP,aAAa,MAAM,OAAO;AAC5B;AAEF,QACG,QAAQ,QAAQ,EAChB,YAAY,0CAA0C,EACtD,OAAO,MAAM,aAAa,OAAO,CAAC;AAErC,QACG,QAAQ,WAAW,EACnB,YAAY,YAAY,EACxB,OAAO,MAAM,gBAAgB,OAAO,CAAC;AAExC,QAAQ,MAAM;","names":[]}
@@ -0,0 +1,206 @@
1
+ // src/commands/login.ts
2
+ import { intro, outro, spinner, log, note, cancel, text } from "@clack/prompts";
3
+ import { StamnClient } from "@stamn/sdk";
4
+ async function handleLogin(opts, adapter) {
5
+ const client = new StamnClient();
6
+ intro("Stamn Device Login");
7
+ let name = opts.name;
8
+ if (!name) {
9
+ const input = await text({
10
+ message: "What should we call this agent?",
11
+ placeholder: "my-agent",
12
+ validate: (value) => {
13
+ if (!value?.trim()) return "Name is required.";
14
+ }
15
+ });
16
+ if (typeof input === "symbol") {
17
+ cancel("Login cancelled.");
18
+ return;
19
+ }
20
+ name = input;
21
+ }
22
+ const s = spinner();
23
+ try {
24
+ s.start("Initiating device flow...");
25
+ const flow = await client.auth.initiateDeviceFlow();
26
+ s.stop("Device flow initiated.");
27
+ const label = (str) => str.padEnd(7);
28
+ note(
29
+ `${label("Open:")} ${flow.verificationUri}
30
+ ${label("Code:")} ${flow.userCode}`,
31
+ "Authorize in your browser"
32
+ );
33
+ s.start("Waiting for approval...");
34
+ const apiKey = await client.auth.pollForApproval(flow.deviceCode);
35
+ s.stop("Approved!");
36
+ client.setApiKey(apiKey);
37
+ s.start("Registering agent...");
38
+ const participant = await client.participants.create({ name });
39
+ s.stop("Agent registered.");
40
+ adapter.writeConfig({
41
+ apiKey,
42
+ agentId: participant.id,
43
+ agentName: participant.name
44
+ });
45
+ log.success(`Agent "${participant.name}" (${participant.id})`);
46
+ log.info(`Config written to ${adapter.getConfigPath()}`);
47
+ outro("Done! You can now use stamn commands.");
48
+ } catch (err) {
49
+ s.stop("Failed.");
50
+ cancel(`Login failed: ${err.message}`);
51
+ process.exitCode = 1;
52
+ }
53
+ }
54
+
55
+ // src/commands/config.ts
56
+ import { execSync } from "child_process";
57
+ import { mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
58
+ import { join } from "path";
59
+ import { tmpdir } from "os";
60
+ import { log as log2 } from "@clack/prompts";
61
+ function openEditor(initial) {
62
+ const editor = process.env.EDITOR || process.env.VISUAL || "vi";
63
+ const tmpFile = join(tmpdir(), `stamn-personality-${Date.now()}.md`);
64
+ mkdirSync(tmpdir(), { recursive: true });
65
+ writeFileSync(tmpFile, initial, "utf-8");
66
+ try {
67
+ execSync(`${editor} "${tmpFile}"`, { stdio: "inherit" });
68
+ const result = readFileSync(tmpFile, "utf-8").trim();
69
+ return result || null;
70
+ } catch {
71
+ return null;
72
+ } finally {
73
+ try {
74
+ unlinkSync(tmpFile);
75
+ } catch {
76
+ }
77
+ }
78
+ }
79
+ function handleConfig(opts, adapter) {
80
+ if (!opts.name && !opts.personality) {
81
+ const config = adapter.readConfig();
82
+ if (!config) {
83
+ log2.warn("No config found. Run `stamn agent login` first.");
84
+ return;
85
+ }
86
+ log2.info(`Name: ${config.agentName ?? "(not set)"}`);
87
+ log2.info(`Personality: ${config.personality ? "configured" : "(not set)"}`);
88
+ return;
89
+ }
90
+ if (opts.name) {
91
+ adapter.writeConfig({ agentName: opts.name });
92
+ log2.success(`Name set: "${opts.name}"`);
93
+ }
94
+ if (opts.personality) {
95
+ const existing = adapter.readConfig()?.personality ?? "";
96
+ const text2 = openEditor(existing);
97
+ if (!text2) {
98
+ log2.warn("Editor closed without saving. Personality unchanged.");
99
+ return;
100
+ }
101
+ adapter.writeConfig({ personality: text2 });
102
+ log2.success("Personality updated.");
103
+ }
104
+ }
105
+
106
+ // src/commands/status.ts
107
+ import { intro as intro2, outro as outro2, log as log3 } from "@clack/prompts";
108
+ import { StamnClient as StamnClient2 } from "@stamn/sdk";
109
+ async function handleStatus(adapter) {
110
+ const config = adapter.readConfig();
111
+ const status = adapter.readStatusFile();
112
+ const label = (str) => str.padEnd(14);
113
+ intro2("Stamn Status");
114
+ log3.info(`${label("Agent ID:")} ${config?.agentId || "(not configured)"}`);
115
+ log3.info(
116
+ `${label("Agent Name:")} ${config?.agentName || "(not configured)"}`
117
+ );
118
+ log3.info(`${label("Connected:")} ${status?.connected ? "yes" : "no"}`);
119
+ if (status?.connected && status.connectedAt) {
120
+ log3.info(
121
+ `${label("Since:")} ${new Date(status.connectedAt).toLocaleString()}`
122
+ );
123
+ }
124
+ if (config?.apiKey) {
125
+ const client = new StamnClient2({ apiKey: config.apiKey });
126
+ const health = await client.health.check();
127
+ log3.info(`${label("Server:")} ${health.ok ? "healthy" : "unhealthy"}`);
128
+ }
129
+ outro2("");
130
+ }
131
+
132
+ // src/commands/uninstall.ts
133
+ import { intro as intro3, outro as outro3, confirm, log as log4, cancel as cancel2 } from "@clack/prompts";
134
+ async function handleUninstall(adapter) {
135
+ intro3("Stamn Uninstall");
136
+ const shouldContinue = await confirm({
137
+ message: "This will remove all Stamn config and data. Continue?"
138
+ });
139
+ if (!shouldContinue || typeof shouldContinue === "symbol") {
140
+ cancel2("Uninstall cancelled.");
141
+ return;
142
+ }
143
+ try {
144
+ adapter.uninstall?.();
145
+ log4.success("Removed Stamn config");
146
+ outro3("Stamn config removed.");
147
+ } catch (err) {
148
+ cancel2(`Failed to remove config: ${err.message}`);
149
+ process.exitCode = 1;
150
+ }
151
+ }
152
+
153
+ // src/config.ts
154
+ import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "fs";
155
+ import { dirname, join as join2 } from "path";
156
+ import { homedir } from "os";
157
+ function readJsonFile(filePath) {
158
+ try {
159
+ const raw = readFileSync2(filePath, "utf-8");
160
+ return JSON.parse(raw);
161
+ } catch {
162
+ return null;
163
+ }
164
+ }
165
+ function writeJsonFile(filePath, data) {
166
+ mkdirSync2(dirname(filePath), { recursive: true });
167
+ writeFileSync2(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
168
+ }
169
+ function getConfigPath() {
170
+ return join2(homedir(), ".stamn", "config.json");
171
+ }
172
+ function readConfig() {
173
+ return readJsonFile(getConfigPath());
174
+ }
175
+ function writeConfig(updates) {
176
+ const existing = readConfig() ?? {};
177
+ writeJsonFile(getConfigPath(), { ...existing, ...updates });
178
+ }
179
+ function readStatusFile() {
180
+ return readJsonFile(join2(homedir(), ".stamn", "status.json"));
181
+ }
182
+ function createDefaultAdapter() {
183
+ return {
184
+ readConfig,
185
+ writeConfig,
186
+ readStatusFile,
187
+ getConfigPath,
188
+ uninstall() {
189
+ const configDir = dirname(getConfigPath());
190
+ if (existsSync(configDir)) {
191
+ rmSync(configDir, { recursive: true, force: true });
192
+ }
193
+ }
194
+ };
195
+ }
196
+
197
+ export {
198
+ handleLogin,
199
+ handleConfig,
200
+ handleStatus,
201
+ handleUninstall,
202
+ readJsonFile,
203
+ writeJsonFile,
204
+ createDefaultAdapter
205
+ };
206
+ //# sourceMappingURL=chunk-7DSOXMQ6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/login.ts","../src/commands/config.ts","../src/commands/status.ts","../src/commands/uninstall.ts","../src/config.ts"],"sourcesContent":["import { intro, outro, spinner, log, note, cancel, text } from \"@clack/prompts\";\nimport { StamnClient } from \"@stamn/sdk\";\nimport type { ConfigAdapter } from \"@/types\";\n\nexport async function handleLogin(\n opts: { name?: string },\n adapter: ConfigAdapter,\n): Promise<void> {\n const client = new StamnClient();\n\n intro(\"Stamn Device Login\");\n\n let name = opts.name;\n if (!name) {\n const input = await text({\n message: \"What should we call this agent?\",\n placeholder: \"my-agent\",\n validate: (value) => {\n if (!value?.trim()) return \"Name is required.\";\n },\n });\n if (typeof input === \"symbol\") {\n cancel(\"Login cancelled.\");\n return;\n }\n name = input;\n }\n\n const s = spinner();\n\n try {\n s.start(\"Initiating device flow...\");\n const flow = await client.auth.initiateDeviceFlow();\n s.stop(\"Device flow initiated.\");\n\n const label = (str: string) => str.padEnd(7);\n note(\n `${label(\"Open:\")} ${flow.verificationUri}\\n${label(\"Code:\")} ${flow.userCode}`,\n \"Authorize in your browser\",\n );\n\n s.start(\"Waiting for approval...\");\n const apiKey = await client.auth.pollForApproval(flow.deviceCode);\n s.stop(\"Approved!\");\n\n client.setApiKey(apiKey);\n\n s.start(\"Registering agent...\");\n const participant = await client.participants.create({ name });\n s.stop(\"Agent registered.\");\n\n adapter.writeConfig({\n apiKey,\n agentId: participant.id,\n agentName: participant.name,\n });\n\n log.success(`Agent \"${participant.name}\" (${participant.id})`);\n log.info(`Config written to ${adapter.getConfigPath()}`);\n\n outro(\"Done! You can now use stamn commands.\");\n } catch (err) {\n s.stop(\"Failed.\");\n cancel(`Login failed: ${(err as Error).message}`);\n process.exitCode = 1;\n }\n}\n","import { execSync } from \"child_process\";\nimport { mkdirSync, readFileSync, writeFileSync, unlinkSync } from \"fs\";\nimport { join } from \"path\";\nimport { tmpdir } from \"os\";\nimport { log } from \"@clack/prompts\";\nimport type { ConfigAdapter } from \"@/types\";\n\nfunction openEditor(initial: string): string | null {\n const editor = process.env.EDITOR || process.env.VISUAL || \"vi\";\n const tmpFile = join(tmpdir(), `stamn-personality-${Date.now()}.md`);\n\n mkdirSync(tmpdir(), { recursive: true });\n writeFileSync(tmpFile, initial, \"utf-8\");\n\n try {\n execSync(`${editor} \"${tmpFile}\"`, { stdio: \"inherit\" });\n const result = readFileSync(tmpFile, \"utf-8\").trim();\n return result || null;\n } catch {\n return null;\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {}\n }\n}\n\nexport function handleConfig(\n opts: { name?: string; personality?: boolean },\n adapter: ConfigAdapter,\n): void {\n if (!opts.name && !opts.personality) {\n const config = adapter.readConfig();\n if (!config) {\n log.warn(\"No config found. Run `stamn agent login` first.\");\n return;\n }\n log.info(`Name: ${config.agentName ?? \"(not set)\"}`);\n log.info(`Personality: ${config.personality ? \"configured\" : \"(not set)\"}`);\n return;\n }\n\n if (opts.name) {\n adapter.writeConfig({ agentName: opts.name });\n log.success(`Name set: \"${opts.name}\"`);\n }\n\n if (opts.personality) {\n const existing = adapter.readConfig()?.personality ?? \"\";\n const text = openEditor(existing);\n if (!text) {\n log.warn(\"Editor closed without saving. Personality unchanged.\");\n return;\n }\n adapter.writeConfig({ personality: text });\n log.success(\"Personality updated.\");\n }\n}\n","import { intro, outro, log } from \"@clack/prompts\";\nimport { StamnClient } from \"@stamn/sdk\";\nimport type { StamnConfig, ConfigAdapter } from \"@/types\";\n\nexport async function handleStatus(adapter: ConfigAdapter): Promise<void> {\n const config = adapter.readConfig();\n const status = adapter.readStatusFile();\n const label = (str: string) => str.padEnd(14);\n\n intro(\"Stamn Status\");\n\n log.info(`${label(\"Agent ID:\")} ${config?.agentId || \"(not configured)\"}`);\n log.info(\n `${label(\"Agent Name:\")} ${config?.agentName || \"(not configured)\"}`,\n );\n log.info(`${label(\"Connected:\")} ${status?.connected ? \"yes\" : \"no\"}`);\n\n if (status?.connected && status.connectedAt) {\n log.info(\n `${label(\"Since:\")} ${new Date(status.connectedAt).toLocaleString()}`,\n );\n }\n\n if (config?.apiKey) {\n const client = new StamnClient({ apiKey: config.apiKey });\n const health = await client.health.check();\n log.info(`${label(\"Server:\")} ${health.ok ? \"healthy\" : \"unhealthy\"}`);\n }\n\n outro(\"\");\n}\n","import { intro, outro, confirm, log, cancel } from \"@clack/prompts\";\nimport type { ConfigAdapter } from \"@/types\";\n\nexport async function handleUninstall(adapter: ConfigAdapter): Promise<void> {\n intro(\"Stamn Uninstall\");\n\n const shouldContinue = await confirm({\n message: \"This will remove all Stamn config and data. Continue?\",\n });\n\n if (!shouldContinue || typeof shouldContinue === \"symbol\") {\n cancel(\"Uninstall cancelled.\");\n return;\n }\n\n try {\n adapter.uninstall?.();\n log.success(\"Removed Stamn config\");\n outro(\"Stamn config removed.\");\n } catch (err) {\n cancel(`Failed to remove config: ${(err as Error).message}`);\n process.exitCode = 1;\n }\n}\n","import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { homedir } from \"os\";\nimport type { StamnConfig, StamnStatusFile, ConfigAdapter } from \"@/types\";\n\nexport function readJsonFile<T>(filePath: string): T | null {\n try {\n const raw = readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\nexport function writeJsonFile(filePath: string, data: unknown): void {\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, JSON.stringify(data, null, 2) + \"\\n\", \"utf-8\");\n}\n\nexport function getConfigPath(): string {\n return join(homedir(), \".stamn\", \"config.json\");\n}\n\nexport function readConfig(): StamnConfig | null {\n return readJsonFile<StamnConfig>(getConfigPath());\n}\n\nexport function writeConfig(updates: Partial<StamnConfig>): void {\n const existing = readConfig() ?? {};\n writeJsonFile(getConfigPath(), { ...existing, ...updates });\n}\n\nexport function readStatusFile(): StamnStatusFile | null {\n return readJsonFile<StamnStatusFile>(join(homedir(), \".stamn\", \"status.json\"));\n}\n\nexport function createDefaultAdapter(): ConfigAdapter {\n return {\n readConfig,\n writeConfig,\n readStatusFile,\n getConfigPath,\n uninstall() {\n const configDir = dirname(getConfigPath());\n if (existsSync(configDir)) {\n rmSync(configDir, { recursive: true, force: true });\n }\n },\n };\n}\n"],"mappings":"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","names":["log","text","intro","outro","log","StamnClient","intro","outro","log","cancel","mkdirSync","readFileSync","writeFileSync","join"]}
@@ -0,0 +1,49 @@
1
+ interface ServiceConfig {
2
+ tag: string;
3
+ description: string;
4
+ priceCents: number;
5
+ }
6
+ interface StamnConfig {
7
+ apiKey: string;
8
+ agentId: string;
9
+ agentName?: string;
10
+ heartbeatIntervalMs: number;
11
+ autonomousIntervalMs?: number;
12
+ gatewayPort?: number;
13
+ gatewayToken?: string;
14
+ personality?: string;
15
+ services?: ServiceConfig[];
16
+ }
17
+ interface StamnStatusFile {
18
+ connected: boolean;
19
+ agentId: string;
20
+ agentName?: string;
21
+ connectedAt?: string;
22
+ disconnectedAt?: string;
23
+ }
24
+ interface ConfigAdapter {
25
+ readConfig(): StamnConfig | null;
26
+ writeConfig(updates: Partial<StamnConfig>): void;
27
+ readStatusFile(): StamnStatusFile | null;
28
+ getConfigPath(): string;
29
+ uninstall?(): void;
30
+ }
31
+
32
+ declare function handleLogin(opts: {
33
+ name?: string;
34
+ }, adapter: ConfigAdapter): Promise<void>;
35
+
36
+ declare function handleConfig(opts: {
37
+ name?: string;
38
+ personality?: boolean;
39
+ }, adapter: ConfigAdapter): void;
40
+
41
+ declare function handleStatus(adapter: ConfigAdapter): Promise<void>;
42
+
43
+ declare function handleUninstall(adapter: ConfigAdapter): Promise<void>;
44
+
45
+ declare function readJsonFile<T>(filePath: string): T | null;
46
+ declare function writeJsonFile(filePath: string, data: unknown): void;
47
+ declare function createDefaultAdapter(): ConfigAdapter;
48
+
49
+ export { type ConfigAdapter, type ServiceConfig, type StamnConfig, type StamnStatusFile, createDefaultAdapter, handleConfig, handleLogin, handleStatus, handleUninstall, readJsonFile, writeJsonFile };
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ import {
2
+ createDefaultAdapter,
3
+ handleConfig,
4
+ handleLogin,
5
+ handleStatus,
6
+ handleUninstall,
7
+ readJsonFile,
8
+ writeJsonFile
9
+ } from "./chunk-7DSOXMQ6.js";
10
+ export {
11
+ createDefaultAdapter,
12
+ handleConfig,
13
+ handleLogin,
14
+ handleStatus,
15
+ handleUninstall,
16
+ readJsonFile,
17
+ writeJsonFile
18
+ };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@stamn/cli",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "Stamn CLI",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "stamn": "./dist/bin.js"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "start": "node dist/bin.js",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "prepare": "npm run build"
27
+ },
28
+ "tsup": {
29
+ "entry": [
30
+ "src/index.ts",
31
+ "src/bin.ts"
32
+ ],
33
+ "format": [
34
+ "esm"
35
+ ],
36
+ "dts": true,
37
+ "clean": true,
38
+ "sourcemap": true,
39
+ "external": [
40
+ "@stamn/sdk"
41
+ ]
42
+ },
43
+ "keywords": [
44
+ "stamn",
45
+ "cli"
46
+ ],
47
+ "license": "MIT",
48
+ "devDependencies": {
49
+ "@types/node": "^22.0.0",
50
+ "tsup": "^8.5.1",
51
+ "typescript": "^5.9.0",
52
+ "vitest": "^4.0.18"
53
+ },
54
+ "dependencies": {
55
+ "@clack/prompts": "^1.0.1",
56
+ "@stamn/sdk": "file:../../packages/sdk",
57
+ "commander": "^14.0.3"
58
+ }
59
+ }