@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.
- package/LICENSE +21 -0
- package/README.md +148 -0
- package/dist/cli/args.d.ts +20 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +144 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/runner.d.ts +18 -0
- package/dist/core/runner.d.ts.map +1 -0
- package/dist/core/runner.js +107 -0
- package/dist/core/runner.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/output/colors.d.ts +33 -0
- package/dist/output/colors.d.ts.map +1 -0
- package/dist/output/colors.js +63 -0
- package/dist/output/colors.js.map +1 -0
- package/dist/output/formatter.d.ts +28 -0
- package/dist/output/formatter.d.ts.map +1 -0
- package/dist/output/formatter.js +275 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/output/index.d.ts +4 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +4 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/logger.d.ts +13 -0
- package/dist/output/logger.d.ts.map +1 -0
- package/dist/output/logger.js +38 -0
- package/dist/output/logger.js.map +1 -0
- package/dist/parsers/index.d.ts +3 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +3 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/signals.d.ts +10 -0
- package/dist/parsers/signals.d.ts.map +1 -0
- package/dist/parsers/signals.js +24 -0
- package/dist/parsers/signals.js.map +1 -0
- package/dist/parsers/stream.d.ts +16 -0
- package/dist/parsers/stream.d.ts.map +1 -0
- package/dist/parsers/stream.js +45 -0
- package/dist/parsers/stream.js.map +1 -0
- package/dist/process/index.d.ts +2 -0
- package/dist/process/index.d.ts.map +1 -0
- package/dist/process/index.js +2 -0
- package/dist/process/index.js.map +1 -0
- package/dist/process/pty.d.ts +19 -0
- package/dist/process/pty.d.ts.map +1 -0
- package/dist/process/pty.js +47 -0
- package/dist/process/pty.js.map +1 -0
- package/dist/templates/command.d.ts +17 -0
- package/dist/templates/command.d.ts.map +1 -0
- package/dist/templates/command.js +48 -0
- package/dist/templates/command.js.map +1 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +2 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/types/claude.d.ts +66 -0
- package/dist/types/claude.d.ts.map +1 -0
- package/dist/types/claude.js +28 -0
- package/dist/types/claude.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/runner.d.ts +74 -0
- package/dist/types/runner.d.ts.map +1 -0
- package/dist/types/runner.js +31 -0
- package/dist/types/runner.js.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andre Bremer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Claude Code Runner
|
|
2
|
+
|
|
3
|
+
Deterministic, scripted, unattended Claude Code execution.
|
|
4
|
+
|
|
5
|
+
## Why Use This?
|
|
6
|
+
|
|
7
|
+
- **Run unattended** — Execute Claude commands in CI/CD pipelines and automation scripts
|
|
8
|
+
- **Script multiple commands** — Chain prompts together in a single run
|
|
9
|
+
- **Iterative runs with fresh context per phase** — Each command starts with a clean slate, ideal for phase-based implementation plans
|
|
10
|
+
- **Self-correcting loops** — Users can configure prompts with [runner signals](#runner-signals) to control execution, like retry, complete, or escalation to a human
|
|
11
|
+
- **Full visibility** — Watch tool calls stream in real-time
|
|
12
|
+
- **Complete logs** — Every session captured for debugging and review
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
- Node.js 18 or later
|
|
17
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @rcrsr/claude-code-runner
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### prompt — Run a single prompt
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
claude-code-runner prompt "Refactor the auth module to use async/await"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The `prompt` keyword is optional — bare strings work the same way:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude-code-runner "Fix the failing tests in src/utils"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### command — Run a slash command file
|
|
40
|
+
|
|
41
|
+
Store prompts as markdown files in `.claude/commands/` and invoke them by name:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude-code-runner command review-code src/auth.ts
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This loads `.claude/commands/review-code.md` and substitutes `$1` with `src/auth.ts`.
|
|
48
|
+
|
|
49
|
+
**Example template** (`.claude/commands/review-code.md`):
|
|
50
|
+
|
|
51
|
+
```markdown
|
|
52
|
+
Review the code in $1 for:
|
|
53
|
+
|
|
54
|
+
- Security vulnerabilities
|
|
55
|
+
- Performance issues
|
|
56
|
+
- Code style violations
|
|
57
|
+
|
|
58
|
+
Output findings as a numbered list.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Templates support multiple arguments (`$1`, `$2`, `$3`, etc.) and YAML frontmatter is automatically stripped.
|
|
62
|
+
|
|
63
|
+
### script — Run multiple commands in sequence
|
|
64
|
+
|
|
65
|
+
Create a script file with one command per line:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
claude-code-runner script deploy-tasks.txt
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Example script** (`deploy-tasks.txt`):
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
# Comments start with #
|
|
75
|
+
prompt Run the test suite and fix any failures
|
|
76
|
+
command review-code src/api/handlers.ts
|
|
77
|
+
prompt Update the changelog for version 2.1.0
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Scripts stop on `BLOCKED` or `ERROR` signals, letting you catch issues before continuing.
|
|
81
|
+
|
|
82
|
+
### Options
|
|
83
|
+
|
|
84
|
+
| Option | Description |
|
|
85
|
+
| ----------- | ---------------------------- |
|
|
86
|
+
| `--quiet` | Minimal output (errors only) |
|
|
87
|
+
| `--normal` | Default output level |
|
|
88
|
+
| `--verbose` | Full output with details |
|
|
89
|
+
| `--no-log` | Disable file logging |
|
|
90
|
+
|
|
91
|
+
## Runner Signals
|
|
92
|
+
|
|
93
|
+
Signals give Claude a way to control execution flow. Instruct Claude to output these signals in your prompts or templates, and the runner will respond accordingly.
|
|
94
|
+
|
|
95
|
+
| Signal | Effect |
|
|
96
|
+
| ------------------------ | -------------------------------- |
|
|
97
|
+
| `:::RUNNER::DONE:::` | Exit successfully |
|
|
98
|
+
| `:::RUNNER::CONTINUE:::` | Continue to next iteration |
|
|
99
|
+
| `:::RUNNER::BLOCKED:::` | Exit with error (awaiting human) |
|
|
100
|
+
| `:::RUNNER::ERROR:::` | Exit with error |
|
|
101
|
+
|
|
102
|
+
**Example prompt using signals:**
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
claude-code-runner "Fix all lint errors in src/. Output :::RUNNER::DONE::: when complete, or :::RUNNER::BLOCKED::: if you need human input."
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Example template with signals** (`.claude/commands/fix-tests.md`):
|
|
109
|
+
|
|
110
|
+
```markdown
|
|
111
|
+
Run the test suite for $1.
|
|
112
|
+
|
|
113
|
+
- If all tests pass, output :::RUNNER::DONE:::
|
|
114
|
+
- If tests fail and you can fix them, fix them and output :::RUNNER::CONTINUE::: to re-run
|
|
115
|
+
- If tests fail and you need help, output :::RUNNER::BLOCKED::: with an explanation
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This pattern enables self-correcting loops: Claude attempts a fix, signals `CONTINUE` to retry, and only exits when done or stuck.
|
|
119
|
+
|
|
120
|
+
**Defaults:**
|
|
121
|
+
|
|
122
|
+
- Max 10 iterations per command (prevents runaway loops)
|
|
123
|
+
- If no signal is detected, the runner uses the CLI exit code (0 = success, non-0 = error)
|
|
124
|
+
|
|
125
|
+
## Exit Codes
|
|
126
|
+
|
|
127
|
+
For CI/CD integration:
|
|
128
|
+
|
|
129
|
+
| Code | Meaning |
|
|
130
|
+
| ---- | -------------------------------------------- |
|
|
131
|
+
| 0 | Success (`DONE` signal or clean exit) |
|
|
132
|
+
| 1 | Error (`ERROR`, `BLOCKED`, or non-zero exit) |
|
|
133
|
+
|
|
134
|
+
## Logs
|
|
135
|
+
|
|
136
|
+
Sessions are logged to `./logs/` with timestamped filenames. Disable with `--no-log`.
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm run check # Run all checks (typecheck, lint, format, test)
|
|
142
|
+
npm run build # Build the project
|
|
143
|
+
npm test # Run tests
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing
|
|
3
|
+
*/
|
|
4
|
+
import type { ParsedArgs } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a command line into a prompt
|
|
7
|
+
* Used for script mode line parsing
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseCommandLine(line: string): {
|
|
10
|
+
prompt: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Parse CLI arguments
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseArgs(args: string[]): ParsedArgs;
|
|
16
|
+
/**
|
|
17
|
+
* Print usage information
|
|
18
|
+
*/
|
|
19
|
+
export declare function printUsage(): void;
|
|
20
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,mBAAmB,CAAC;AAsC3B;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAkBjE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAwDpD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CA0BjC"}
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { loadCommandTemplate } from '../templates/command.js';
|
|
6
|
+
/**
|
|
7
|
+
* Extract options from raw args, returning positional args and config
|
|
8
|
+
*/
|
|
9
|
+
function extractOptions(args) {
|
|
10
|
+
let verbosity = 'normal';
|
|
11
|
+
let enableLog = true;
|
|
12
|
+
const positionalArgs = [];
|
|
13
|
+
for (const arg of args) {
|
|
14
|
+
switch (arg) {
|
|
15
|
+
case '--quiet':
|
|
16
|
+
verbosity = 'quiet';
|
|
17
|
+
break;
|
|
18
|
+
case '--normal':
|
|
19
|
+
verbosity = 'normal';
|
|
20
|
+
break;
|
|
21
|
+
case '--verbose':
|
|
22
|
+
verbosity = 'verbose';
|
|
23
|
+
break;
|
|
24
|
+
case '--no-log':
|
|
25
|
+
enableLog = false;
|
|
26
|
+
break;
|
|
27
|
+
default:
|
|
28
|
+
positionalArgs.push(arg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { positionalArgs, verbosity, enableLog };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse a command line into a prompt
|
|
35
|
+
* Used for script mode line parsing
|
|
36
|
+
*/
|
|
37
|
+
export function parseCommandLine(line) {
|
|
38
|
+
const parts = line.trim().split(/\s+/);
|
|
39
|
+
const cmd = parts[0];
|
|
40
|
+
if (cmd === 'prompt') {
|
|
41
|
+
return { prompt: parts.slice(1).join(' ') };
|
|
42
|
+
}
|
|
43
|
+
else if (cmd === 'command') {
|
|
44
|
+
const cmdName = parts[1];
|
|
45
|
+
if (!cmdName) {
|
|
46
|
+
throw new Error('command requires a name');
|
|
47
|
+
}
|
|
48
|
+
return { prompt: loadCommandTemplate(cmdName, parts.slice(2)) };
|
|
49
|
+
}
|
|
50
|
+
else if (cmd === 'script') {
|
|
51
|
+
throw new Error('script cannot be nested');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// Treat as raw prompt
|
|
55
|
+
return { prompt: line.trim() };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Parse CLI arguments
|
|
60
|
+
*/
|
|
61
|
+
export function parseArgs(args) {
|
|
62
|
+
const { positionalArgs, verbosity, enableLog } = extractOptions(args);
|
|
63
|
+
const subcommand = (positionalArgs[0] ?? 'prompt');
|
|
64
|
+
let prompt = '';
|
|
65
|
+
let scriptMode = false;
|
|
66
|
+
let scriptLines = [];
|
|
67
|
+
switch (subcommand) {
|
|
68
|
+
case 'command': {
|
|
69
|
+
const commandName = positionalArgs[1];
|
|
70
|
+
if (!commandName) {
|
|
71
|
+
console.error('Error: command name required');
|
|
72
|
+
console.error('Usage: claude-code-runner command <name> [args...]');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
prompt = loadCommandTemplate(commandName, positionalArgs.slice(2));
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'script': {
|
|
79
|
+
const scriptFile = positionalArgs[1];
|
|
80
|
+
if (!scriptFile) {
|
|
81
|
+
console.error('Error: script file required');
|
|
82
|
+
console.error('Usage: claude-code-runner script <file>');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
if (!fs.existsSync(scriptFile)) {
|
|
86
|
+
console.error(`Error: script file not found: ${scriptFile}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
scriptLines = fs
|
|
90
|
+
.readFileSync(scriptFile, 'utf-8')
|
|
91
|
+
.split('\n')
|
|
92
|
+
.map((l) => l.trim())
|
|
93
|
+
.filter((l) => l && !l.startsWith('#')); // Skip empty lines and comments
|
|
94
|
+
scriptMode = true;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
case 'prompt':
|
|
98
|
+
prompt =
|
|
99
|
+
positionalArgs.slice(1).join(' ') || 'Tell me about this project';
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
const config = {
|
|
103
|
+
verbosity,
|
|
104
|
+
enableLog,
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
subcommand: scriptMode ? 'script' : subcommand,
|
|
108
|
+
prompt,
|
|
109
|
+
scriptLines,
|
|
110
|
+
scriptMode,
|
|
111
|
+
config,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Print usage information
|
|
116
|
+
*/
|
|
117
|
+
export function printUsage() {
|
|
118
|
+
console.log(`
|
|
119
|
+
Claude Code Runner - executes claude CLI with proper TTY handling
|
|
120
|
+
|
|
121
|
+
Usage:
|
|
122
|
+
claude-code-runner [options] prompt <prompt>
|
|
123
|
+
claude-code-runner [options] command <name> [args...]
|
|
124
|
+
claude-code-runner [options] script <file>
|
|
125
|
+
|
|
126
|
+
Subcommands:
|
|
127
|
+
prompt <text> Run with the given prompt (supports RUNNER signals)
|
|
128
|
+
command <name> [args] Load .claude/commands/<name>.md (supports RUNNER signals)
|
|
129
|
+
script <file> Run commands from file, stop on ERROR/BLOCKED
|
|
130
|
+
|
|
131
|
+
Iteration Status Signals (output by Claude to control loop):
|
|
132
|
+
:::RUNNER::DONE::: Exit successfully
|
|
133
|
+
:::RUNNER::CONTINUE::: Continue to next iteration
|
|
134
|
+
:::RUNNER::BLOCKED::: Exit with error (awaiting human intervention)
|
|
135
|
+
:::RUNNER::ERROR::: Exit with error (something went wrong)
|
|
136
|
+
|
|
137
|
+
Options:
|
|
138
|
+
--quiet Minimal output (errors only)
|
|
139
|
+
--normal Default output level
|
|
140
|
+
--verbose Full output with all details
|
|
141
|
+
--no-log Disable logging to file (enabled by default)
|
|
142
|
+
`);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core runner with iteration control and signal detection
|
|
3
|
+
*/
|
|
4
|
+
import type { FormatterState } from '../output/formatter.js';
|
|
5
|
+
import type { Logger } from '../output/logger.js';
|
|
6
|
+
import type { RunnerConfig, SignalResult } from '../types/runner.js';
|
|
7
|
+
export interface RunnerContext {
|
|
8
|
+
config: RunnerConfig;
|
|
9
|
+
logger: Logger;
|
|
10
|
+
formatterState: FormatterState;
|
|
11
|
+
cwd: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run a command with RUNNER signal support
|
|
15
|
+
* Handles iteration loop and signal detection
|
|
16
|
+
*/
|
|
17
|
+
export declare function runWithSignals(promptText: string, startTime: number, context: RunnerContext): Promise<SignalResult>;
|
|
18
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAoGvB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core runner with iteration control and signal detection
|
|
3
|
+
*/
|
|
4
|
+
import { colors, formatDuration } from '../output/colors.js';
|
|
5
|
+
import { detectRunnerSignal } from '../parsers/signals.js';
|
|
6
|
+
import { spawnClaude } from '../process/pty.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run a command with RUNNER signal support
|
|
9
|
+
* Handles iteration loop and signal detection
|
|
10
|
+
*/
|
|
11
|
+
export async function runWithSignals(promptText, startTime, context) {
|
|
12
|
+
const { config, logger, formatterState, cwd } = context;
|
|
13
|
+
const { verbosity, maxIterations, parallelThresholdMs, iterationPauseMs } = config;
|
|
14
|
+
let iteration = 0;
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- intentional infinite loop with internal exits
|
|
16
|
+
while (true) {
|
|
17
|
+
iteration++;
|
|
18
|
+
// Check max iterations
|
|
19
|
+
if (iteration > maxIterations) {
|
|
20
|
+
const totalDuration = Math.round((Date.now() - startTime) / 1000);
|
|
21
|
+
console.log('');
|
|
22
|
+
printSeparator();
|
|
23
|
+
console.log(`${colors.red}MAX ITERATIONS (${maxIterations})${colors.reset} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
24
|
+
printSeparator();
|
|
25
|
+
logger.log(`\nMAX ITERATIONS reached after ${maxIterations}`);
|
|
26
|
+
return 'error';
|
|
27
|
+
}
|
|
28
|
+
// Print iteration header for subsequent iterations
|
|
29
|
+
if (iteration > 1) {
|
|
30
|
+
console.log('');
|
|
31
|
+
printIterationHeader(iteration);
|
|
32
|
+
logger.log(`\n--- Iteration ${iteration} ---\n`);
|
|
33
|
+
}
|
|
34
|
+
// Run Claude
|
|
35
|
+
const { exitCode, duration, claudeText } = await spawnClaude({
|
|
36
|
+
prompt: promptText,
|
|
37
|
+
cwd,
|
|
38
|
+
verbosity,
|
|
39
|
+
logger,
|
|
40
|
+
formatterState,
|
|
41
|
+
parallelThresholdMs,
|
|
42
|
+
});
|
|
43
|
+
const status = detectRunnerSignal(claudeText);
|
|
44
|
+
const totalDuration = Math.round((Date.now() - startTime) / 1000);
|
|
45
|
+
console.log('');
|
|
46
|
+
printSeparator();
|
|
47
|
+
if (status === 'done') {
|
|
48
|
+
console.log(`${colors.green}COMPLETE${colors.reset} | Iterations: ${iteration} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
49
|
+
printSeparator();
|
|
50
|
+
logger.log(`\nCOMPLETE after ${iteration} iterations, ${totalDuration}s total`);
|
|
51
|
+
return 'ok';
|
|
52
|
+
}
|
|
53
|
+
else if (status === 'blocked') {
|
|
54
|
+
console.log(`${colors.red}BLOCKED${colors.reset} | Iterations: ${iteration} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
55
|
+
printSeparator();
|
|
56
|
+
logger.log(`\nBLOCKED after ${iteration} iterations, ${totalDuration}s total`);
|
|
57
|
+
return 'blocked';
|
|
58
|
+
}
|
|
59
|
+
else if (status === 'error') {
|
|
60
|
+
console.log(`${colors.red}ERROR${colors.reset} | Iterations: ${iteration} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
61
|
+
printSeparator();
|
|
62
|
+
logger.log(`\nERROR after ${iteration} iterations, ${totalDuration}s total`);
|
|
63
|
+
return 'error';
|
|
64
|
+
}
|
|
65
|
+
else if (status === 'continue') {
|
|
66
|
+
console.log(`${colors.yellow}CONTINUE${colors.reset} | Iteration ${iteration} done (${duration}s), continuing...`);
|
|
67
|
+
printSeparator();
|
|
68
|
+
logger.log(`Iteration ${iteration} complete, continuing...`);
|
|
69
|
+
await sleep(iterationPauseMs);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// No status signal - treat as successful single run
|
|
73
|
+
const exitStatus = exitCode === 0 ? 'ok' : 'error';
|
|
74
|
+
if (iteration === 1) {
|
|
75
|
+
console.log(`Exit: ${exitCode === 0 ? colors.green : colors.red}${exitCode}${colors.reset} | Duration: ${duration}s`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.log(`${exitCode === 0 ? colors.green + 'COMPLETE' : colors.red + 'FAILED'}${colors.reset} | Iterations: ${iteration} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
79
|
+
}
|
|
80
|
+
printSeparator();
|
|
81
|
+
logger.log(`\nCompleted after ${iteration} iteration(s), exit=${exitCode}`);
|
|
82
|
+
return exitStatus;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Print a separator line
|
|
88
|
+
*/
|
|
89
|
+
function printSeparator() {
|
|
90
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Print iteration header
|
|
94
|
+
*/
|
|
95
|
+
function printIterationHeader(iteration) {
|
|
96
|
+
console.log(`${colors.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}`);
|
|
97
|
+
console.log(`${colors.blue}Iteration ${iteration}${colors.reset}`);
|
|
98
|
+
console.log(`${colors.blue}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}`);
|
|
99
|
+
console.log('');
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Sleep for a given number of milliseconds
|
|
103
|
+
*/
|
|
104
|
+
function sleep(ms) {
|
|
105
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Runner - executes claude CLI with proper TTY handling
|
|
4
|
+
* Shows intermediate tool calls and responses in real-time
|
|
5
|
+
*/
|
|
6
|
+
import { parseArgs, parseCommandLine } from './cli/args.js';
|
|
7
|
+
import { runWithSignals } from './core/runner.js';
|
|
8
|
+
import { colors, formatDuration, truncate } from './output/colors.js';
|
|
9
|
+
import { createFormatterState } from './output/formatter.js';
|
|
10
|
+
import { createLogger } from './output/logger.js';
|
|
11
|
+
import { DEFAULT_CONFIG } from './types/runner.js';
|
|
12
|
+
async function main() {
|
|
13
|
+
const totalStart = Date.now();
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const parsed = parseArgs(args);
|
|
16
|
+
// Merge config with defaults
|
|
17
|
+
const config = {
|
|
18
|
+
...DEFAULT_CONFIG,
|
|
19
|
+
...parsed.config,
|
|
20
|
+
};
|
|
21
|
+
// Create logger
|
|
22
|
+
const commandName = parsed.scriptMode
|
|
23
|
+
? 'script'
|
|
24
|
+
: parsed.subcommand === 'command'
|
|
25
|
+
? (args[1] ?? 'prompt')
|
|
26
|
+
: 'prompt';
|
|
27
|
+
const logger = createLogger(config.enableLog, config.logDir, commandName);
|
|
28
|
+
// Create formatter state
|
|
29
|
+
const formatterState = createFormatterState();
|
|
30
|
+
// Create runner context
|
|
31
|
+
const context = {
|
|
32
|
+
config,
|
|
33
|
+
logger,
|
|
34
|
+
formatterState,
|
|
35
|
+
cwd: process.cwd(),
|
|
36
|
+
};
|
|
37
|
+
// Print header
|
|
38
|
+
printHeader(parsed.subcommand, config.verbosity, logger.filePath);
|
|
39
|
+
logger.log(`Started: ${new Date().toISOString()}`);
|
|
40
|
+
if (parsed.scriptMode) {
|
|
41
|
+
// Script mode: run each line
|
|
42
|
+
await runScriptMode(parsed.scriptLines, context, totalStart);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Single command mode
|
|
46
|
+
await runSingleMode(parsed.prompt, context, totalStart);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Print runner header
|
|
51
|
+
*/
|
|
52
|
+
function printHeader(mode, verbosity, logFile) {
|
|
53
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
54
|
+
console.log(`${colors.bold}Claude Code Runner${colors.reset} ${colors.dim}(${verbosity}, ${mode})${colors.reset}`);
|
|
55
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
56
|
+
if (logFile) {
|
|
57
|
+
console.log(`${colors.dim}Log:${colors.reset} ${logFile}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Run in single command mode (prompt or command)
|
|
62
|
+
*/
|
|
63
|
+
async function runSingleMode(prompt, context, startTime) {
|
|
64
|
+
console.log(`${colors.dim}Prompt:${colors.reset} ${truncate(prompt, 80)}`);
|
|
65
|
+
console.log('');
|
|
66
|
+
context.logger.log(`Prompt: ${prompt}\n`);
|
|
67
|
+
const result = await runWithSignals(prompt, startTime, context);
|
|
68
|
+
context.logger.close();
|
|
69
|
+
process.exit(result === 'ok' ? 0 : 1);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run in script mode
|
|
73
|
+
*/
|
|
74
|
+
async function runScriptMode(scriptLines, context, startTime) {
|
|
75
|
+
console.log(`${colors.dim}Script:${colors.reset} ${scriptLines.length} commands`);
|
|
76
|
+
console.log('');
|
|
77
|
+
context.logger.log(`Script: ${scriptLines.length} commands\n`);
|
|
78
|
+
for (const [i, line] of scriptLines.entries()) {
|
|
79
|
+
printScriptStep(i + 1, scriptLines.length, line);
|
|
80
|
+
context.logger.log(`\n=== [${i + 1}/${scriptLines.length}] ${line} ===\n`);
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
const parsed = parseCommandLine(line);
|
|
84
|
+
result = await runWithSignals(parsed.prompt, startTime, context);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.log(`${colors.red}PARSE ERROR:${colors.reset} ${err.message}`);
|
|
88
|
+
result = 'error';
|
|
89
|
+
}
|
|
90
|
+
if (result === 'blocked' || result === 'error') {
|
|
91
|
+
const totalDuration = Math.round((Date.now() - startTime) / 1000);
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
94
|
+
console.log(`${colors.red}SCRIPT STOPPED${colors.reset} at step ${i + 1}/${scriptLines.length} | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
95
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
96
|
+
context.logger.log(`\nSCRIPT STOPPED at step ${i + 1}, ${totalDuration}s total`);
|
|
97
|
+
context.logger.close();
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// All commands completed
|
|
102
|
+
const totalDuration = Math.round((Date.now() - startTime) / 1000);
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
105
|
+
console.log(`${colors.green}SCRIPT COMPLETE${colors.reset} | ${scriptLines.length} commands | Total: ${formatDuration(totalDuration * 1000)}`);
|
|
106
|
+
console.log(`${colors.bold}════════════════════════════════════════════════════════════${colors.reset}`);
|
|
107
|
+
context.logger.log(`\nSCRIPT COMPLETE, ${scriptLines.length} commands, ${totalDuration}s total`);
|
|
108
|
+
context.logger.close();
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Print script step header
|
|
113
|
+
*/
|
|
114
|
+
function printScriptStep(current, total, line) {
|
|
115
|
+
console.log(`${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}`);
|
|
116
|
+
console.log(`${colors.cyan}[${current}/${total}]${colors.reset} ${truncate(line, 60)}`);
|
|
117
|
+
console.log(`${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}`);
|
|
118
|
+
console.log('');
|
|
119
|
+
}
|
|
120
|
+
// Run main
|
|
121
|
+
main().catch((err) => {
|
|
122
|
+
console.error('Fatal error:', err);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=index.js.map
|