@context-forge/cli 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +116 -0
  3. package/dist/commands/build.d.ts +3 -0
  4. package/dist/commands/build.d.ts.map +1 -0
  5. package/dist/commands/build.js +51 -0
  6. package/dist/commands/build.js.map +1 -0
  7. package/dist/commands/check.d.ts +3 -0
  8. package/dist/commands/check.d.ts.map +1 -0
  9. package/dist/commands/check.js +13 -0
  10. package/dist/commands/check.js.map +1 -0
  11. package/dist/commands/config.d.ts +3 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +82 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/future.d.ts +3 -0
  16. package/dist/commands/future.d.ts.map +1 -0
  17. package/dist/commands/future.js +49 -0
  18. package/dist/commands/future.js.map +1 -0
  19. package/dist/commands/guides.d.ts +3 -0
  20. package/dist/commands/guides.d.ts.map +1 -0
  21. package/dist/commands/guides.js +116 -0
  22. package/dist/commands/guides.js.map +1 -0
  23. package/dist/commands/init.d.ts +3 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +36 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/next.d.ts +3 -0
  28. package/dist/commands/next.d.ts.map +1 -0
  29. package/dist/commands/next.js +80 -0
  30. package/dist/commands/next.js.map +1 -0
  31. package/dist/commands/project.d.ts +3 -0
  32. package/dist/commands/project.d.ts.map +1 -0
  33. package/dist/commands/project.js +239 -0
  34. package/dist/commands/project.js.map +1 -0
  35. package/dist/commands/prompt.d.ts +3 -0
  36. package/dist/commands/prompt.d.ts.map +1 -0
  37. package/dist/commands/prompt.js +111 -0
  38. package/dist/commands/prompt.js.map +1 -0
  39. package/dist/commands/status.d.ts +3 -0
  40. package/dist/commands/status.d.ts.map +1 -0
  41. package/dist/commands/status.js +79 -0
  42. package/dist/commands/status.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +47 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/output/formatter.d.ts +6 -0
  48. package/dist/output/formatter.d.ts.map +1 -0
  49. package/dist/output/formatter.js +9 -0
  50. package/dist/output/formatter.js.map +1 -0
  51. package/dist/output/styles.d.ts +15 -0
  52. package/dist/output/styles.d.ts.map +1 -0
  53. package/dist/output/styles.js +16 -0
  54. package/dist/output/styles.js.map +1 -0
  55. package/dist/output/tables.d.ts +6 -0
  56. package/dist/output/tables.d.ts.map +1 -0
  57. package/dist/output/tables.js +42 -0
  58. package/dist/output/tables.js.map +1 -0
  59. package/dist/utils/errors.d.ts +13 -0
  60. package/dist/utils/errors.d.ts.map +1 -0
  61. package/dist/utils/errors.js +27 -0
  62. package/dist/utils/errors.js.map +1 -0
  63. package/dist/utils/phaseShorthand.d.ts +23 -0
  64. package/dist/utils/phaseShorthand.d.ts.map +1 -0
  65. package/dist/utils/phaseShorthand.js +68 -0
  66. package/dist/utils/phaseShorthand.js.map +1 -0
  67. package/dist/utils/project.d.ts +28 -0
  68. package/dist/utils/project.d.ts.map +1 -0
  69. package/dist/utils/project.js +81 -0
  70. package/dist/utils/project.js.map +1 -0
  71. package/package.json +48 -0
