@rcrsr/claude-code-runner 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/dist/cli/args.d.ts +20 -0
  4. package/dist/cli/args.d.ts.map +1 -0
  5. package/dist/cli/args.js +144 -0
  6. package/dist/cli/args.js.map +1 -0
  7. package/dist/cli/index.d.ts +2 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +2 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/core/index.d.ts +2 -0
  12. package/dist/core/index.d.ts.map +1 -0
  13. package/dist/core/index.js +2 -0
  14. package/dist/core/index.js.map +1 -0
  15. package/dist/core/runner.d.ts +18 -0
  16. package/dist/core/runner.d.ts.map +1 -0
  17. package/dist/core/runner.js +107 -0
  18. package/dist/core/runner.js.map +1 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +125 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/output/colors.d.ts +33 -0
  24. package/dist/output/colors.d.ts.map +1 -0
  25. package/dist/output/colors.js +63 -0
  26. package/dist/output/colors.js.map +1 -0
  27. package/dist/output/formatter.d.ts +28 -0
  28. package/dist/output/formatter.d.ts.map +1 -0
  29. package/dist/output/formatter.js +275 -0
  30. package/dist/output/formatter.js.map +1 -0
  31. package/dist/output/index.d.ts +4 -0
  32. package/dist/output/index.d.ts.map +1 -0
  33. package/dist/output/index.js +4 -0
  34. package/dist/output/index.js.map +1 -0
  35. package/dist/output/logger.d.ts +13 -0
  36. package/dist/output/logger.d.ts.map +1 -0
  37. package/dist/output/logger.js +38 -0
  38. package/dist/output/logger.js.map +1 -0
  39. package/dist/parsers/index.d.ts +3 -0
  40. package/dist/parsers/index.d.ts.map +1 -0
  41. package/dist/parsers/index.js +3 -0
  42. package/dist/parsers/index.js.map +1 -0
  43. package/dist/parsers/signals.d.ts +10 -0
  44. package/dist/parsers/signals.d.ts.map +1 -0
  45. package/dist/parsers/signals.js +24 -0
  46. package/dist/parsers/signals.js.map +1 -0
  47. package/dist/parsers/stream.d.ts +16 -0
  48. package/dist/parsers/stream.d.ts.map +1 -0
  49. package/dist/parsers/stream.js +45 -0
  50. package/dist/parsers/stream.js.map +1 -0
  51. package/dist/process/index.d.ts +2 -0
  52. package/dist/process/index.d.ts.map +1 -0
  53. package/dist/process/index.js +2 -0
  54. package/dist/process/index.js.map +1 -0
  55. package/dist/process/pty.d.ts +19 -0
  56. package/dist/process/pty.d.ts.map +1 -0
  57. package/dist/process/pty.js +47 -0
  58. package/dist/process/pty.js.map +1 -0
  59. package/dist/templates/command.d.ts +17 -0
  60. package/dist/templates/command.d.ts.map +1 -0
  61. package/dist/templates/command.js +48 -0
  62. package/dist/templates/command.js.map +1 -0
  63. package/dist/templates/index.d.ts +2 -0
  64. package/dist/templates/index.d.ts.map +1 -0
  65. package/dist/templates/index.js +2 -0
  66. package/dist/templates/index.js.map +1 -0
  67. package/dist/types/claude.d.ts +66 -0
  68. package/dist/types/claude.d.ts.map +1 -0
  69. package/dist/types/claude.js +28 -0
  70. package/dist/types/claude.js.map +1 -0
  71. package/dist/types/index.d.ts +3 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/index.js +3 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/types/runner.d.ts +74 -0
  76. package/dist/types/runner.d.ts.map +1 -0
  77. package/dist/types/runner.js +31 -0
  78. package/dist/types/runner.js.map +1 -0
  79. package/package.json +66 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Stream JSON parser for Claude CLI output
