@devcortex/cli 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/commands/export.d.ts +9 -0
  2. package/dist/commands/export.d.ts.map +1 -0
  3. package/dist/commands/export.js +49 -0
  4. package/dist/commands/export.js.map +1 -0
  5. package/dist/commands/import.d.ts +21 -0
  6. package/dist/commands/import.d.ts.map +1 -0
  7. package/dist/commands/import.js +237 -0
  8. package/dist/commands/import.js.map +1 -0
  9. package/dist/commands/init.d.ts +22 -0
  10. package/dist/commands/init.d.ts.map +1 -0
  11. package/dist/commands/init.js +225 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/issue.d.ts +8 -0
  14. package/dist/commands/issue.d.ts.map +1 -0
  15. package/dist/commands/issue.js +42 -0
  16. package/dist/commands/issue.js.map +1 -0
  17. package/dist/commands/keys.d.ts +23 -0
  18. package/dist/commands/keys.d.ts.map +1 -0
  19. package/dist/commands/keys.js +133 -0
  20. package/dist/commands/keys.js.map +1 -0
  21. package/dist/commands/list.d.ts +20 -0
  22. package/dist/commands/list.d.ts.map +1 -0
  23. package/dist/commands/list.js +163 -0
  24. package/dist/commands/list.js.map +1 -0
  25. package/dist/commands/login.d.ts +9 -0
  26. package/dist/commands/login.d.ts.map +1 -0
  27. package/dist/commands/login.js +91 -0
  28. package/dist/commands/login.js.map +1 -0
  29. package/dist/commands/logs.d.ts +22 -0
  30. package/dist/commands/logs.d.ts.map +1 -0
  31. package/dist/commands/logs.js +172 -0
  32. package/dist/commands/logs.js.map +1 -0
  33. package/dist/commands/start.d.ts +9 -0
  34. package/dist/commands/start.d.ts.map +1 -0
  35. package/dist/commands/start.js +88 -0
  36. package/dist/commands/start.js.map +1 -0
  37. package/dist/commands/status.d.ts +22 -0
  38. package/dist/commands/status.d.ts.map +1 -0
  39. package/dist/commands/status.js +179 -0
  40. package/dist/commands/status.js.map +1 -0
  41. package/dist/commands/test-mcp.d.ts +7 -0
  42. package/dist/commands/test-mcp.d.ts.map +1 -0
  43. package/dist/commands/test-mcp.js +115 -0
  44. package/dist/commands/test-mcp.js.map +1 -0
  45. package/dist/commands/update.d.ts +9 -0
  46. package/dist/commands/update.d.ts.map +1 -0
  47. package/dist/commands/update.js +124 -0
  48. package/dist/commands/update.js.map +1 -0
  49. package/dist/index.d.ts +4 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +48 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/lib/api.d.ts +8 -0
  54. package/dist/lib/api.d.ts.map +1 -0
  55. package/dist/lib/api.js +30 -0
  56. package/dist/lib/api.js.map +1 -0
  57. package/dist/lib/auth.d.ts +20 -0
  58. package/dist/lib/auth.d.ts.map +1 -0
  59. package/dist/lib/auth.js +16 -0
  60. package/dist/lib/auth.js.map +1 -0
  61. package/dist/lib/config.d.ts +16 -0
  62. package/dist/lib/config.d.ts.map +1 -0
  63. package/dist/lib/config.js +29 -0
  64. package/dist/lib/config.js.map +1 -0
  65. package/package.json +41 -0
