@spekn/cli 1.0.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.
Files changed (159) hide show
  1. package/dist/__tests__/export-cli.test.d.ts +1 -0
  2. package/dist/__tests__/export-cli.test.js +70 -0
  3. package/dist/__tests__/tui-args-policy.test.d.ts +1 -0
  4. package/dist/__tests__/tui-args-policy.test.js +50 -0
  5. package/dist/acp-S2MHZOAD.mjs +23 -0
  6. package/dist/acp-UCCI44JY.mjs +25 -0
  7. package/dist/auth/credentials-store.d.ts +2 -0
  8. package/dist/auth/credentials-store.js +5 -0
  9. package/dist/auth/device-flow.d.ts +36 -0
  10. package/dist/auth/device-flow.js +189 -0
  11. package/dist/auth/jwt.d.ts +1 -0
  12. package/dist/auth/jwt.js +6 -0
  13. package/dist/auth/session.d.ts +67 -0
  14. package/dist/auth/session.js +86 -0
  15. package/dist/auth-login.d.ts +34 -0
  16. package/dist/auth-login.js +202 -0
  17. package/dist/auth-logout.d.ts +25 -0
  18. package/dist/auth-logout.js +115 -0
  19. package/dist/auth-status.d.ts +24 -0
  20. package/dist/auth-status.js +109 -0
  21. package/dist/backlog-generate.d.ts +11 -0
  22. package/dist/backlog-generate.js +308 -0
  23. package/dist/backlog-health.d.ts +11 -0
  24. package/dist/backlog-health.js +287 -0
  25. package/dist/bridge-login.d.ts +40 -0
  26. package/dist/bridge-login.js +277 -0
  27. package/dist/chunk-3PAYRI4G.mjs +2428 -0
  28. package/dist/chunk-M4CS3A25.mjs +2426 -0
  29. package/dist/commands/auth/login.d.ts +30 -0
  30. package/dist/commands/auth/login.js +164 -0
  31. package/dist/commands/auth/logout.d.ts +25 -0
  32. package/dist/commands/auth/logout.js +115 -0
  33. package/dist/commands/auth/status.d.ts +24 -0
  34. package/dist/commands/auth/status.js +109 -0
  35. package/dist/commands/backlog/generate.d.ts +11 -0
  36. package/dist/commands/backlog/generate.js +308 -0
  37. package/dist/commands/backlog/health.d.ts +11 -0
  38. package/dist/commands/backlog/health.js +287 -0
  39. package/dist/commands/bridge/login.d.ts +36 -0
  40. package/dist/commands/bridge/login.js +258 -0
  41. package/dist/commands/export.d.ts +35 -0
  42. package/dist/commands/export.js +485 -0
  43. package/dist/commands/marketplace-export.d.ts +21 -0
  44. package/dist/commands/marketplace-export.js +214 -0
  45. package/dist/commands/project-clean.d.ts +1 -0
  46. package/dist/commands/project-clean.js +126 -0
  47. package/dist/commands/repo/common.d.ts +105 -0
  48. package/dist/commands/repo/common.js +775 -0
  49. package/dist/commands/repo/detach.d.ts +2 -0
  50. package/dist/commands/repo/detach.js +120 -0
  51. package/dist/commands/repo/register.d.ts +21 -0
  52. package/dist/commands/repo/register.js +175 -0
  53. package/dist/commands/repo/sync.d.ts +22 -0
  54. package/dist/commands/repo/sync.js +873 -0
  55. package/dist/commands/skills-import-local.d.ts +16 -0
  56. package/dist/commands/skills-import-local.js +352 -0
  57. package/dist/commands/spec/drift-check.d.ts +3 -0
  58. package/dist/commands/spec/drift-check.js +186 -0
  59. package/dist/commands/spec/frontmatter.d.ts +11 -0
  60. package/dist/commands/spec/frontmatter.js +219 -0
  61. package/dist/commands/spec/lint.d.ts +11 -0
  62. package/dist/commands/spec/lint.js +499 -0
  63. package/dist/commands/spec/parse.d.ts +11 -0
  64. package/dist/commands/spec/parse.js +162 -0
  65. package/dist/export.d.ts +35 -0
  66. package/dist/export.js +485 -0
  67. package/dist/index.d.ts +11 -0
  68. package/dist/index.js +21 -0
  69. package/dist/main.d.ts +1 -0
  70. package/dist/main.js +115280 -0
  71. package/dist/marketplace-export.d.ts +21 -0
  72. package/dist/marketplace-export.js +214 -0
  73. package/dist/project-clean.d.ts +1 -0
  74. package/dist/project-clean.js +126 -0
  75. package/dist/project-context.d.ts +99 -0
  76. package/dist/project-context.js +376 -0
  77. package/dist/repo-common.d.ts +101 -0
  78. package/dist/repo-common.js +671 -0
  79. package/dist/repo-detach.d.ts +2 -0
  80. package/dist/repo-detach.js +102 -0
  81. package/dist/repo-ingest.d.ts +29 -0
  82. package/dist/repo-ingest.js +305 -0
  83. package/dist/repo-register.d.ts +21 -0
  84. package/dist/repo-register.js +175 -0
  85. package/dist/repo-sync.d.ts +16 -0
  86. package/dist/repo-sync.js +152 -0
  87. package/dist/resources/prompt-loader.d.ts +1 -0
  88. package/dist/resources/prompt-loader.js +62 -0
  89. package/dist/resources/prompts/README.md +21 -0
  90. package/dist/resources/prompts/prompts/repo-analysis.prompt.md +126 -0
  91. package/dist/resources/prompts/repo-analysis.prompt.md +151 -0
  92. package/dist/resources/prompts/repo-sync-analysis.prompt.md +85 -0
  93. package/dist/skills-import-local.d.ts +16 -0
  94. package/dist/skills-import-local.js +352 -0
  95. package/dist/spec-drift-check.d.ts +3 -0
  96. package/dist/spec-drift-check.js +186 -0
  97. package/dist/spec-frontmatter.d.ts +11 -0
  98. package/dist/spec-frontmatter.js +219 -0
  99. package/dist/spec-lint.d.ts +11 -0
  100. package/dist/spec-lint.js +499 -0
  101. package/dist/spec-parse.d.ts +11 -0
  102. package/dist/spec-parse.js +162 -0
  103. package/dist/stubs/dotenv.d.ts +5 -0
  104. package/dist/stubs/dotenv.js +6 -0
  105. package/dist/stubs/typeorm.d.ts +22 -0
  106. package/dist/stubs/typeorm.js +28 -0
  107. package/dist/tui/app.d.ts +7 -0
  108. package/dist/tui/app.js +122 -0
  109. package/dist/tui/args.d.ts +8 -0
  110. package/dist/tui/args.js +57 -0
  111. package/dist/tui/capabilities/policy.d.ts +7 -0
  112. package/dist/tui/capabilities/policy.js +64 -0
  113. package/dist/tui/components/frame.d.ts +8 -0
  114. package/dist/tui/components/frame.js +8 -0
  115. package/dist/tui/components/status-bar.d.ts +8 -0
  116. package/dist/tui/components/status-bar.js +8 -0
  117. package/dist/tui/index.d.ts +2 -0
  118. package/dist/tui/index.js +23 -0
  119. package/dist/tui/index.mjs +7563 -0
  120. package/dist/tui/keymap/use-global-keymap.d.ts +19 -0
  121. package/dist/tui/keymap/use-global-keymap.js +82 -0
  122. package/dist/tui/navigation/nav-items.d.ts +3 -0
  123. package/dist/tui/navigation/nav-items.js +18 -0
  124. package/dist/tui/screens/bridge.d.ts +8 -0
  125. package/dist/tui/screens/bridge.js +19 -0
  126. package/dist/tui/screens/decisions.d.ts +5 -0
  127. package/dist/tui/screens/decisions.js +28 -0
  128. package/dist/tui/screens/export.d.ts +5 -0
  129. package/dist/tui/screens/export.js +16 -0
  130. package/dist/tui/screens/home.d.ts +5 -0
  131. package/dist/tui/screens/home.js +33 -0
  132. package/dist/tui/screens/locked.d.ts +5 -0
  133. package/dist/tui/screens/locked.js +9 -0
  134. package/dist/tui/screens/specs.d.ts +5 -0
  135. package/dist/tui/screens/specs.js +31 -0
  136. package/dist/tui/services/client.d.ts +1 -0
  137. package/dist/tui/services/client.js +18 -0
  138. package/dist/tui/services/context-service.d.ts +19 -0
  139. package/dist/tui/services/context-service.js +246 -0
  140. package/dist/tui/shared-enums.d.ts +16 -0
  141. package/dist/tui/shared-enums.js +19 -0
  142. package/dist/tui/state/use-app-state.d.ts +35 -0
  143. package/dist/tui/state/use-app-state.js +177 -0
  144. package/dist/tui/types.d.ts +77 -0
  145. package/dist/tui/types.js +2 -0
  146. package/dist/tui-bundle.d.ts +1 -0
  147. package/dist/tui-bundle.js +5 -0
  148. package/dist/tui-entry.mjs +1407 -0
  149. package/dist/utils/cli-runtime.d.ts +5 -0
  150. package/dist/utils/cli-runtime.js +22 -0
  151. package/dist/utils/help-error.d.ts +7 -0
  152. package/dist/utils/help-error.js +14 -0
  153. package/dist/utils/interaction.d.ts +19 -0
  154. package/dist/utils/interaction.js +93 -0
  155. package/dist/utils/structured-log.d.ts +7 -0
  156. package/dist/utils/structured-log.js +112 -0
  157. package/dist/utils/trpc-url.d.ts +4 -0
  158. package/dist/utils/trpc-url.js +15 -0
  159. package/package.json +59 -0
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import { CredentialsStore } from './auth/credentials-store';
3
+ type ExportFormat = 'agents-md' | 'claude-md' | 'cursorrules' | 'gemini-md';
4
+ type ExportMode = 'global' | 'scoped';
5
+ type ExportDeliveryMode = 'download' | 'copy' | 'commit' | 'pr';
6
+ type ExportCommand = 'generate' | 'status' | 'discover' | 'preview';
7
+ interface CLIOptions {
8
+ command: ExportCommand;
9
+ projectId?: string;
10
+ format?: ExportFormat;
11
+ output?: string;
12
+ anchors?: string[];
13
+ mode: ExportMode;
14
+ scope?: string;
15
+ delivery: ExportDeliveryMode;
16
+ json: boolean;
17
+ branch?: string;
18
+ baseBranch?: string;
19
+ commitMessage?: string;
20
+ prTitle?: string;
21
+ prBody?: string;
22
+ apiUrl: string;
23
+ }
24
+ interface Deps {
25
+ createClient: (apiUrl: string, organizationId: string, authToken?: string) => any;
26
+ writeFile: (filePath: string, content: string) => void;
27
+ stdout: (content: string) => void;
28
+ stderr: (content: string) => void;
29
+ credentialsStore: CredentialsStore;
30
+ }
31
+ declare function normalizeTrpcUrl(apiUrl: string): string;
32
+ declare function parseArgs(args: string[]): CLIOptions;
33
+ export declare function runExportCli(args: string[], deps?: Deps): Promise<number>;
34
+ declare function main(): Promise<void>;
35
+ export { main, parseArgs, normalizeTrpcUrl };
package/dist/export.js ADDED
@@ -0,0 +1,485 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.runExportCli = runExportCli;
38
+ exports.main = main;
39
+ exports.parseArgs = parseArgs;
40
+ exports.normalizeTrpcUrl = normalizeTrpcUrl;
41
+ const client_1 = require("@trpc/client");
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const credentials_store_1 = require("./auth/credentials-store");
45
+ const project_context_1 = require("./project-context");
46
+ const structured_log_1 = require("./utils/structured-log");
47
+ const defaultDeps = {
48
+ createClient: (apiUrl, organizationId, authToken) => (0, client_1.createTRPCProxyClient)({
49
+ links: [
50
+ (0, client_1.httpBatchLink)({
51
+ url: normalizeTrpcUrl(apiUrl),
52
+ headers: {
53
+ 'x-organization-id': organizationId,
54
+ authorization: authToken ? `Bearer ${authToken}` : '',
55
+ },
56
+ }),
57
+ ],
58
+ }),
59
+ writeFile: (filePath, content) => {
60
+ const dir = path.dirname(filePath);
61
+ fs.mkdirSync(dir, { recursive: true });
62
+ fs.writeFileSync(filePath, content, 'utf-8');
63
+ },
64
+ stdout: (content) => process.stdout.write(content),
65
+ stderr: (content) => process.stderr.write(content),
66
+ credentialsStore: new credentials_store_1.CredentialsStore(),
67
+ };
68
+ function normalizeTrpcUrl(apiUrl) {
69
+ if (apiUrl.endsWith('/trpc')) {
70
+ return apiUrl;
71
+ }
72
+ if (apiUrl.endsWith('/')) {
73
+ return `${apiUrl}trpc`;
74
+ }
75
+ return `${apiUrl}/trpc`;
76
+ }
77
+ function printHelp(stderr) {
78
+ stderr(`
79
+ export - Generate and deliver agent context exports
80
+
81
+ USAGE:
82
+ spekn export discover --project <uuid> [options]
83
+ spekn export preview --project <uuid> --format <agents-md|claude-md|cursorrules|gemini-md> [options]
84
+ spekn export --project <uuid> --format <agents-md|claude-md|cursorrules|gemini-md> [options]
85
+ spekn export status --project <uuid> --format <agents-md|claude-md|cursorrules|gemini-md> [options]
86
+
87
+ OPTIONS:
88
+ --project <uuid> Project ID (optional if .spekn/context is present)
89
+ --format <format> Export format: agents-md | claude-md | cursorrules | gemini-md (required)
90
+ --output <path> Write output to file (generate-only backward-compat mode)
91
+ --anchors <a,b,c> Comma-separated anchor list
92
+ --mode <mode> Export mode: global | scoped (default: global)
93
+ --scope <path> Scope folder path when mode=scoped
94
+ --delivery <mode> Delivery: download | copy | commit | pr (default: download)
95
+ --branch <name> Target branch for commit/pr delivery
96
+ --base-branch <name> Base branch for branch creation
97
+ --commit-message <m> Commit message override
98
+ --pr-title <title> PR title (delivery=pr)
99
+ --pr-body <body> PR body (delivery=pr)
100
+ --json Output machine-readable JSON
101
+ --api-url <url> API base URL (default: SPEKN_API_URL or https://app.spekn.com)
102
+ --help Show help
103
+ `);
104
+ }
105
+ function parseArgs(args) {
106
+ const command = args[0] === 'status' ? 'status' : args[0] === 'discover' ? 'discover' : args[0] === 'preview' ? 'preview' : 'generate';
107
+ const parseArgs = command === 'generate' ? args : args.slice(1);
108
+ let projectId = '';
109
+ let format = '';
110
+ let output;
111
+ let anchors;
112
+ let mode = 'global';
113
+ let scope;
114
+ let delivery = 'download';
115
+ let json = false;
116
+ let branch;
117
+ let baseBranch;
118
+ let commitMessage;
119
+ let prTitle;
120
+ let prBody;
121
+ let apiUrl = process.env.SPEKN_API_URL || 'https://app.spekn.com';
122
+ for (let index = 0; index < parseArgs.length; index++) {
123
+ const arg = parseArgs[index];
124
+ if (arg === '--help' || arg === '-h') {
125
+ throw new Error('__HELP__');
126
+ }
127
+ if (arg === '--json') {
128
+ json = true;
129
+ continue;
130
+ }
131
+ if (arg === '--project' && parseArgs[index + 1]) {
132
+ projectId = parseArgs[++index];
133
+ continue;
134
+ }
135
+ if (arg.startsWith('--project=')) {
136
+ projectId = arg.slice('--project='.length);
137
+ continue;
138
+ }
139
+ if (arg === '--format' && parseArgs[index + 1]) {
140
+ format = parseArgs[++index];
141
+ continue;
142
+ }
143
+ if (arg.startsWith('--format=')) {
144
+ format = arg.slice('--format='.length);
145
+ continue;
146
+ }
147
+ if (arg === '--output' && parseArgs[index + 1]) {
148
+ output = parseArgs[++index];
149
+ continue;
150
+ }
151
+ if (arg.startsWith('--output=')) {
152
+ output = arg.slice('--output='.length);
153
+ continue;
154
+ }
155
+ if (arg === '--anchors' && parseArgs[index + 1]) {
156
+ anchors = parseArgs[++index]
157
+ .split(',')
158
+ .map((entry) => entry.trim())
159
+ .filter(Boolean);
160
+ continue;
161
+ }
162
+ if (arg.startsWith('--anchors=')) {
163
+ anchors = arg
164
+ .slice('--anchors='.length)
165
+ .split(',')
166
+ .map((entry) => entry.trim())
167
+ .filter(Boolean);
168
+ continue;
169
+ }
170
+ if (arg === '--mode' && parseArgs[index + 1]) {
171
+ mode = parseArgs[++index];
172
+ continue;
173
+ }
174
+ if (arg.startsWith('--mode=')) {
175
+ mode = arg.slice('--mode='.length);
176
+ continue;
177
+ }
178
+ if (arg === '--scope' && parseArgs[index + 1]) {
179
+ scope = parseArgs[++index];
180
+ continue;
181
+ }
182
+ if (arg.startsWith('--scope=')) {
183
+ scope = arg.slice('--scope='.length);
184
+ continue;
185
+ }
186
+ if (arg === '--delivery' && parseArgs[index + 1]) {
187
+ delivery = parseArgs[++index];
188
+ continue;
189
+ }
190
+ if (arg.startsWith('--delivery=')) {
191
+ delivery = arg.slice('--delivery='.length);
192
+ continue;
193
+ }
194
+ if (arg === '--branch' && parseArgs[index + 1]) {
195
+ branch = parseArgs[++index];
196
+ continue;
197
+ }
198
+ if (arg.startsWith('--branch=')) {
199
+ branch = arg.slice('--branch='.length);
200
+ continue;
201
+ }
202
+ if (arg === '--base-branch' && parseArgs[index + 1]) {
203
+ baseBranch = parseArgs[++index];
204
+ continue;
205
+ }
206
+ if (arg.startsWith('--base-branch=')) {
207
+ baseBranch = arg.slice('--base-branch='.length);
208
+ continue;
209
+ }
210
+ if (arg === '--commit-message' && parseArgs[index + 1]) {
211
+ commitMessage = parseArgs[++index];
212
+ continue;
213
+ }
214
+ if (arg.startsWith('--commit-message=')) {
215
+ commitMessage = arg.slice('--commit-message='.length);
216
+ continue;
217
+ }
218
+ if (arg === '--pr-title' && parseArgs[index + 1]) {
219
+ prTitle = parseArgs[++index];
220
+ continue;
221
+ }
222
+ if (arg.startsWith('--pr-title=')) {
223
+ prTitle = arg.slice('--pr-title='.length);
224
+ continue;
225
+ }
226
+ if (arg === '--pr-body' && parseArgs[index + 1]) {
227
+ prBody = parseArgs[++index];
228
+ continue;
229
+ }
230
+ if (arg.startsWith('--pr-body=')) {
231
+ prBody = arg.slice('--pr-body='.length);
232
+ continue;
233
+ }
234
+ if (arg === '--api-url' && parseArgs[index + 1]) {
235
+ apiUrl = parseArgs[++index];
236
+ continue;
237
+ }
238
+ if (arg.startsWith('--api-url=')) {
239
+ apiUrl = arg.slice('--api-url='.length);
240
+ continue;
241
+ }
242
+ }
243
+ if (command !== 'discover' && !['agents-md', 'claude-md', 'cursorrules', 'gemini-md'].includes(format)) {
244
+ throw new Error('Missing or invalid --format. Allowed values: agents-md, claude-md, cursorrules, gemini-md');
245
+ }
246
+ if (!['global', 'scoped'].includes(mode)) {
247
+ throw new Error('Invalid --mode. Allowed values: global, scoped');
248
+ }
249
+ if (mode === 'scoped' && !scope) {
250
+ throw new Error('Missing --scope when --mode=scoped');
251
+ }
252
+ if (!['download', 'copy', 'commit', 'pr'].includes(delivery)) {
253
+ throw new Error('Invalid --delivery. Allowed values: download, copy, commit, pr');
254
+ }
255
+ return {
256
+ command,
257
+ projectId,
258
+ format: format,
259
+ output,
260
+ anchors,
261
+ mode,
262
+ scope,
263
+ delivery,
264
+ json,
265
+ branch,
266
+ baseBranch,
267
+ commitMessage,
268
+ prTitle,
269
+ prBody,
270
+ apiUrl,
271
+ };
272
+ }
273
+ async function runExportCli(args, deps = defaultDeps) {
274
+ try {
275
+ const options = parseArgs(args);
276
+ const emit = (payload) => {
277
+ deps.stdout(`${JSON.stringify(payload, null, 2)}\n`);
278
+ };
279
+ (0, structured_log_1.appendCliStructuredLog)({
280
+ source: 'cli.export',
281
+ level: 'info',
282
+ message: `Starting export ${options.command}`,
283
+ details: {
284
+ format: options.format,
285
+ mode: options.mode,
286
+ delivery: options.delivery,
287
+ output: options.output,
288
+ apiUrl: options.apiUrl,
289
+ },
290
+ });
291
+ const storedToken = await deps.credentialsStore.getValidToken();
292
+ const authToken = storedToken ?? process.env.SPEKN_AUTH_TOKEN;
293
+ const storedCreds = deps.credentialsStore.load();
294
+ const context = (0, project_context_1.resolveProjectContext)({
295
+ explicitProjectId: options.projectId,
296
+ repoPath: process.cwd(),
297
+ credentialsOrganizationId: storedCreds?.organizationId,
298
+ envOrganizationId: process.env.SPEKN_ORGANIZATION_ID,
299
+ });
300
+ const client = deps.createClient(options.apiUrl, context.organizationId, authToken ?? undefined);
301
+ if (options.command === 'discover') {
302
+ const result = await client.export.discover.query({
303
+ projectId: context.projectId,
304
+ });
305
+ if (options.json) {
306
+ emit(result);
307
+ }
308
+ else {
309
+ deps.stdout(`Plan: ${result.plan}\n`);
310
+ deps.stdout(`Modes: ${result.modes.join(', ')}\n`);
311
+ deps.stdout('Formats:\n');
312
+ for (const format of result.formats) {
313
+ deps.stdout(`- ${format.id} (${format.filename})\n`);
314
+ }
315
+ deps.stdout('Delivery:\n');
316
+ for (const delivery of result.delivery) {
317
+ deps.stdout(`- ${delivery.mode}: ${delivery.available ? 'available' : `unavailable (${delivery.reason})`}\n`);
318
+ }
319
+ }
320
+ return 0;
321
+ }
322
+ if (options.command === 'preview') {
323
+ const result = await client.export.preview.query({
324
+ projectId: context.projectId,
325
+ formatId: options.format,
326
+ anchorFilter: options.anchors,
327
+ mode: options.mode,
328
+ scopePath: options.scope,
329
+ });
330
+ if (options.json) {
331
+ emit(result);
332
+ }
333
+ else {
334
+ deps.stdout(result.content);
335
+ deps.stdout('\n');
336
+ }
337
+ return 0;
338
+ }
339
+ if (options.command === 'status') {
340
+ const result = await client.export.delivery.status.query({
341
+ projectId: context.projectId,
342
+ formatId: options.format,
343
+ mode: options.mode,
344
+ scopePath: options.scope,
345
+ anchorFilter: options.anchors,
346
+ });
347
+ if (options.json) {
348
+ emit(result);
349
+ }
350
+ else {
351
+ deps.stdout(`Status: ${result.overall}\n`);
352
+ for (const target of result.targets) {
353
+ deps.stdout(`- ${target.path} [${target.kind}] -> ${target.status}\n`);
354
+ }
355
+ }
356
+ return 0;
357
+ }
358
+ // Backward-compatible single output mode.
359
+ if (options.output && options.delivery === 'download') {
360
+ const result = await client.export.generate.mutate({
361
+ projectId: context.projectId,
362
+ formatId: options.format,
363
+ anchorFilter: options.anchors,
364
+ mode: options.mode,
365
+ scopePath: options.scope,
366
+ });
367
+ const resolvedPath = path.resolve(process.cwd(), options.output);
368
+ deps.writeFile(resolvedPath, result.content);
369
+ if (options.json) {
370
+ emit({
371
+ delivery: 'download',
372
+ targets: [{ path: resolvedPath, kind: 'entrypoint' }],
373
+ anchorCount: result.anchorCount,
374
+ specVersion: result.specVersion,
375
+ warnings: result.warnings ?? [],
376
+ });
377
+ }
378
+ else {
379
+ deps.stdout(`Exported ${result.anchorCount} anchors to ${resolvedPath}\n`);
380
+ }
381
+ return 0;
382
+ }
383
+ if (options.delivery === 'commit') {
384
+ const result = await client.export.delivery.commit.mutate({
385
+ projectId: context.projectId,
386
+ formatId: options.format,
387
+ mode: options.mode,
388
+ scopePath: options.scope,
389
+ branch: options.branch,
390
+ baseBranch: options.baseBranch,
391
+ commitMessage: options.commitMessage,
392
+ anchorFilter: options.anchors,
393
+ });
394
+ if (options.json) {
395
+ emit(result);
396
+ }
397
+ else {
398
+ deps.stdout(`Committed to ${result.branch}: ${result.commitSha}\n`);
399
+ for (const fileUrl of result.fileUrls || [])
400
+ deps.stdout(`- ${fileUrl}\n`);
401
+ }
402
+ return 0;
403
+ }
404
+ if (options.delivery === 'pr') {
405
+ const result = await client.export.delivery.createPr.mutate({
406
+ projectId: context.projectId,
407
+ formatId: options.format,
408
+ mode: options.mode,
409
+ scopePath: options.scope,
410
+ branch: options.branch,
411
+ baseBranch: options.baseBranch,
412
+ commitMessage: options.commitMessage,
413
+ prTitle: options.prTitle,
414
+ prBody: options.prBody,
415
+ anchorFilter: options.anchors,
416
+ });
417
+ if (options.json) {
418
+ emit(result);
419
+ }
420
+ else {
421
+ deps.stdout(`PR #${result.prNumber}: ${result.prUrl}\n`);
422
+ deps.stdout(`Commit: ${result.commitSha} on ${result.branch}\n`);
423
+ }
424
+ return 0;
425
+ }
426
+ const plan = await client.export.delivery.previewTarget.query({
427
+ projectId: context.projectId,
428
+ formatId: options.format,
429
+ mode: options.mode,
430
+ scopePath: options.scope,
431
+ anchorFilter: options.anchors,
432
+ });
433
+ if (options.delivery === 'copy') {
434
+ if (options.json) {
435
+ emit(plan);
436
+ }
437
+ else {
438
+ for (const target of plan.targets) {
439
+ deps.stdout(`\n### ${target.path}\n\n`);
440
+ deps.stdout(target.content);
441
+ deps.stdout('\n');
442
+ }
443
+ }
444
+ return 0;
445
+ }
446
+ const writtenTargets = [];
447
+ for (const target of plan.targets) {
448
+ const resolvedPath = path.resolve(process.cwd(), target.path);
449
+ deps.writeFile(resolvedPath, target.content);
450
+ writtenTargets.push({ path: resolvedPath, kind: target.kind });
451
+ if (!options.json) {
452
+ deps.stdout(`Wrote ${target.kind} -> ${resolvedPath}\n`);
453
+ }
454
+ }
455
+ if (options.json) {
456
+ emit({ delivery: 'download', targets: writtenTargets, warnings: plan.warnings ?? [] });
457
+ }
458
+ else if (plan.warnings?.length) {
459
+ for (const warning of plan.warnings)
460
+ deps.stdout(`Warning: ${warning}\n`);
461
+ }
462
+ return 0;
463
+ }
464
+ catch (error) {
465
+ if (error instanceof Error && error.message === '__HELP__') {
466
+ printHelp(deps.stderr);
467
+ return 0;
468
+ }
469
+ const message = error instanceof Error ? error.message : String(error);
470
+ deps.stderr(`Error: ${message}\n`);
471
+ (0, structured_log_1.appendCliStructuredLog)({
472
+ source: 'cli.export',
473
+ level: 'error',
474
+ message,
475
+ });
476
+ return 1;
477
+ }
478
+ }
479
+ async function main() {
480
+ const exitCode = await runExportCli(process.argv.slice(2));
481
+ process.exit(exitCode);
482
+ }
483
+ if (require.main === module) {
484
+ void main();
485
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * spekn - CLI tools for SDD platform
3
+ *
4
+ * This package provides command-line tools for working with specifications and backlog management.
5
+ */
6
+ export { main as specParse } from "./commands/spec/parse";
7
+ export { main as specLint } from "./commands/spec/lint";
8
+ export { main as backlogGenerate } from "./commands/backlog/generate";
9
+ export { main as backlogHealth } from "./commands/backlog/health";
10
+ export { main as specDriftCheck } from "./commands/spec/drift-check";
11
+ export { runExportCli as exportContext } from "./commands/export";
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * spekn - CLI tools for SDD platform
4
+ *
5
+ * This package provides command-line tools for working with specifications and backlog management.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.exportContext = exports.specDriftCheck = exports.backlogHealth = exports.backlogGenerate = exports.specLint = exports.specParse = void 0;
9
+ var parse_1 = require("./commands/spec/parse");
10
+ Object.defineProperty(exports, "specParse", { enumerable: true, get: function () { return parse_1.main; } });
11
+ var lint_1 = require("./commands/spec/lint");
12
+ Object.defineProperty(exports, "specLint", { enumerable: true, get: function () { return lint_1.main; } });
13
+ var generate_1 = require("./commands/backlog/generate");
14
+ Object.defineProperty(exports, "backlogGenerate", { enumerable: true, get: function () { return generate_1.main; } });
15
+ var health_1 = require("./commands/backlog/health");
16
+ Object.defineProperty(exports, "backlogHealth", { enumerable: true, get: function () { return health_1.main; } });
17
+ var drift_check_1 = require("./commands/spec/drift-check");
18
+ Object.defineProperty(exports, "specDriftCheck", { enumerable: true, get: function () { return drift_check_1.main; } });
19
+ var export_1 = require("./commands/export");
20
+ Object.defineProperty(exports, "exportContext", { enumerable: true, get: function () { return export_1.runExportCli; } });
21
+ // TUI is ESM-only (ink v5) — use `spekn tui` or import the .mjs bundle directly
package/dist/main.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};