3
+ * Handles line-by-line JSON parsing with ANSI stripping
4
+ */
5
+ import { stripAnsi } from '../output/colors.js';
6
+ /**
7
+ * Create a stream parser for Claude CLI JSON output
8
+ */
9
+ export function createStreamParser() {
10
+ let buffer = '';
11
+ return {
12
+ process(data) {
13
+ buffer += data;
14
+ const messages = [];
15
+ // Process complete JSON lines
16
+ const lines = buffer.split('\n');
17
+ buffer = lines.pop() ?? '';
18
+ for (const line of lines) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed) {
21
+ continue;
22
+ }
23
+ // Strip ANSI escape codes and other terminal artifacts
24
+ const cleaned = stripAnsi(trimmed).replace(/\[<u/g, '');
25
+ if (!cleaned) {
26
+ continue;
27
+ }
28
+ try {
29
+ const msg = JSON.parse(cleaned);
30
+ messages.push(msg);
31
+ }
32
+ catch {
33
+ // Not valid JSON - skip terminal control codes
34
+ }
35
+ }
36
+ return messages;
37
+ },
38
+ flush() {
39
+ const remaining = buffer;
40
+ buffer = '';
41
+ return remaining;
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/parsers/stream.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAUhD;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,OAAO;QACL,OAAO,CAAC,IAAY;YAClB,MAAM,IAAI,IAAI,CAAC;YACf,MAAM,QAAQ,GAAoB,EAAE,CAAC;YAErC,8BAA8B;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,SAAS;gBACX,CAAC;gBAED,uDAAuD;gBACvD,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACxD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAkB,CAAC;oBACjD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC;gBAAC,MAAM,CAAC;oBACP,+CAA+C;gBACjD,CAAC;YACH,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,KAAK;YACH,MAAM,SAAS,GAAG,MAAM,CAAC;YACzB,MAAM,GAAG,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './pty.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/process/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './pty.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/process/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * PTY process management for Claude CLI
3
+ */
4
+ import type { FormatterState } from '../output/formatter.js';
5
+ import type { Logger } from '../output/logger.js';
6
+ import type { RunResult, Verbosity } from '../types/runner.js';
7
+ export interface ClaudeProcessOptions {
8
+ prompt: string;
9
+ cwd: string;
10
+ verbosity: Verbosity;
11
+ logger: Logger;
12
+ formatterState: FormatterState;
13
+ parallelThresholdMs: number;
14
+ }
15
+ /**
16
+ * Spawn Claude CLI process with PTY
17
+ */
18
+ export declare function spawnClaude(options: ClaudeProcessOptions): Promise<RunResult>;
19
+ //# sourceMappingURL=pty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty.d.ts","sourceRoot":"","sources":["../../src/process/pty.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC,CA2D7E"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * PTY process management for Claude CLI
3
+ */
4
+ import * as pty from 'node-pty';
5
+ import { flushPendingTools, formatMessage, resetFormatterState, } from '../output/formatter.js';
6
+ import { createStreamParser } from '../parsers/stream.js';
7
+ /**
8
+ * Spawn Claude CLI process with PTY
9
+ */
10
+ export function spawnClaude(options) {
11
+ const { prompt, cwd, verbosity, logger, formatterState, parallelThresholdMs, } = options;
12
+ return new Promise((resolve) => {
13
+ // Reset state for new run
14
+ resetFormatterState(formatterState);
15
+ const runStart = Date.now();
16
+ let claudeText = '';
17
+ const parser = createStreamParser();
18
+ const ptyProcess = pty.spawn('claude', [
19
+ '-p',
20
+ prompt,
21
+ '--dangerously-skip-permissions',
22
+ '--verbose',
23
+ '--output-format',
24
+ 'stream-json',
25
+ ], {
26
+ name: 'xterm-256color',
27
+ cols: 200,
28
+ rows: 50,
29
+ cwd,
30
+ env: { ...process.env },
31
+ });
32
+ ptyProcess.onData((data) => {
33
+ const messages = parser.process(data);
34
+ for (const msg of messages) {
35
+ const text = formatMessage(msg, formatterState, verbosity, logger, parallelThresholdMs);
36
+ claudeText += text;
37
+ logger.log(JSON.stringify(msg));
38
+ }
39
+ });
40
+ ptyProcess.onExit(({ exitCode }) => {
41
+ flushPendingTools(formatterState, verbosity);
42
+ const duration = Math.round((Date.now() - runStart) / 1000);
43
+ resolve({ exitCode, duration, claudeText });
44
+ });
45
+ });
46
+ }
47
+ //# sourceMappingURL=pty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty.js","sourceRoot":"","sources":["../../src/process/pty.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAGhC,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAY1D;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAA6B;IACvD,MAAM,EACJ,MAAM,EACN,GAAG,EACH,SAAS,EACT,MAAM,EACN,cAAc,EACd,mBAAmB,GACpB,GAAG,OAAO,CAAC;IAEZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,0BAA0B;QAC1B,mBAAmB,CAAC,cAAc,CAAC,CAAC;QAEpC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;QAEpC,MAAM,UAAU,GAAS,GAAG,CAAC,KAAK,CAChC,QAAQ,EACR;YACE,IAAI;YACJ,MAAM;YACN,gCAAgC;YAChC,WAAW;YACX,iBAAiB;YACjB,aAAa;SACd,EACD;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,EAAE;YACR,GAAG;YACH,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CACF,CAAC;QAEF,UAAU,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEtC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,aAAa,CACxB,GAAG,EACH,cAAc,EACd,SAAS,EACT,MAAM,EACN,mBAAmB,CACpB,CAAC;gBACF,UAAU,IAAI,IAAI,CAAC;gBACnB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YACjC,iBAAiB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;YAC5D,OAAO,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Command template loading and variable substitution
3
+ */
4
+ /**
5
+ * Strip YAML frontmatter from markdown content
6
+ * Frontmatter can cause CLI parsing issues
7
+ */
8
+ export declare function stripFrontmatter(content: string): string;
9
+ /**
10
+ * Load a command template and substitute positional arguments
11
+ * Templates are loaded from .claude/commands/<name>.md
12
+ *
13
+ * @param commandName - Name of the command (without .md extension)
14
+ * @param cmdArgs - Positional arguments to substitute ($1, $2, etc.)
15
+ */
16
+ export declare function loadCommandTemplate(commandName: string, cmdArgs: string[]): string;
17
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/templates/command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASxD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,GAChB,MAAM,CA+BR"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Command template loading and variable substitution
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ /**
7
+ * Strip YAML frontmatter from markdown content
8
+ * Frontmatter can cause CLI parsing issues
9
+ */
10
+ export function stripFrontmatter(content) {
11
+ if (!content.startsWith('---')) {
12
+ return content;
13
+ }
14
+ const endIndex = content.indexOf('\n---', 3);
15
+ if (endIndex === -1) {
16
+ return content;
17
+ }
18
+ return content.slice(endIndex + 4).trimStart();
19
+ }
20
+ /**
21
+ * Load a command template and substitute positional arguments
22
+ * Templates are loaded from .claude/commands/<name>.md
23
+ *
24
+ * @param commandName - Name of the command (without .md extension)
25
+ * @param cmdArgs - Positional arguments to substitute ($1, $2, etc.)
26
+ */
27
+ export function loadCommandTemplate(commandName, cmdArgs) {
28
+ const commandFile = path.join(process.cwd(), '.claude', 'commands', `${commandName}.md`);
29
+ if (!fs.existsSync(commandFile)) {
30
+ console.error(`Error: command not found: ${commandFile}`);
31
+ process.exit(1);
32
+ }
33
+ let template = fs.readFileSync(commandFile, 'utf-8');
34
+ // Strip YAML frontmatter
35
+ template = stripFrontmatter(template);
36
+ // Substitute $1, $2, $3, ... with positional args
37
+ for (const [i, arg] of cmdArgs.entries()) {
38
+ template = template.replace(new RegExp(`\\$${i + 1}`, 'g'), arg);
39
+ }
40
+ // Warn about unsubstituted variables
41
+ const unsubstituted = template.match(/\$\d+/g);
42
+ if (unsubstituted) {
43
+ const unique = [...new Set(unsubstituted)];
44
+ console.error(`Warning: unsubstituted variables: ${unique.join(', ')}`);
45
+ }
46
+ return template;
47
+ }
48
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/templates/command.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAmB,EACnB,OAAiB;IAEjB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,OAAO,CAAC,GAAG,EAAE,EACb,SAAS,EACT,UAAU,EACV,GAAG,WAAW,KAAK,CACpB,CAAC;IAEF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,6BAA6B,WAAW,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAErD,yBAAyB;IACzB,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAEtC,kDAAkD;IAClD,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACzC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACnE,CAAC;IAED,qCAAqC;IACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,qCAAqC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './command.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './command.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Types for Claude CLI stream-json output messages
3
+ */
4
+ export interface TextBlock {
5
+ type: 'text';
6
+ text: string;
7
+ }
8
+ export interface ToolUseBlock {
9
+ type: 'tool_use';
10
+ id: string;
11
+ name: string;
12
+ input: Record<string, unknown>;
13
+ }
14
+ export interface ToolResultBlock {
15
+ type: 'tool_result';
16
+ tool_use_id: string;
17
+ content: string | unknown[];
18
+ is_error?: boolean;
19
+ }
20
+ export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
21
+ export interface McpServer {
22
+ name: string;
23
+ status: 'connected' | 'failed' | 'connecting';
24
+ }
25
+ export interface MessageEnvelope {
26
+ role: 'assistant' | 'user';
27
+ content: ContentBlock[];
28
+ }
29
+ export interface SystemInitMessage {
30
+ type: 'system';
31
+ subtype: 'init';
32
+ model: string;
33
+ tools?: string[];
34
+ mcp_servers?: McpServer[];
35
+ }
36
+ export interface AssistantMessage {
37
+ type: 'assistant';
38
+ message: MessageEnvelope;
39
+ }
40
+ export interface UserMessage {
41
+ type: 'user';
42
+ message: MessageEnvelope;
43
+ }
44
+ export interface ResultMessage {
45
+ type: 'result';
46
+ duration_ms?: number;
47
+ cost_usd?: number;
48
+ is_error?: boolean;
49
+ }
50
+ export interface GenericMessage {
51
+ type: string;
52
+ subtype?: string;
53
+ [key: string]: unknown;
54
+ }
55
+ export type ClaudeMessage = SystemInitMessage | AssistantMessage | UserMessage | ResultMessage | GenericMessage;
56
+ /**
57
+ * Type guard functions
58
+ */
59
+ export declare function isSystemInitMessage(msg: ClaudeMessage): msg is SystemInitMessage;
60
+ export declare function isAssistantMessage(msg: ClaudeMessage): msg is AssistantMessage;
61
+ export declare function isUserMessage(msg: ClaudeMessage): msg is UserMessage;
62
+ export declare function isResultMessage(msg: ClaudeMessage): msg is ResultMessage;
63
+ export declare function isToolUseBlock(block: ContentBlock): block is ToolUseBlock;
64
+ export declare function isToolResultBlock(block: ContentBlock): block is ToolResultBlock;
65
+ export declare function isTextBlock(block: ContentBlock): block is TextBlock;
66
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/types/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,eAAe,CAAC;AAGtE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;CAC/C;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAGD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;CAC3B;AAGD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAGD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;CAC1B;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,cAAc,CAAC;AAEnB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,GACjB,GAAG,IAAI,iBAAiB,CAE1B;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,GACjB,GAAG,IAAI,gBAAgB,CAEzB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,WAAW,CAEpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,GAAG,IAAI,aAAa,CAExE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,IAAI,YAAY,CAEzE;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,GAClB,KAAK,IAAI,eAAe,CAE1B;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,IAAI,SAAS,CAEnE"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Types for Claude CLI stream-json output messages
3
+ */
4
+ /**
5
+ * Type guard functions
6
+ */
7
+ export function isSystemInitMessage(msg) {
8
+ return msg.type === 'system' && 'subtype' in msg && msg.subtype === 'init';
9
+ }
10
+ export function isAssistantMessage(msg) {
11
+ return msg.type === 'assistant';
12
+ }
13
+ export function isUserMessage(msg) {
14
+ return msg.type === 'user';
15
+ }
16
+ export function isResultMessage(msg) {
17
+ return msg.type === 'result';
18
+ }
19
+ export function isToolUseBlock(block) {
20
+ return block.type === 'tool_use';
21
+ }
22
+ export function isToolResultBlock(block) {
23
+ return block.type === 'tool_result';
24
+ }
25
+ export function isTextBlock(block) {
26
+ return block.type === 'text';
27
+ }
28
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/types/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+EH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAkB;IAElB,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,GAAkB;IAElB,OAAO,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,OAAO,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAkB;IAChD,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmB;IAChD,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAmB;IAEnB,OAAO,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC7C,OAAO,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './claude.js';
2
+ export * from './runner.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './claude.js';
2
+ export * from './runner.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Runner configuration and state types
3
+ */
4
+ export type Verbosity = 'quiet' | 'normal' | 'verbose';
5
+ export type Subcommand = 'prompt' | 'command' | 'script';
6
+ /**
7
+ * Runner signals for iteration control
8
+ * Claude outputs these to control the runner loop
9
+ */
10
+ export type RunnerSignal = 'done' | 'continue' | 'blocked' | 'error';
11
+ export declare const RUNNER_SIGNALS: {
12
+ readonly DONE: ":::RUNNER::DONE:::";
13
+ readonly CONTINUE: ":::RUNNER::CONTINUE:::";
14
+ readonly BLOCKED: ":::RUNNER::BLOCKED:::";
15
+ readonly ERROR: ":::RUNNER::ERROR:::";
16
+ };
17
+ /**
18
+ * Result of running a single Claude invocation
19
+ */
20
+ export interface RunResult {
21
+ exitCode: number;
22
+ duration: number;
23
+ claudeText: string;
24
+ }
25
+ /**
26
+ * Result of running with signal support (may involve multiple iterations)
27
+ */
28
+ export type SignalResult = 'ok' | 'blocked' | 'error';
29
+ /**
30
+ * Runner configuration
31
+ */
32
+ export interface RunnerConfig {
33
+ verbosity: Verbosity;
34
+ enableLog: boolean;
35
+ logDir: string;
36
+ maxIterations: number;
37
+ parallelThresholdMs: number;
38
+ iterationPauseMs: number;
39
+ }
40
+ /**
41
+ * Default runner configuration
42
+ */
43
+ export declare const DEFAULT_CONFIG: RunnerConfig;
44
+ /**
45
+ * Parsed CLI arguments
46
+ */
47
+ export interface ParsedArgs {
48
+ subcommand: Subcommand;
49
+ prompt: string;
50
+ scriptLines: string[];
51
+ scriptMode: boolean;
52
+ config: Partial<RunnerConfig>;
53
+ }
54
+ /**
55
+ * Tool call tracking
56
+ */
57
+ export interface PendingTool {
58
+ name: string;
59
+ input: Record<string, unknown>;
60
+ id: string;
61
+ }
62
+ /**
63
+ * Active task (subagent) tracking
64
+ */
65
+ export interface ActiveTask {
66
+ name: string;
67
+ description: string;
68
+ id: string;
69
+ }
70
+ /**
71
+ * Noise patterns to filter from output
72
+ */
73
+ export declare const NOISE_PATTERNS: RegExp[];
74
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/types/runner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAErE,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,YAO5B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,EAMlC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Runner configuration and state types
3
+ */
4
+ export const RUNNER_SIGNALS = {
5
+ DONE: ':::RUNNER::DONE:::',
6
+ CONTINUE: ':::RUNNER::CONTINUE:::',
7
+ BLOCKED: ':::RUNNER::BLOCKED:::',
8
+ ERROR: ':::RUNNER::ERROR:::',
9
+ };
10
+ /**
11
+ * Default runner configuration
12
+ */
13
+ export const DEFAULT_CONFIG = {
14
+ verbosity: 'normal',
15
+ enableLog: true,
16
+ logDir: 'logs',
17
+ maxIterations: 10,
18
+ parallelThresholdMs: 100,
19
+ iterationPauseMs: 2000,
20
+ };
21
+ /**
22
+ * Noise patterns to filter from output
23
+ */
24
+ export const NOISE_PATTERNS = [
25
+ /\.venv\//,
26
+ /node_modules\//,
27
+ /\.pnpm\//,
28
+ /__pycache__\//,
29
+ /\.pyc$/,
30
+ ];
31
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/types/runner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,oBAAoB;IAC1B,QAAQ,EAAE,wBAAwB;IAClC,OAAO,EAAE,uBAAuB;IAChC,KAAK,EAAE,qBAAqB;CACpB,CAAC;AA4BX;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,SAAS,EAAE,QAAQ;IACnB,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,MAAM;IACd,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,GAAG;IACxB,gBAAgB,EAAE,IAAI;CACvB,CAAC;AA+BF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,UAAU;IACV,gBAAgB;IAChB,UAAU;IACV,eAAe;IACf,QAAQ;CACT,CAAC"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@rcrsr/claude-code-runner",
3
+ "version": "0.1.0",
4
+ "description": "Execute Claude CLI with PTY handling, real-time tool visualization, and iterative execution support",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "claude-code-runner": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/rcrsr/claude-code-runner.git"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/rcrsr/claude-code-runner/issues"
19
+ },
20
+ "homepage": "https://github.com/rcrsr/claude-code-runner#readme",
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "build:watch": "tsc --watch",
27
+ "start": "node dist/index.js",
28
+ "typecheck": "tsc --noEmit",
29
+ "lint": "eslint src/",
30
+ "lint:fix": "eslint src/ --fix",
31
+ "format": "prettier --write src/ tests/",
32
+ "format:check": "prettier --check src/ tests/",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "test:coverage": "vitest run --coverage",
36
+ "check": "npm run typecheck && npm run lint && npm run format:check && npm run test",
37
+ "clean": "rm -rf dist coverage",
38
+ "prepublishOnly": "npm run check && npm run build"
39
+ },
40
+ "keywords": [
41
+ "claude",
42
+ "cli",
43
+ "runner",
44
+ "automation"
45
+ ],
46
+ "author": "Andre Bremer",
47
+ "license": "MIT",
48
+ "dependencies": {
49
+ "node-pty": "^1.0.0"
50
+ },
51
+ "devDependencies": {
52
+ "@eslint/js": "^9.0.0",
53
+ "@types/node": "^20.11.0",
54
+ "@vitest/coverage-v8": "^2.0.0",
55
+ "eslint": "^9.0.0",
56
+ "eslint-plugin-simple-import-sort": "^12.1.1",
57
+ "prettier": "^3.2.0",
58
+ "tsc-files": "^1.1.4",
59
+ "typescript": "^5.3.0",
60
+ "typescript-eslint": "^8.0.0",
61
+ "vitest": "^2.0.0"
62
+ },
63
+ "engines": {
64
+ "node": ">=18.0.0"
65
+ }
66
+ }