@rcrsr/claude-code-runner 0.6.2 → 0.7.1
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/README.md +66 -114
- package/dist/cli/args.d.ts +0 -7
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -59
- package/dist/cli/args.js.map +1 -1
- package/dist/index.js +57 -114
- package/dist/index.js.map +1 -1
- package/dist/parsers/index.d.ts +0 -1
- package/dist/parsers/index.d.ts.map +1 -1
- package/dist/parsers/index.js +0 -1
- package/dist/parsers/index.js.map +1 -1
- package/dist/rill/context.d.ts +44 -0
- package/dist/rill/context.d.ts.map +1 -0
- package/dist/rill/context.js +207 -0
- package/dist/rill/context.js.map +1 -0
- package/dist/rill/index.d.ts +8 -0
- package/dist/rill/index.d.ts.map +1 -0
- package/dist/rill/index.js +6 -0
- package/dist/rill/index.js.map +1 -0
- package/dist/rill/runner.d.ts +62 -0
- package/dist/rill/runner.d.ts.map +1 -0
- package/dist/rill/runner.js +263 -0
- package/dist/rill/runner.js.map +1 -0
- package/dist/templates/command.d.ts +9 -0
- package/dist/templates/command.d.ts.map +1 -1
- package/dist/templates/command.js +43 -9
- package/dist/templates/command.js.map +1 -1
- package/dist/types/runner.d.ts +2 -28
- package/dist/types/runner.d.ts.map +1 -1
- package/dist/types/runner.js +2 -9
- package/dist/types/runner.js.map +1 -1
- package/dist/utils/constants.d.ts +0 -4
- package/dist/utils/constants.d.ts.map +1 -1
- package/dist/utils/constants.js +0 -4
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/formatting.d.ts +5 -0
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +13 -0
- package/dist/utils/formatting.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Claude Code Runner
|
|
2
2
|
|
|
3
|
-
Deterministic, scripted, unattended Claude Code execution.
|
|
3
|
+
Deterministic, scripted, unattended Claude Code execution with [Rill](https://github.com/rcrsr/rill) scripting.
|
|
4
4
|
|
|
5
5
|
## Why Use This?
|
|
6
6
|
|
|
7
|
+
- **Rich scripting** — Fully scriptable with variables, conditionals, loops, and functions
|
|
7
8
|
- **Walk away** — Workflows run unattended in CI/CD pipelines
|
|
8
9
|
- **Chain results** — Capture output from one step, inject it into the next
|
|
9
|
-
- **Claude decides** —
|
|
10
|
-
- **No
|
|
10
|
+
- **Claude decides** — Results protocol lets Claude control flow with `<ccr:result type="..."/>`
|
|
11
|
+
- **No context limits** — Fresh context per step keeps long workflows running
|
|
11
12
|
- **Watch live** — See tool calls stream as they execute
|
|
12
13
|
- **Replay later** — Full session logs for debugging
|
|
13
14
|
|
|
@@ -75,62 +76,56 @@ Review $1 with severity level $2...
|
|
|
75
76
|
|
|
76
77
|
### script — Run multi-phase workflows
|
|
77
78
|
|
|
78
|
-
Scripts
|
|
79
|
+
Scripts use [Rill](https://github.com/rcrsr/rill), a scripting language designed for AI workflows. Rill provides:
|
|
80
|
+
|
|
81
|
+
- **Variables & capture** — Store Claude's output with `:>` operator
|
|
82
|
+
- **Conditionals** — Branch logic with `(condition) ? action`
|
|
83
|
+
- **Loops** — Iterate with `for` and `while`
|
|
84
|
+
- **Functions** — Reusable logic blocks
|
|
85
|
+
- **String interpolation** — Embed variables with `{$var}` syntax
|
|
86
|
+
- **Heredocs** — Multi-line prompts with `<<EOF...EOF`
|
|
79
87
|
|
|
80
88
|
```bash
|
|
81
|
-
claude-code-runner script
|
|
89
|
+
claude-code-runner script workflow.rill src/api/
|
|
82
90
|
```
|
|
83
91
|
|
|
84
|
-
**
|
|
85
|
-
|
|
86
|
-
| Syntax | Description |
|
|
87
|
-
| ----------------------------------- | ----------------------------------------- |
|
|
88
|
-
| `prompt("text")` | Run a prompt (supports `\n` for newlines) |
|
|
89
|
-
| `prompt(<<EOF...EOF)` | Multi-line prompt using heredoc |
|
|
90
|
-
| `command("name")` | Run a command template |
|
|
91
|
-
| `command("name", ["arg1", "arg2"])` | Run command with arguments |
|
|
92
|
-
| `-> $varname` | Capture output into a variable |
|
|
93
|
-
| `$_` | Previous step's output (auto-captured) |
|
|
94
|
-
| `$varname` | Named captured variable |
|
|
95
|
-
| `$1`, `$2`, `$ARGUMENTS` | Script arguments |
|
|
96
|
-
| `# comment` | Comments (ignored) |
|
|
97
|
-
|
|
98
|
-
**Example: Variable capture and chaining** (`refactor-workflow.txt`):
|
|
92
|
+
**Example** (`code-review.rill`):
|
|
99
93
|
|
|
100
|
-
```
|
|
94
|
+
```rill
|
|
101
95
|
---
|
|
102
|
-
|
|
96
|
+
description: Code review workflow
|
|
97
|
+
args: path: string
|
|
103
98
|
---
|
|
104
|
-
# Phase 1: Analyze - capture issues list
|
|
105
|
-
prompt("Review $1 for error handling issues. List each issue with file:line.") -> $issues
|
|
106
99
|
|
|
107
|
-
#
|
|
108
|
-
prompt(
|
|
109
|
-
Fix these issues:
|
|
110
|
-
$issues
|
|
100
|
+
# Analyze the code
|
|
101
|
+
ccr::prompt("Review the code in {$path} for bugs") :> $issues
|
|
111
102
|
|
|
112
|
-
|
|
103
|
+
# Get fixes based on issues found
|
|
104
|
+
ccr::prompt(<<EOF
|
|
105
|
+
Based on these issues:
|
|
106
|
+
{$issues}
|
|
107
|
+
|
|
108
|
+
Suggest specific fixes with code examples.
|
|
113
109
|
EOF
|
|
114
|
-
)
|
|
110
|
+
) :> $fixes
|
|
115
111
|
|
|
116
|
-
#
|
|
117
|
-
prompt("
|
|
112
|
+
# Summarize
|
|
113
|
+
ccr::prompt("Summarize: Issues: {$issues} Fixes: {$fixes}")
|
|
118
114
|
```
|
|
119
115
|
|
|
120
|
-
**
|
|
116
|
+
**Host functions:**
|
|
121
117
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
| Function | Description |
|
|
119
|
+
| ----------------------------- | ---------------------------------- |
|
|
120
|
+
| `ccr::prompt(text, model?)` | Execute a Claude prompt |
|
|
121
|
+
| `ccr::command(name, args?)` | Run a command template |
|
|
122
|
+
| `ccr::skill(name, args?)` | Run a slash command |
|
|
123
|
+
| `ccr::get_result(text)` | Extract `<ccr:result>` from output |
|
|
124
|
+
| `ccr::file_exists(path)` | Check if file exists |
|
|
125
|
+
| `ccr::read_frontmatter(path)` | Parse YAML frontmatter |
|
|
126
|
+
| `ccr::error(message?)` | Stop execution with error |
|
|
125
127
|
|
|
126
|
-
|
|
127
|
-
prompt("Fix these test failures:\n$failures")
|
|
128
|
-
|
|
129
|
-
# Verify
|
|
130
|
-
command("run-tests", [$1])
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Scripts stop on `BLOCKED` or `ERROR` signals, catching issues before continuing to the next phase.
|
|
128
|
+
See [docs/rill-scripting.md](docs/rill-scripting.md) for the full scripting reference.
|
|
134
129
|
|
|
135
130
|
### Options
|
|
136
131
|
|
|
@@ -141,7 +136,7 @@ Scripts stop on `BLOCKED` or `ERROR` signals, catching issues before continuing
|
|
|
141
136
|
| `--quiet` | Minimal output (errors only) |
|
|
142
137
|
| `--normal` | Default output level |
|
|
143
138
|
| `--verbose` | Full output with details |
|
|
144
|
-
| `--
|
|
139
|
+
| `--log` | Enable file logging |
|
|
145
140
|
| `--deaddrop` | Enable [DeadDrop](https://deaddrop.sh) streaming |
|
|
146
141
|
|
|
147
142
|
**Example with model selection:**
|
|
@@ -150,91 +145,48 @@ Scripts stop on `BLOCKED` or `ERROR` signals, catching issues before continuing
|
|
|
150
145
|
claude-code-runner -m sonnet prompt "Explain this codebase"
|
|
151
146
|
```
|
|
152
147
|
|
|
153
|
-
##
|
|
154
|
-
|
|
155
|
-
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.
|
|
156
|
-
|
|
157
|
-
| Signal | Effect |
|
|
158
|
-
| --------------------------- | -------------------------------- |
|
|
159
|
-
| `:::RUNNER::REPEAT_STEP:::` | Run the same step again |
|
|
160
|
-
| `:::RUNNER::BLOCKED:::` | Exit with error (awaiting human) |
|
|
161
|
-
| `:::RUNNER::ERROR:::` | Exit with error |
|
|
162
|
-
|
|
163
|
-
No signal means success—the runner exits when Claude finishes without outputting a signal.
|
|
164
|
-
|
|
165
|
-
### Document-Driven Workflows
|
|
166
|
-
|
|
167
|
-
The real power of runner signals is **checklist-based execution**. Create a document with implementation steps, and Claude works through them one at a time across multiple invocations.
|
|
168
|
-
|
|
169
|
-
**Implementation plan** (`PLAN.md`):
|
|
170
|
-
|
|
171
|
-
```markdown
|
|
172
|
-
# Feature: User Authentication
|
|
173
|
-
|
|
174
|
-
- [ ] Create `src/auth/types.ts` with User and Session interfaces
|
|
175
|
-
- [ ] Implement `src/auth/session.ts` with createSession and validateSession
|
|
176
|
-
- [ ] Add JWT signing in `src/auth/jwt.ts`
|
|
177
|
-
- [ ] Write tests in `src/auth/__tests__/session.test.ts`
|
|
178
|
-
- [ ] Update `src/index.ts` to export auth module
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
**Command template** (`.claude/commands/work-plan.md`):
|
|
182
|
-
|
|
183
|
-
```markdown
|
|
184
|
-
Read $1 and find the first unchecked item (- [ ]).
|
|
148
|
+
## Results
|
|
185
149
|
|
|
186
|
-
|
|
187
|
-
2. Mark it complete by changing `- [ ]` to `- [x]`
|
|
188
|
-
3. Check if any unchecked items remain:
|
|
189
|
-
- If YES: output :::RUNNER::REPEAT_STEP:::
|
|
190
|
-
- If NO: output "All tasks complete"
|
|
150
|
+
Results let Claude communicate control flow decisions back to your scripts using XML:
|
|
191
151
|
|
|
192
|
-
|
|
152
|
+
```xml
|
|
153
|
+
<ccr:result type="repeat"/>
|
|
154
|
+
<ccr:result type="done"/>
|
|
155
|
+
<ccr:result type="blocked" reason="...">details</ccr:result>
|
|
193
156
|
```
|
|
194
157
|
|
|
195
|
-
|
|
158
|
+
Result types are application-defined. Your script extracts and handles them:
|
|
196
159
|
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
|
|
160
|
+
```rill
|
|
161
|
+
ccr::prompt("Fix bugs. Signal <ccr:result type='repeat'/> if more remain.") :> $result
|
|
162
|
+
ccr::get_result($result) :> $result
|
|
200
163
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
### Self-Correcting Loops
|
|
204
|
-
|
|
205
|
-
For retry-based patterns where Claude validates its own work:
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
claude-code-runner prompt "Fix all lint errors. Run the linter after each fix. Output :::RUNNER::REPEAT_STEP::: if errors remain, nothing if clean."
|
|
164
|
+
($result.type == "repeat") ? log("More work needed")
|
|
165
|
+
($result.type == "blocked") ? ccr::error($result.reason)
|
|
209
166
|
```
|
|
210
167
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```markdown
|
|
214
|
-
Run the test suite for $1.
|
|
215
|
-
|
|
216
|
-
- If tests pass: done
|
|
217
|
-
- If tests fail and fixable: fix them, output :::RUNNER::REPEAT_STEP:::
|
|
218
|
-
- If tests fail and stuck: output :::RUNNER::BLOCKED::: with explanation
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
**Defaults:**
|
|
222
|
-
|
|
223
|
-
- Max 10 iterations per command (prevents runaway loops)
|
|
224
|
-
- If no signal is detected, the runner uses the CLI exit code (0 = success, non-0 = error)
|
|
168
|
+
See [docs/results.md](docs/results.md) for workflow patterns.
|
|
225
169
|
|
|
226
170
|
## Exit Codes
|
|
227
171
|
|
|
228
172
|
For CI/CD integration:
|
|
229
173
|
|
|
230
|
-
| Code | Meaning
|
|
231
|
-
| ---- |
|
|
232
|
-
| 0 | Success
|
|
233
|
-
| 1 | Error (
|
|
174
|
+
| Code | Meaning |
|
|
175
|
+
| ---- | --------------------------------------- |
|
|
176
|
+
| 0 | Success |
|
|
177
|
+
| 1 | Error (script threw or Claude exited 1) |
|
|
234
178
|
|
|
235
179
|
## Logs
|
|
236
180
|
|
|
237
|
-
Sessions are logged to `./logs/` with timestamped filenames
|
|
181
|
+
Sessions are logged to `./logs/` with timestamped filenames when `--log` is specified.
|
|
182
|
+
|
|
183
|
+
## Documentation
|
|
184
|
+
|
|
185
|
+
- [Getting Started](docs/getting-started.md)
|
|
186
|
+
- [CLI Reference](docs/cli-reference.md)
|
|
187
|
+
- [Rill Scripting](docs/rill-scripting.md)
|
|
188
|
+
- [Results](docs/results.md)
|
|
189
|
+
- [Examples](docs/examples.md)
|
|
238
190
|
|
|
239
191
|
## Development
|
|
240
192
|
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
* CLI argument parsing
|
|
3
3
|
*/
|
|
4
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
5
|
export declare function parseArgs(args: string[]): ParsedArgs;
|
|
13
6
|
/**
|
|
14
7
|
* Print usage information
|
package/dist/cli/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,mBAAmB,CAAC;AA2D3B,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA2FpD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAsBjC"}
|
package/dist/cli/args.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CLI argument parsing
|
|
3
3
|
*/
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
|
-
import {
|
|
5
|
+
import { isRillScript } from '../rill/index.js';
|
|
6
6
|
import { loadCommandTemplate } from '../templates/command.js';
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
const pkg = require('../../package.json');
|
|
@@ -16,7 +16,7 @@ function extractOptions(args) {
|
|
|
16
16
|
process.exit(0);
|
|
17
17
|
}
|
|
18
18
|
let verbosity = 'normal';
|
|
19
|
-
let enableLog =
|
|
19
|
+
let enableLog = false;
|
|
20
20
|
let model = null;
|
|
21
21
|
let deaddrop = false;
|
|
22
22
|
const positionalArgs = [];
|
|
@@ -31,8 +31,8 @@ function extractOptions(args) {
|
|
|
31
31
|
else if (arg === '--verbose') {
|
|
32
32
|
verbosity = 'verbose';
|
|
33
33
|
}
|
|
34
|
-
else if (arg === '--
|
|
35
|
-
enableLog =
|
|
34
|
+
else if (arg === '--log') {
|
|
35
|
+
enableLog = true;
|
|
36
36
|
}
|
|
37
37
|
else if (arg === '--deaddrop') {
|
|
38
38
|
deaddrop = true;
|
|
@@ -49,32 +49,6 @@ function extractOptions(args) {
|
|
|
49
49
|
}
|
|
50
50
|
return { positionalArgs, verbosity, enableLog, model, deaddrop };
|
|
51
51
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Parse a command line into a prompt
|
|
54
|
-
* Used for script mode line parsing
|
|
55
|
-
*/
|
|
56
|
-
export function parseCommandLine(line) {
|
|
57
|
-
const parts = line.trim().split(/\s+/);
|
|
58
|
-
const cmd = parts[0];
|
|
59
|
-
if (cmd === 'prompt') {
|
|
60
|
-
return { prompt: parts.slice(1).join(' ') };
|
|
61
|
-
}
|
|
62
|
-
else if (cmd === 'command') {
|
|
63
|
-
const cmdName = parts[1];
|
|
64
|
-
if (!cmdName) {
|
|
65
|
-
throw new Error('command requires a name');
|
|
66
|
-
}
|
|
67
|
-
const { prompt } = loadCommandTemplate(cmdName, parts.slice(2));
|
|
68
|
-
return { prompt };
|
|
69
|
-
}
|
|
70
|
-
else if (cmd === 'script') {
|
|
71
|
-
throw new Error('script cannot be nested');
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
// Treat as raw prompt
|
|
75
|
-
return { prompt: line.trim() };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
52
|
/**
|
|
79
53
|
* Parse CLI arguments
|
|
80
54
|
*/
|
|
@@ -100,8 +74,6 @@ export function parseArgs(args) {
|
|
|
100
74
|
const subcommand = firstArg;
|
|
101
75
|
let prompt = '';
|
|
102
76
|
let displayCommand = '';
|
|
103
|
-
let scriptMode = false;
|
|
104
|
-
let scriptLines = [];
|
|
105
77
|
let scriptFile = null;
|
|
106
78
|
let scriptArgs = [];
|
|
107
79
|
let frontmatterModel = null;
|
|
@@ -123,24 +95,15 @@ export function parseArgs(args) {
|
|
|
123
95
|
const file = positionalArgs[1];
|
|
124
96
|
if (!file) {
|
|
125
97
|
console.error('Error: script file required');
|
|
126
|
-
console.error('Usage: claude-code-runner script <file> [args...]');
|
|
98
|
+
console.error('Usage: claude-code-runner script <file.rill> [args...]');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
if (!isRillScript(file)) {
|
|
102
|
+
console.error('Error: script must be a .rill file');
|
|
127
103
|
process.exit(1);
|
|
128
104
|
}
|
|
129
105
|
scriptFile = file;
|
|
130
106
|
scriptArgs = positionalArgs.slice(2);
|
|
131
|
-
const parsed = loadScript(file, scriptArgs);
|
|
132
|
-
// Convert parsed lines to display strings for backward compat
|
|
133
|
-
scriptLines = parsed.lines.map((line) => {
|
|
134
|
-
if (line.type === 'prompt') {
|
|
135
|
-
const text = line.text.length > 50 ? line.text.slice(0, 50) + '...' : line.text;
|
|
136
|
-
return `prompt("${text}")${line.capture ? ` -> $${line.capture}` : ''}`;
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
return `command("${line.name}")${line.capture ? ` -> $${line.capture}` : ''}`;
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
frontmatterModel = parsed.frontmatter.model ?? null;
|
|
143
|
-
scriptMode = true;
|
|
144
107
|
displayCommand = positionalArgs.slice(1).join(' ');
|
|
145
108
|
break;
|
|
146
109
|
}
|
|
@@ -162,11 +125,9 @@ export function parseArgs(args) {
|
|
|
162
125
|
deaddrop,
|
|
163
126
|
};
|
|
164
127
|
return {
|
|
165
|
-
subcommand
|
|
128
|
+
subcommand,
|
|
166
129
|
prompt,
|
|
167
130
|
displayCommand,
|
|
168
|
-
scriptLines,
|
|
169
|
-
scriptMode,
|
|
170
131
|
config,
|
|
171
132
|
scriptFile,
|
|
172
133
|
scriptArgs,
|
|
@@ -182,23 +143,18 @@ Claude Code Runner - executes claude CLI with proper TTY handling
|
|
|
182
143
|
Usage:
|
|
183
144
|
claude-code-runner [options] prompt <prompt>
|
|
184
145
|
claude-code-runner [options] command <name> [args...]
|
|
185
|
-
claude-code-runner [options] script <file> [args...]
|
|
146
|
+
claude-code-runner [options] script <file.rill> [args...]
|
|
186
147
|
|
|
187
148
|
Subcommands:
|
|
188
|
-
prompt <text> Run with the given prompt
|
|
189
|
-
command <name> [args] Load .claude/commands/<name>.md
|
|
190
|
-
script <file> [args]
|
|
191
|
-
|
|
192
|
-
Iteration Signals (control runner execution):
|
|
193
|
-
:::RUNNER::REPEAT_STEP::: Run the same step again
|
|
194
|
-
:::RUNNER::BLOCKED::: Exit with error (awaiting human intervention)
|
|
195
|
-
:::RUNNER::ERROR::: Exit with error (something went wrong)
|
|
149
|
+
prompt <text> Run with the given prompt
|
|
150
|
+
command <name> [args] Load .claude/commands/<name>.md template
|
|
151
|
+
script <file.rill> [args] Run a Rill script
|
|
196
152
|
|
|
197
153
|
Options:
|
|
198
154
|
--quiet Minimal output (errors only)
|
|
199
155
|
--normal Default output level
|
|
200
156
|
--verbose Full output with all details
|
|
201
|
-
--
|
|
157
|
+
--log Enable logging to file (disabled by default)
|
|
202
158
|
--model, -m <model> Specify Claude model (e.g., sonnet, opus, haiku)
|
|
203
159
|
--deaddrop Send messages to Deaddrop (requires DEADDROP_API_KEY env var)
|
|
204
160
|
`);
|
package/dist/cli/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { randomBytes } from 'crypto';
|
|
7
7
|
import { parseArgs } from './cli/args.js';
|
|
8
|
-
import { runWithSignals, } from './core/runner.js';
|
|
9
8
|
import { createDeadDropClientFromEnv } from './deaddrop/index.js';
|
|
10
9
|
import { configureDeadDrop, flushDeadDrop, printRunner, printRunnerInfo, } from './output/colors.js';
|
|
11
|
-
import { createFormatterState, finalizeStepStats, getRunStatsSummary,
|
|
10
|
+
import { createFormatterState, finalizeStepStats, getRunStatsSummary, } from './output/formatter.js';
|
|
12
11
|
import { createLogger } from './output/logger.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import { spawnClaude } from './process/pty.js';
|
|
13
|
+
import { runRillScript } from './rill/index.js';
|
|
15
14
|
import { DEFAULT_CONFIG } from './types/runner.js';
|
|
16
15
|
/**
|
|
17
16
|
* Generate a short unique run ID (8 chars, uppercase)
|
|
@@ -19,16 +18,6 @@ import { DEFAULT_CONFIG } from './types/runner.js';
|
|
|
19
18
|
function generateRunId() {
|
|
20
19
|
return randomBytes(4).toString('hex').toUpperCase();
|
|
21
20
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Format variables used for "with X" clause
|
|
24
|
-
*/
|
|
25
|
-
function formatVarsUsed(vars) {
|
|
26
|
-
if (vars.length === 0)
|
|
27
|
-
return '';
|
|
28
|
-
// Convert $_ to "last result", keep others as-is
|
|
29
|
-
const labels = vars.map((v) => (v === '$_' ? 'last result' : v));
|
|
30
|
-
return `with ${labels.join(', ')}: `;
|
|
31
|
-
}
|
|
32
21
|
async function main() {
|
|
33
22
|
const totalStart = Date.now();
|
|
34
23
|
const args = process.argv.slice(2);
|
|
@@ -50,22 +39,9 @@ async function main() {
|
|
|
50
39
|
configureDeadDrop(client.send.bind(client));
|
|
51
40
|
}
|
|
52
41
|
// Create logger
|
|
53
|
-
const
|
|
54
|
-
? 'script'
|
|
55
|
-
: parsed.subcommand === 'command'
|
|
56
|
-
? (args[1] ?? 'prompt')
|
|
57
|
-
: 'prompt';
|
|
58
|
-
const logger = createLogger(config.enableLog, config.logDir, commandName);
|
|
42
|
+
const logger = createLogger(config.enableLog, config.logDir, parsed.subcommand);
|
|
59
43
|
// Create formatter state
|
|
60
44
|
const formatterState = createFormatterState();
|
|
61
|
-
// Create runner context
|
|
62
|
-
const context = {
|
|
63
|
-
config,
|
|
64
|
-
logger,
|
|
65
|
-
formatterState,
|
|
66
|
-
cwd: process.cwd(),
|
|
67
|
-
runId,
|
|
68
|
-
};
|
|
69
45
|
// Emit starting run message first (operational, sent to deaddrop)
|
|
70
46
|
printRunner(`Starting run ${runId}`);
|
|
71
47
|
// Print config with [RUNNER] messages (informational, not sent to deaddrop)
|
|
@@ -80,95 +56,62 @@ async function main() {
|
|
|
80
56
|
printRunnerInfo(`Log: ${logger.filePath}`);
|
|
81
57
|
}
|
|
82
58
|
logger.logEvent({ event: 'run_start', runId });
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
59
|
+
// Handle script subcommand (Rill scripts only)
|
|
60
|
+
if (parsed.subcommand === 'script' && parsed.scriptFile) {
|
|
61
|
+
const result = await runRillScript({
|
|
62
|
+
scriptFile: parsed.scriptFile,
|
|
63
|
+
args: parsed.scriptArgs,
|
|
64
|
+
config,
|
|
65
|
+
logger,
|
|
66
|
+
formatterState,
|
|
67
|
+
cwd: process.cwd(),
|
|
68
|
+
runId,
|
|
69
|
+
});
|
|
70
|
+
// Print run completion
|
|
71
|
+
const totalDuration = Date.now() - totalStart;
|
|
72
|
+
const runSummary = getRunStatsSummary(formatterState, totalDuration);
|
|
73
|
+
printRunner(`Run ${runId} complete: ${runSummary}`);
|
|
74
|
+
logger.close();
|
|
75
|
+
await flushDeadDrop();
|
|
76
|
+
process.exit(result.success ? 0 : 1);
|
|
90
77
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
// Handle prompt and command subcommands (single execution)
|
|
79
|
+
const promptText = parsed.prompt;
|
|
80
|
+
if (parsed.subcommand === 'command' && !promptText) {
|
|
81
|
+
// This shouldn't happen - parseArgs should have handled it
|
|
82
|
+
console.error('Error: no prompt text');
|
|
83
|
+
process.exit(1);
|
|
94
84
|
}
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Build display string for a script line
|
|
103
|
-
*/
|
|
104
|
-
function getDisplayLine(line) {
|
|
105
|
-
if (line.type === 'prompt') {
|
|
106
|
-
// Replace newlines with spaces for single-line display
|
|
107
|
-
const cleaned = line.text.replace(/[\r\n]+/g, ' ').trim();
|
|
108
|
-
const preview = cleaned.length > 50 ? cleaned.slice(0, 50) + '...' : cleaned;
|
|
109
|
-
return `"${preview}"`;
|
|
85
|
+
// Set step info for formatter
|
|
86
|
+
formatterState.currentStep = 1;
|
|
87
|
+
formatterState.stepStartTime = Date.now();
|
|
88
|
+
if (config.verbosity !== 'quiet') {
|
|
89
|
+
printRunner(`Running: ${parsed.displayCommand}`);
|
|
110
90
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
promptText = template.prompt;
|
|
136
|
-
}
|
|
137
|
-
// Substitute variables
|
|
138
|
-
const varsUsed = getSubstitutionList(promptText, store);
|
|
139
|
-
const finalPrompt = substituteVariables(promptText, store, scriptArgs);
|
|
140
|
-
// Build display: show substituted prompt and what variables were used
|
|
141
|
-
const substitutedDisplay = getDisplayLine({
|
|
142
|
-
type: 'prompt',
|
|
143
|
-
text: finalPrompt,
|
|
144
|
-
});
|
|
145
|
-
const withClause = formatVarsUsed(varsUsed);
|
|
146
|
-
// Set step number and start time for formatter output
|
|
147
|
-
context.formatterState.currentStep = stepNum;
|
|
148
|
-
context.formatterState.stepStartTime = Date.now();
|
|
149
|
-
// Run via runWithSignals (handles iterations, signals, output)
|
|
150
|
-
const stepContext = { stepNum };
|
|
151
|
-
const result = await runWithSignals(finalPrompt, `${withClause}${substitutedDisplay}`, startTime, context, stepContext);
|
|
152
|
-
// Capture output for variable store
|
|
153
|
-
captureOutput(store, result.claudeText, line.capture);
|
|
154
|
-
// Finalize step stats and print completion
|
|
155
|
-
const stepDurationMs = context.formatterState.stepStartTime
|
|
156
|
-
? Date.now() - context.formatterState.stepStartTime
|
|
157
|
-
: (context.formatterState.lastStepDurationMs ?? 0);
|
|
158
|
-
const stepSummary = finalizeStepStats(context.formatterState, stepDurationMs);
|
|
159
|
-
printRunner(`Step ${stepNum} complete: ${stepSummary}`);
|
|
160
|
-
// Handle failure (runWithSignals already printed the error)
|
|
161
|
-
if (result.status !== 'ok') {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
// Reset step stats for next step (preserves runStats)
|
|
165
|
-
resetFormatterState(context.formatterState);
|
|
166
|
-
}
|
|
167
|
-
// Print run completion with overall stats
|
|
168
|
-
const totalDuration = Date.now() - startTime;
|
|
169
|
-
const runSummary = getRunStatsSummary(context.formatterState, totalDuration);
|
|
170
|
-
printRunner(`Run ${context.runId} complete: ${runSummary}`);
|
|
171
|
-
return true;
|
|
91
|
+
// Execute via PTY
|
|
92
|
+
const result = await spawnClaude({
|
|
93
|
+
prompt: promptText,
|
|
94
|
+
cwd: process.cwd(),
|
|
95
|
+
verbosity: config.verbosity,
|
|
96
|
+
logger,
|
|
97
|
+
formatterState,
|
|
98
|
+
parallelThresholdMs: config.parallelThresholdMs,
|
|
99
|
+
model: config.model,
|
|
100
|
+
});
|
|
101
|
+
// Finalize step stats
|
|
102
|
+
const stepDurationMs = formatterState.stepStartTime
|
|
103
|
+
? Date.now() - formatterState.stepStartTime
|
|
104
|
+
: 0;
|
|
105
|
+
const stepSummary = finalizeStepStats(formatterState, stepDurationMs);
|
|
106
|
+
printRunner(`Step 1 complete: ${stepSummary}`);
|
|
107
|
+
// Print run completion
|
|
108
|
+
const totalDuration = Date.now() - totalStart;
|
|
109
|
+
const runSummary = getRunStatsSummary(formatterState, totalDuration);
|
|
110
|
+
printRunner(`Run ${runId} complete: ${runSummary}`);
|
|
111
|
+
logger.logEvent({ event: 'run_complete', runId, exit: result.exitCode });
|
|
112
|
+
logger.close();
|
|
113
|
+
await flushDeadDrop();
|
|
114
|
+
process.exit(result.exitCode === 0 ? 0 : 1);
|
|
172
115
|
}
|
|
173
116
|
// Run main
|
|
174
117
|
main().catch((err) => {
|