@@ -0,0 +1,9 @@
1
+ import type { Command } from 'commander';
2
+ export interface UpdateOptions {
3
+ agent?: string;
4
+ apiUrl?: string;
5
+ watch?: boolean;
6
+ }
7
+ export declare function runUpdate(opts: UpdateOptions, cwd?: string): Promise<string>;
8
+ export declare function registerUpdate(program: Command): void;
9
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAWD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmDzF;AAgFD,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAerD"}
@@ -0,0 +1,124 @@
1
+ import * as clack from '@clack/prompts';
2
+ import { writeFileSync, existsSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { readLinkFile, detectStack, substituteStackCommands } from './init.js';
5
+ import { apiJson } from '../lib/api.js';
6
+ export async function runUpdate(opts, cwd = process.cwd()) {
7
+ // AC-5: Check link file
8
+ const link = readLinkFile(cwd);
9
+ if (!link) {
10
+ console.error('✗ No project linked. Run dcx init first.');
11
+ process.exit(1);
12
+ }
13
+ const agentFile = opts.agent === 'opencode' ? 'AGENTS.md' : 'CLAUDE.md';
14
+ const filePath = join(cwd, agentFile);
15
+ // Read old content for diff
16
+ const oldContent = existsSync(filePath) ? readFileSync(filePath, 'utf8') : '';
17
+ // AC-1: Fetch constitution
18
+ const res = await apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/constitution`, {}, opts.apiUrl ?? link.apiUrl);
19
+ const stack = detectStack(cwd);
20
+ const newContent = substituteStackCommands(res.content, stack);
21
+ // AC-4: No changes
22
+ if (newContent === oldContent) {
23
+ clack.note(`${agentFile} is already up to date`);
24
+ return newContent;
25
+ }
26
+ // AC-1: Overwrite file
27
+ writeFileSync(filePath, newContent);
28
+ // AC-2: Diff summary (count requirement lines)
29
+ const oldReqs = countReqLines(oldContent);
30
+ const newReqs = countReqLines(newContent);
31
+ const oldIssues = countIssueLines(oldContent);
32
+ const newIssues = countIssueLines(newContent);
33
+ const diff = [];
34
+ if (newReqs > oldReqs)
35
+ diff.push(`+ ${newReqs - oldReqs} requirements added`);
36
+ if (newReqs < oldReqs)
37
+ diff.push(`- ${oldReqs - newReqs} requirements removed`);
38
+ if (newIssues !== oldIssues)
39
+ diff.push(`~ issues: ${oldIssues} → ${newIssues}`);
40
+ clack.note([
41
+ `✔ ${agentFile} refreshed`,
42
+ ...diff,
43
+ `→ ${agentFile} is up to date (${newReqs} requirements, ${newIssues} issues)`,
44
+ ].join('\n'));
45
+ return newContent;
46
+ }
47
+ async function watchUpdate(opts, cwd = process.cwd()) {
48
+ const link = readLinkFile(cwd);
49
+ if (!link) {
50
+ console.error('✗ No project linked. Run dcx init first.');
51
+ process.exit(1);
52
+ }
53
+ const agentFile = opts.agent === 'opencode' ? 'AGENTS.md' : 'CLAUDE.md';
54
+ const apiUrlOverride = opts.apiUrl ?? link.apiUrl;
55
+ // Step 1: Full update immediately
56
+ console.log('DevCortex Watch — running initial update...');
57
+ await runUpdate(opts, cwd);
58
+ let lastPoll = new Date().toISOString();
59
+ console.log(`Watching for requirement changes every 60s. Press Ctrl+C to stop.\n`);
60
+ // Handle Ctrl+C gracefully
61
+ process.on('SIGINT', () => {
62
+ console.log('\nStopped watching');
63
+ process.exit(0);
64
+ });
65
+ // Poll every 60 seconds
66
+ const poll = setInterval(async () => {
67
+ try {
68
+ const res = await apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/requirements?since=${encodeURIComponent(lastPoll)}`, {}, apiUrlOverride);
69
+ const changedCount = res.total ?? res.data?.length ?? 0;
70
+ const pollTime = new Date().toISOString();
71
+ if (changedCount > 0) {
72
+ // Regenerate the constitution file
73
+ try {
74
+ const constitution = await apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/constitution`, {}, apiUrlOverride);
75
+ const filePath = join(cwd, agentFile);
76
+ const stack = detectStack(cwd);
77
+ writeFileSync(filePath, substituteStackCommands(constitution.content, stack));
78
+ console.log(`✔ ${agentFile} updated — ${changedCount} requirement(s) changed`);
79
+ }
80
+ catch {
81
+ console.error(`✗ Failed to regenerate ${agentFile}`);
82
+ }
83
+ }
84
+ lastPoll = pollTime;
85
+ }
86
+ catch {
87
+ // Silently continue on poll failure
88
+ }
89
+ }, 60000);
90
+ // Keep process alive
91
+ await new Promise(() => {
92
+ // This promise never resolves — the process stays alive until SIGINT
93
+ // clearInterval cleanup happens in the SIGINT handler above
94
+ process.on('SIGTERM', () => {
95
+ clearInterval(poll);
96
+ console.log('\nStopped watching');
97
+ process.exit(0);
98
+ });
99
+ });
100
+ }
101
+ function countReqLines(content) {
102
+ return (content.match(/^- REQ-/gm) ?? []).length;
103
+ }
104
+ function countIssueLines(content) {
105
+ return (content.match(/^- ISS-/gm) ?? []).length;
106
+ }
107
+ export function registerUpdate(program) {
108
+ program
109
+ .command('update')
110
+ .description('Refresh CLAUDE.md from the live database')
111
+ .option('--agent <name>', 'Agent type: claude (default) | opencode')
112
+ .option('--api-url <url>', 'API URL override')
113
+ .option('--watch', 'Watch for requirement changes and auto-update CLAUDE.md every 60s')
114
+ .action(async (opts) => {
115
+ if (opts.watch) {
116
+ await watchUpdate(opts);
117
+ }
118
+ else {
119
+ clack.intro('DevCortex Update');
120
+ await runUpdate(opts);
121
+ }
122
+ });
123
+ }
124
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAiBxC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACtE,wBAAwB;IACxB,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;IACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEtC,4BAA4B;IAC5B,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9E,2BAA2B;IAC3B,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,kBAAkB,IAAI,CAAC,OAAO,aAAa,IAAI,CAAC,SAAS,eAAe,EACxE,EAAE,EACF,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAC3B,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,uBAAuB,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE/D,mBAAmB;IACnB,IAAI,UAAU,KAAK,UAAU,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,wBAAwB,CAAC,CAAC;QACjD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,uBAAuB;IACvB,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEpC,+CAA+C;IAC/C,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAE9C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,GAAG,OAAO,qBAAqB,CAAC,CAAC;IAC9E,IAAI,OAAO,GAAG,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,GAAG,OAAO,uBAAuB,CAAC,CAAC;IAChF,IAAI,SAAS,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,SAAS,MAAM,SAAS,EAAE,CAAC,CAAC;IAEhF,KAAK,CAAC,IAAI,CAAC;QACT,KAAK,SAAS,YAAY;QAC1B,GAAG,IAAI;QACP,KAAK,SAAS,mBAAmB,OAAO,kBAAkB,SAAS,UAAU;KAC9E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEd,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAmB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACjE,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;IACxE,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAElD,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC3D,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE3B,IAAI,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;IAEnF,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,OAAO,CACvB,kBAAkB,IAAI,CAAC,OAAO,aAAa,IAAI,CAAC,SAAS,uBAAuB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAC9G,EAAE,EACF,cAAc,CACf,CAAC;YAEF,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAE1C,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;gBACrB,mCAAmC;gBACnC,IAAI,CAAC;oBACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAChC,kBAAkB,IAAI,CAAC,OAAO,aAAa,IAAI,CAAC,SAAS,eAAe,EACxE,EAAE,EACF,cAAc,CACf,CAAC;oBACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;oBACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;oBAC/B,aAAa,CAAC,QAAQ,EAAE,uBAAuB,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;oBAC9E,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,cAAc,YAAY,yBAAyB,CAAC,CAAC;gBACjF,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,KAAK,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YAED,QAAQ,GAAG,QAAQ,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC,EAAE,KAAK,CAAC,CAAC;IAEV,qBAAqB;IACrB,MAAM,IAAI,OAAO,CAAQ,GAAG,EAAE;QAC5B,qEAAqE;QACrE,4DAA4D;QAC5D,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACzB,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;AACnD,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,gBAAgB,EAAE,yCAAyC,CAAC;SACnE,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;SAC7C,MAAM,CAAC,SAAS,EAAE,mEAAmE,CAAC;SACtF,MAAM,CAAC,KAAK,EAAE,IAAmB,EAAE,EAAE;QACpC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAChC,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ export declare const program: Command;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,OAAO,SAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ // REQ-059: DevCortex CLI Foundation — @devcortex/cli
3
+ import { Command } from 'commander';
4
+ import { createRequire } from 'node:module';
5
+ import { registerLogin } from './commands/login.js';
6
+ import { registerInit } from './commands/init.js';
7
+ import { registerStart } from './commands/start.js';
8
+ import { registerKeys } from './commands/keys.js';
9
+ import { registerStatus } from './commands/status.js';
10
+ import { registerLogs } from './commands/logs.js';
11
+ import { registerUpdate } from './commands/update.js';
12
+ import { registerList } from './commands/list.js';
13
+ import { registerExport } from './commands/export.js';
14
+ import { registerImport } from './commands/import.js';
15
+ import { registerTestMcp } from './commands/test-mcp.js';
16
+ import { registerIssue } from './commands/issue.js';
17
+ const require = createRequire(import.meta.url);
18
+ const pkg = require('../package.json');
19
+ export const program = new Command();
20
+ program
21
+ .name('dcx')
22
+ .description('DevCortex CLI — connect AI agents to your project')
23
+ .version(pkg.version) // AC-3: --version outputs version
24
+ // AC-6: --api-url global flag
25
+ .option('--api-url <url>', 'Override API URL (default: http://localhost:3001)');
26
+ // AC-4: Register all commands
27
+ registerLogin(program);
28
+ registerInit(program);
29
+ registerStart(program);
30
+ registerKeys(program);
31
+ registerStatus(program);
32
+ registerLogs(program);
33
+ registerUpdate(program);
34
+ registerList(program);
35
+ registerExport(program);
36
+ registerImport(program);
37
+ registerTestMcp(program);
38
+ registerIssue(program);
39
+ // AC-7: Only parse argv when run directly (not when imported by tests)
40
+ import { fileURLToPath } from 'node:url';
41
+ const isMain = fileURLToPath(import.meta.url) === process.argv[1];
42
+ if (isMain) {
43
+ program.parseAsync(process.argv).catch((err) => {
44
+ console.error(`✗ ${err.message}`);
45
+ process.exit(1);
46
+ });
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,qDAAqD;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AAE9D,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAErC,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAE,kCAAkC;IACzD,8BAA8B;KAC7B,MAAM,CAAC,iBAAiB,EAAE,mDAAmD,CAAC,CAAC;AAElF,8BAA8B;AAC9B,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,aAAa,CAAC,OAAO,CAAC,CAAC;AACvB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,YAAY,CAAC,OAAO,CAAC,CAAC;AACtB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,cAAc,CAAC,OAAO,CAAC,CAAC;AACxB,eAAe,CAAC,OAAO,CAAC,CAAC;AACzB,aAAa,CAAC,OAAO,CAAC,CAAC;AAEvB,uEAAuE;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClE,IAAI,MAAM,EAAE,CAAC;IACX,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACtD,OAAO,CAAC,KAAK,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface ApiError {
2
+ status: number;
3
+ message: string;
4
+ }
5
+ export declare function apiRequest(path: string, options?: RequestInit, apiUrlOverride?: string): Promise<Response>;
6
+ export declare function apiJson<T>(path: string, options?: RequestInit, apiUrlOverride?: string): Promise<T>;
7
+ export declare function isApiReachable(apiUrl?: string): Promise<boolean>;
8
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,QAAQ,CAAC,CASnB;AAED,wBAAsB,OAAO,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhE"}
@@ -0,0 +1,30 @@
1
+ // API client — wraps fetch with auth header and base URL.
2
+ import { getApiUrl, getToken } from './config.js';
3
+ export async function apiRequest(path, options = {}, apiUrlOverride) {
4
+ const base = getApiUrl(apiUrlOverride);
5
+ const token = getToken();
6
+ const headers = {
7
+ 'Content-Type': 'application/json',
8
+ ...(options.headers ?? {}),
9
+ };
10
+ if (token)
11
+ headers['Authorization'] = `Bearer ${token}`;
12
+ return fetch(`${base}${path}`, { ...options, headers });
13
+ }
14
+ export async function apiJson(path, options = {}, apiUrlOverride) {
15
+ const res = await apiRequest(path, options, apiUrlOverride);
16
+ if (!res.ok) {
17
+ const body = await res.json().catch(() => ({}));
18
+ const msg = body?.error?.message ?? body?.message ?? `HTTP ${res.status}`;
19
+ const err = new Error(msg);
20
+ err.status = res.status;
21
+ throw err;
22
+ }
23
+ return res.json();
24
+ }
25
+ export function isApiReachable(apiUrl) {
26
+ return fetch(`${getApiUrl(apiUrl)}/health`)
27
+ .then((r) => r.ok)
28
+ .catch(() => false);
29
+ }
30
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOlD,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,UAAuB,EAAE,EACzB,cAAuB;IAEvB,MAAM,IAAI,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,OAAO,CAAC,OAAiC,IAAI,EAAE,CAAC;KACrD,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IACxD,OAAO,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAY,EACZ,UAAuB,EAAE,EACzB,cAAuB;IAEvB,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAC5D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAuD,CAAC;QACtG,MAAM,GAAG,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,IAAI,EAAE,OAAO,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1E,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,GAAG,CAA+B,CAAC;QACzD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACxB,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,OAAO,KAAK,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare function requireAuth(): string;
2
+ export interface LoginResponse {
3
+ token: string;
4
+ expiresIn?: number;
5
+ user: {
6
+ id: string;
7
+ name: string;
8
+ email: string;
9
+ orgMemberships?: Array<{
10
+ orgSlug: string;
11
+ }>;
12
+ };
13
+ }
14
+ export interface OrgProject {
15
+ id: string;
16
+ name: string;
17
+ orgSlug: string;
18
+ }
19
+ export declare function storeToken(loginData: LoginResponse): void;
20
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,CAAC,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC7C,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI,CAIzD"}
@@ -0,0 +1,16 @@
1
+ // Token management helpers.
2
+ import { config, getToken, isTokenExpired } from './config.js';
3
+ export function requireAuth() {
4
+ const token = getToken();
5
+ if (!token || isTokenExpired()) {
6
+ console.error('✗ Not logged in — run dcx login first');
7
+ process.exit(1);
8
+ }
9
+ return token;
10
+ }
11
+ export function storeToken(loginData) {
12
+ const expiry = new Date(Date.now() + (loginData.expiresIn ?? 86400) * 1000).toISOString();
13
+ config.set('token', loginData.token);
14
+ config.set('tokenExpiry', expiry);
15
+ }
16
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,UAAU,WAAW;IACzB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK,IAAI,cAAc,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD,MAAM,UAAU,UAAU,CAAC,SAAwB;IACjD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1F,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import Conf from 'conf';
2
+ export interface CliConfig {
3
+ apiUrl?: string;
4
+ token?: string;
5
+ tokenExpiry?: string;
6
+ defaultOrgSlug?: string;
7
+ defaultProjectId?: string;
8
+ watchEnabled?: boolean;
9
+ }
10
+ export declare const DEFAULT_API_URL = "https://api.devcortexai.com";
11
+ export declare const config: Conf<CliConfig>;
12
+ export declare function getApiUrl(override?: string): string;
13
+ export declare function getToken(): string | undefined;
14
+ export declare function isTokenExpired(): boolean;
15
+ export declare function clearAuth(): void;
16
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,eAAO,MAAM,MAAM,iBAIjB,CAAC;AAEH,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C;AAED,wBAAgB,cAAc,IAAI,OAAO,CAIxC;AAED,wBAAgB,SAAS,IAAI,IAAI,CAKhC"}
@@ -0,0 +1,29 @@
1
+ // REQ-059 AC-5: Config stored at ~/.devcortex/config.json via conf package.
2
+ import Conf from 'conf';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ export const DEFAULT_API_URL = 'https://api.devcortexai.com';
6
+ export const config = new Conf({
7
+ cwd: join(homedir(), '.devcortex'),
8
+ configName: 'config',
9
+ accessPropertiesByDotNotation: false,
10
+ });
11
+ export function getApiUrl(override) {
12
+ return override ?? config.get('apiUrl') ?? DEFAULT_API_URL;
13
+ }
14
+ export function getToken() {
15
+ return config.get('token');
16
+ }
17
+ export function isTokenExpired() {
18
+ const expiry = config.get('tokenExpiry');
19
+ if (!expiry)
20
+ return true;
21
+ return new Date(expiry) < new Date();
22
+ }
23
+ export function clearAuth() {
24
+ config.delete('token');
25
+ config.delete('tokenExpiry');
26
+ config.delete('defaultOrgSlug');
27
+ config.delete('defaultProjectId');
28
+ }
29
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWjC,MAAM,CAAC,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAE7D,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,IAAI,CAAY;IACxC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC;IAClC,UAAU,EAAE,QAAQ;IACpB,6BAA6B,EAAE,KAAK;CACrC,CAAC,CAAC;AAEH,MAAM,UAAU,SAAS,CAAC,QAAiB;IACzC,OAAO,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC7B,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAChC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACpC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@devcortex/cli",
3
+ "version": "1.3.0",
4
+ "description": "DevCortex CLI — structured requirements for agentic development",
5
+ "type": "module",
6
+ "bin": {
7
+ "dcx": "dist/index.js"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "engines": {
13
+ "node": ">=18.0.0"
14
+ },
15
+ "exports": {
16
+ ".": "./dist/index.js"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "dependencies": {
23
+ "commander": "^12.0.0",
24
+ "@clack/prompts": "^0.7.0",
25
+ "chalk": "^5.3.0",
26
+ "conf": "^12.0.0",
27
+ "socket.io-client": "^4.7.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.0.0",
31
+ "typescript": "^5.4.0",
32
+ "vitest": "^1.6.0"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc && node scripts/add-shebang.mjs && chmod +x dist/index.js",
36
+ "dev": "tsc --watch",
37
+ "test": "vitest run",
38
+ "typecheck": "tsc --noEmit",
39
+ "lint": "eslint src --ext .ts"
40
+ }
41
+ }