@@ -0,0 +1,6 @@
1
+ export type OutputMode = 'terminal' | 'json';
2
+ /** Print structured data as formatted JSON to stdout. */
3
+ export declare function printJson(data: unknown): void;
4
+ /** Print raw text to stdout (no formatting, no trailing newline unless in text). */
5
+ export declare function printRaw(text: string): void;
6
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7C,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3C"}
@@ -0,0 +1,9 @@
1
+ /** Print structured data as formatted JSON to stdout. */
2
+ export function printJson(data) {
3
+ process.stdout.write(JSON.stringify(data, null, 2) + '\n');
4
+ }
5
+ /** Print raw text to stdout (no formatting, no trailing newline unless in text). */
6
+ export function printRaw(text) {
7
+ process.stdout.write(text);
8
+ }
9
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAEA,yDAAyD;AACzD,MAAM,UAAU,SAAS,CAAC,IAAa;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** Style for field labels (e.g. "Project:", "Phase:") */
2
+ export declare const label: import("chalk").ChalkInstance;
3
+ /** Style for field values */
4
+ export declare const value: import("chalk").ChalkInstance;
5
+ /** Style for section headings */
6
+ export declare const heading: import("chalk").ChalkInstance;
7
+ /** Style for secondary/subdued text */
8
+ export declare const dim: import("chalk").ChalkInstance;
9
+ /** Style for error messages */
10
+ export declare const error: import("chalk").ChalkInstance;
11
+ /** Style for success messages */
12
+ export declare const success: import("chalk").ChalkInstance;
13
+ /** Style for warning messages */
14
+ export declare const warn: import("chalk").ChalkInstance;
15
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/output/styles.ts"],"names":[],"mappings":"AAEA,yDAAyD;AACzD,eAAO,MAAM,KAAK,+BAAa,CAAC;AAEhC,6BAA6B;AAC7B,eAAO,MAAM,KAAK,+BAAa,CAAC;AAEhC,iCAAiC;AACjC,eAAO,MAAM,OAAO,+BAAuB,CAAC;AAE5C,uCAAuC;AACvC,eAAO,MAAM,GAAG,+BAAY,CAAC;AAE7B,+BAA+B;AAC/B,eAAO,MAAM,KAAK,+BAAY,CAAC;AAE/B,iCAAiC;AACjC,eAAO,MAAM,OAAO,+BAAc,CAAC;AAEnC,iCAAiC;AACjC,eAAO,MAAM,IAAI,+BAAe,CAAC"}
@@ -0,0 +1,16 @@
1
+ import chalk from 'chalk';
2
+ /** Style for field labels (e.g. "Project:", "Phase:") */
3
+ export const label = chalk.bold;
4
+ /** Style for field values */
5
+ export const value = chalk.cyan;
6
+ /** Style for section headings */
7
+ export const heading = chalk.bold.underline;
8
+ /** Style for secondary/subdued text */
9
+ export const dim = chalk.dim;
10
+ /** Style for error messages */
11
+ export const error = chalk.red;
12
+ /** Style for success messages */
13
+ export const success = chalk.green;
14
+ /** Style for warning messages */
15
+ export const warn = chalk.yellow;
16
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/output/styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,yDAAyD;AACzD,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;AAEhC,6BAA6B;AAC7B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;AAEhC,iCAAiC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;AAE5C,uCAAuC;AACvC,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;AAE7B,+BAA+B;AAC/B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;AAE/B,iCAAiC;AACjC,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;AAEnC,iCAAiC;AACjC,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Render a borderless table with bold/cyan headers and an underline separator.
3
+ * Matches orchestration CLI style: no cell borders, column-aligned with padding.
4
+ */
5
+ export declare function renderTable(headers: string[], rows: string[][]): string;
6
+ //# sourceMappingURL=tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/output/tables.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAmCvE"}
@@ -0,0 +1,42 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * Render a borderless table with bold/cyan headers and an underline separator.
4
+ * Matches orchestration CLI style: no cell borders, column-aligned with padding.
5
+ */
6
+ export function renderTable(headers, rows) {
7
+ // Calculate column widths from headers and data
8
+ const colWidths = headers.map((h, i) => {
9
+ const dataMax = rows.reduce((max, row) => Math.max(max, stripAnsi(row[i] ?? '').length), 0);
10
+ return Math.max(stripAnsi(h).length, dataMax);
11
+ });
12
+ const pad = 2; // spacing between columns
13
+ const lines = [];
14
+ // Header row — bold cyan
15
+ const headerLine = headers
16
+ .map((h, i) => chalk.bold.cyan(h.padEnd(colWidths[i])))
17
+ .join(' '.repeat(pad));
18
+ lines.push(' ' + headerLine);
19
+ // Underline — thin dash under each column
20
+ const underline = colWidths
21
+ .map((w) => '─'.repeat(w))
22
+ .join(' '.repeat(pad));
23
+ lines.push(' ' + chalk.dim(underline));
24
+ // Data rows
25
+ for (const row of rows) {
26
+ const rowLine = row
27
+ .map((cell, i) => {
28
+ const visible = stripAnsi(cell ?? '');
29
+ const padding = colWidths[i] - visible.length;
30
+ return (cell ?? '') + ' '.repeat(Math.max(0, padding));
31
+ })
32
+ .join(' '.repeat(pad));
33
+ lines.push(' ' + rowLine);
34
+ }
35
+ return lines.join('\n');
36
+ }
37
+ /** Strip ANSI escape codes to get visible character length. */
38
+ function stripAnsi(str) {
39
+ // eslint-disable-next-line no-control-regex
40
+ return str.replace(/\x1B\[[0-9;]*m/g, '');
41
+ }
42
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/output/tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAiB,EAAE,IAAgB;IAC7D,gDAAgD;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,0BAA0B;IACzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,yBAAyB;IACzB,MAAM,UAAU,GAAG,OAAO;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACtD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,CAAC;IAE9B,0CAA0C;IAC1C,MAAM,SAAS,GAAG,SAAS;SACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACzB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAExC,YAAY;IACZ,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,GAAG;aAChB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACf,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9C,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,+DAA+D;AAC/D,SAAS,SAAS,CAAC,GAAW;IAC5B,4CAA4C;IAC5C,OAAO,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * User-facing error — printed without stack trace.
3
+ * Use for expected failure conditions (missing config, invalid arguments, etc).
4
+ */
5
+ export declare class UserError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ /**
9
+ * Top-level error handler. Prints the message and exits with code 1.
10
+ * UserErrors get a clean message; unexpected errors get a brief summary.
11
+ */
12
+ export declare function handleError(err: unknown): never;
13
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAS/C"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * User-facing error — printed without stack trace.
3
+ * Use for expected failure conditions (missing config, invalid arguments, etc).
4
+ */
5
+ export class UserError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'UserError';
9
+ }
10
+ }
11
+ /**
12
+ * Top-level error handler. Prints the message and exits with code 1.
13
+ * UserErrors get a clean message; unexpected errors get a brief summary.
14
+ */
15
+ export function handleError(err) {
16
+ if (err instanceof UserError) {
17
+ console.error(err.message);
18
+ }
19
+ else if (err instanceof Error) {
20
+ console.error(`Error: ${err.message}`);
21
+ }
22
+ else {
23
+ console.error(`Error: ${String(err)}`);
24
+ }
25
+ process.exit(1);
26
+ }
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Parse phase shorthands from the system prompt file.
3
+ *
4
+ * Extracts headings matching `(Phase n)` or `(Phase n.m)` and builds
5
+ * a map: { P1: 'Concept', P2: 'Architecture', ... }
6
+ *
7
+ * The prompt file is resolved from the project path.
8
+ */
9
+ export declare function getPhaseShorthands(projectPath: string): Promise<Map<string, string>>;
10
+ /** Clear the cached shorthands (for testing). */
11
+ export declare function clearPhaseShorthandCache(): void;
12
+ /**
13
+ * Resolve a phase input (name, shorthand, or key) to a prompt key suitable
14
+ * for SystemPromptParser.getPromptForInstruction().
15
+ *
16
+ * Resolution order:
17
+ * 1. Phase shorthand (P1–P7) → resolved name
18
+ * 2. Otherwise: return as-is (case-insensitive matching handled by parser)
19
+ *
20
+ * Hyphens and spaces are interchangeable.
21
+ */
22
+ export declare function resolvePhaseInput(input: string, projectPath: string): Promise<string>;
23
+ //# sourceMappingURL=phaseShorthand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phaseShorthand.d.ts","sourceRoot":"","sources":["../../src/utils/phaseShorthand.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyB1F;AAED,iDAAiD;AACjD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,68 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { PROMPT_FILE_RELATIVE_PATH } from '@context-forge/core';
4
+ /**
5
+ * Phase shorthand map: P1 → phase name, derived at runtime from the prompt asset.
6
+ * Cached after first parse.
7
+ */
8
+ let cachedShorthands = null;
9
+ /**
10
+ * Parse phase shorthands from the system prompt file.
11
+ *
12
+ * Extracts headings matching `(Phase n)` or `(Phase n.m)` and builds
13
+ * a map: { P1: 'Concept', P2: 'Architecture', ... }
14
+ *
15
+ * The prompt file is resolved from the project path.
16
+ */
17
+ export async function getPhaseShorthands(projectPath) {
18
+ if (cachedShorthands)
19
+ return cachedShorthands;
20
+ const promptFilePath = path.join(projectPath, PROMPT_FILE_RELATIVE_PATH);
21
+ const content = await fs.readFile(promptFilePath, 'utf-8');
22
+ const map = new Map();
23
+ // Match headings like "##### Concept (Phase 1)" or "##### Implementation (Phase 6)"
24
+ const pattern = /^#{1,6}\s+(.+?)\s+\(Phase\s+(\d+(?:\.\d+)?)\)\s*$/gm;
25
+ let match;
26
+ while ((match = pattern.exec(content)) !== null) {
27
+ const name = match[1].trim();
28
+ const number = match[2];
29
+ // Only use the integer part for shorthand (P1, P2, etc.)
30
+ const intPart = number.split('.')[0];
31
+ const shorthand = `P${intPart}`;
32
+ // First match for each integer wins (e.g. P2 = Architecture, not P2.1)
33
+ if (!map.has(shorthand)) {
34
+ map.set(shorthand, name);
35
+ }
36
+ }
37
+ cachedShorthands = map;
38
+ return map;
39
+ }
40
+ /** Clear the cached shorthands (for testing). */
41
+ export function clearPhaseShorthandCache() {
42
+ cachedShorthands = null;
43
+ }
44
+ /**
45
+ * Resolve a phase input (name, shorthand, or key) to a prompt key suitable
46
+ * for SystemPromptParser.getPromptForInstruction().
47
+ *
48
+ * Resolution order:
49
+ * 1. Phase shorthand (P1–P7) → resolved name
50
+ * 2. Otherwise: return as-is (case-insensitive matching handled by parser)
51
+ *
52
+ * Hyphens and spaces are interchangeable.
53
+ */
54
+ export async function resolvePhaseInput(input, projectPath) {
55
+ // Check if input is a shorthand like P1, p5, etc.
56
+ const shorthandMatch = input.match(/^[Pp](\d+)$/);
57
+ if (shorthandMatch) {
58
+ const shorthands = await getPhaseShorthands(projectPath);
59
+ const key = `P${shorthandMatch[1]}`;
60
+ const name = shorthands.get(key);
61
+ if (name)
62
+ return name;
63
+ // Fall through — return as-is and let the parser handle it
64
+ }
65
+ // Normalize: hyphens ↔ spaces
66
+ return input.replace(/-/g, ' ');
67
+ }
68
+ //# sourceMappingURL=phaseShorthand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phaseShorthand.js","sourceRoot":"","sources":["../../src/utils/phaseShorthand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEhE;;;GAGG;AACH,IAAI,gBAAgB,GAA+B,IAAI,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,WAAmB;IAC1D,IAAI,gBAAgB;QAAE,OAAO,gBAAgB,CAAC;IAE9C,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,yBAAyB,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAE3D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,oFAAoF;IACpF,MAAM,OAAO,GAAG,qDAAqD,CAAC;IAEtE,IAAI,KAAK,CAAC;IACV,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACzB,yDAAyD;QACzD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,OAAO,EAAE,CAAC;QAChC,uEAAuE;QACvE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,gBAAgB,GAAG,GAAG,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,wBAAwB;IACtC,gBAAgB,GAAG,IAAI,CAAC;AAC1B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,WAAmB;IAEnB,kDAAkD;IAClD,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,2DAA2D;IAC7D,CAAC;IAED,8BAA8B;IAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { FileProjectStore } from '@context-forge/core/node';
2
+ import type { ProjectData } from '@context-forge/core';
3
+ /**
4
+ * Find a project by exact ID or case-insensitive name.
5
+ * ID match takes priority over name match.
6
+ */
7
+ export declare function findByNameOrId(nameOrId: string, store: FileProjectStore): Promise<ProjectData | null>;
8
+ /**
9
+ * Find the project whose projectPath best matches the current working directory.
10
+ * When multiple projects match (nested paths), the longest projectPath wins.
11
+ * Projects without a projectPath are skipped.
12
+ */
13
+ export declare function findProjectByCwd(store: FileProjectStore): Promise<ProjectData | null>;
14
+ export type ResolutionSource = 'flag' | 'cwd' | 'default' | 'none';
15
+ export interface ResolvedProject {
16
+ id: string;
17
+ source: ResolutionSource;
18
+ }
19
+ /**
20
+ * Resolves which project to use via a three-step chain:
21
+ *
22
+ * 1. explicit --project flag → findByNameOrId
23
+ * 2. CWD detection → findProjectByCwd
24
+ * 3. default_project config → findByNameOrId
25
+ * 4. Throw UserError with guidance
26
+ */
27
+ export declare function resolveProjectId(explicit: string | undefined, store: FileProjectStore): Promise<ResolvedProject>;
28
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAW7B;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAa7B;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,eAAe,CAAC,CAgD1B"}
@@ -0,0 +1,81 @@
1
+ import { ConfigManager } from '@context-forge/core/node';
2
+ import { UserError } from './errors.js';
3
+ /**
4
+ * Find a project by exact ID or case-insensitive name.
5
+ * ID match takes priority over name match.
6
+ */
7
+ export async function findByNameOrId(nameOrId, store) {
8
+ const projects = await store.getAll();
9
+ // Exact ID match first
10
+ const byId = projects.find((p) => p.id === nameOrId);
11
+ if (byId)
12
+ return byId;
13
+ // Case-insensitive name match
14
+ const lower = nameOrId.toLowerCase();
15
+ const byName = projects.find((p) => p.name?.toLowerCase() === lower);
16
+ return byName ?? null;
17
+ }
18
+ /**
19
+ * Find the project whose projectPath best matches the current working directory.
20
+ * When multiple projects match (nested paths), the longest projectPath wins.
21
+ * Projects without a projectPath are skipped.
22
+ */
23
+ export async function findProjectByCwd(store) {
24
+ const projects = await store.getAll();
25
+ const cwd = process.cwd();
26
+ const matches = projects
27
+ .filter((p) => {
28
+ if (!p.projectPath)
29
+ return false;
30
+ const path = p.projectPath.endsWith('/') ? p.projectPath.slice(0, -1) : p.projectPath;
31
+ return cwd === path || cwd.startsWith(path + '/');
32
+ })
33
+ .sort((a, b) => (b.projectPath?.length ?? 0) - (a.projectPath?.length ?? 0));
34
+ return matches[0] ?? null;
35
+ }
36
+ /**
37
+ * Resolves which project to use via a three-step chain:
38
+ *
39
+ * 1. explicit --project flag → findByNameOrId
40
+ * 2. CWD detection → findProjectByCwd
41
+ * 3. default_project config → findByNameOrId
42
+ * 4. Throw UserError with guidance
43
+ */
44
+ export async function resolveProjectId(explicit, store) {
45
+ // Step 1: explicit --project flag
46
+ if (explicit) {
47
+ const project = await findByNameOrId(explicit, store);
48
+ if (!project) {
49
+ throw new UserError(`Project '${explicit}' not found.\n` +
50
+ ' Check the spelling, or run cf project list to see available projects.');
51
+ }
52
+ return { id: project.id, source: 'flag' };
53
+ }
54
+ // Step 2: CWD detection
55
+ const cwdProject = await findProjectByCwd(store);
56
+ if (cwdProject) {
57
+ return { id: cwdProject.id, source: 'cwd' };
58
+ }
59
+ // Step 3: default_project config
60
+ const cm = new ConfigManager();
61
+ const result = await cm.get('default_project');
62
+ const defaultRef = result.value;
63
+ if (defaultRef) {
64
+ const project = await findByNameOrId(defaultRef, store);
65
+ if (!project) {
66
+ throw new UserError(`default_project is set to '${defaultRef}' but no matching project was found.\n` +
67
+ ' cf project list # see available projects\n' +
68
+ ' cf config set default_project <name> # update the default');
69
+ }
70
+ console.error('Warning: Resolved via default_project config. Consider using --project or running from within a registered project directory.\n' +
71
+ ' cf init # register current directory\n' +
72
+ ' cf project list # see registered projects');
73
+ return { id: project.id, source: 'default' };
74
+ }
75
+ // Step 4: no resolution
76
+ throw new UserError('No project specified and no registered project found at current path.\n' +
77
+ ' cf init # register current directory as a project\n' +
78
+ ' --project <name> # specify a project explicitly\n' +
79
+ ' cf project list # see registered projects');
80
+ }
81
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@context-forge/cli",
3
+ "version": "0.2.2",
4
+ "description": "CLI for Context Forge — terminal access to context assembly, project management, workflow navigation, and configuration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "cf": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "cli",
16
+ "context",
17
+ "ai",
18
+ "context-forge"
19
+ ],
20
+ "author": "Manta Templates",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/ecorkran/context-forge.git",
25
+ "directory": "packages/cli"
26
+ },
27
+ "homepage": "https://github.com/ecorkran/context-forge/tree/main/packages/cli#readme",
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ },
31
+ "dependencies": {
32
+ "chalk": "^5.4.1",
33
+ "commander": "^13.1.0",
34
+ "@context-forge/core": "0.2.2"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^25.3.0",
38
+ "typescript": "~5.8.3",
39
+ "vitest": "^3.2.1"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "dev": "tsc --watch",
44
+ "start": "node dist/index.js",
45
+ "test": "vitest run",
46
+ "typecheck": "tsc --noEmit"
47
+ }
48
+ }