rlph-cli 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/README.md +102 -0
- package/dist/agents/base.d.ts +16 -0
- package/dist/agents/base.d.ts.map +1 -0
- package/dist/agents/base.js +5 -0
- package/dist/agents/base.js.map +1 -0
- package/dist/agents/claude.d.ts +3 -0
- package/dist/agents/claude.d.ts.map +1 -0
- package/dist/agents/claude.js +80 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/index.d.ts +4 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +9 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/commands/run.d.ts +7 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +73 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/session/index.d.ts +3 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +3 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/logger.d.ts +10 -0
- package/dist/session/logger.d.ts.map +1 -0
- package/dist/session/logger.js +17 -0
- package/dist/session/logger.js.map +1 -0
- package/dist/session/manager.d.ts +18 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +29 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/utils/files.d.ts +4 -0
- package/dist/utils/files.d.ts.map +1 -0
- package/dist/utils/files.js +39 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Ralph
|
|
2
|
+
|
|
3
|
+
Loop coding agent CLI - run AI coding agents headlessly in a loop.
|
|
4
|
+
|
|
5
|
+
Inspired by [Geoff Huntley's ralph technique](https://ghuntley.com/ralph/) - putting a coding agent in a while loop and letting it work autonomously.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
while :; do cat prompt.md | claude -p; done
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Ralph wraps this pattern into a proper CLI with session logging, iteration limits, and automatic task completion detection.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install -g rlph-cli
|
|
18
|
+
|
|
19
|
+
# or run directly
|
|
20
|
+
npx rlph-cli run -p "your task"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### From source
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
git clone https://github.com/rem4ik4ever/ralph.git
|
|
27
|
+
cd ralph
|
|
28
|
+
bun install
|
|
29
|
+
bun run build
|
|
30
|
+
bun link
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ralph run -p <prompt> [-a agent] [-i iterations]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Options
|
|
40
|
+
|
|
41
|
+
| Flag | Description | Default |
|
|
42
|
+
|------|-------------|---------|
|
|
43
|
+
| `-p, --prompt <files...>` | Prompt text or files to pass to agent | required |
|
|
44
|
+
| `-a, --agent <agent>` | Agent type (currently: claude) | `claude` |
|
|
45
|
+
| `-i, --iterations <n>` | Max loop iterations | `4` |
|
|
46
|
+
|
|
47
|
+
### Examples
|
|
48
|
+
|
|
49
|
+
**Simple task**
|
|
50
|
+
```bash
|
|
51
|
+
ralph run -p "fix the login bug" -i 3
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Using a prompt file**
|
|
55
|
+
```bash
|
|
56
|
+
ralph run -p prompt.md -i 10
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Multiple prompts/files**
|
|
60
|
+
```bash
|
|
61
|
+
ralph run -p task.md context.md "also add tests"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Long running task**
|
|
65
|
+
```bash
|
|
66
|
+
ralph run -p "port this codebase from React to Vue" -i 50
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## How it works
|
|
70
|
+
|
|
71
|
+
1. Ralph reads your prompt (text or files)
|
|
72
|
+
2. Appends completion instructions asking agent to output `<ralph>RALPH_COMPLETED</ralph>` when done
|
|
73
|
+
3. Runs the agent in a loop up to N iterations
|
|
74
|
+
4. Streams output in real-time
|
|
75
|
+
5. Stops early if agent signals completion
|
|
76
|
+
6. Logs each iteration to `~/.ralph/sessions/<session-id>/`
|
|
77
|
+
|
|
78
|
+
## Session logs
|
|
79
|
+
|
|
80
|
+
All sessions are logged to `~/.ralph/sessions/`:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
~/.ralph/sessions/
|
|
84
|
+
└── <session-id>/
|
|
85
|
+
├── meta.json # session metadata
|
|
86
|
+
├── 0.log # iteration 0 output
|
|
87
|
+
├── 1.log # iteration 1 output
|
|
88
|
+
└── ...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Supported agents
|
|
92
|
+
|
|
93
|
+
- `claude` - Claude Code CLI (requires [claude](https://claude.ai/claude-code) installed)
|
|
94
|
+
|
|
95
|
+
## Requirements
|
|
96
|
+
|
|
97
|
+
- Node.js >= 18
|
|
98
|
+
- Claude Code CLI installed and authenticated
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AgentResult {
|
|
2
|
+
output: string;
|
|
3
|
+
exitCode: number;
|
|
4
|
+
duration: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ExecuteOptions {
|
|
7
|
+
onOutput?: (chunk: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export interface Agent {
|
|
10
|
+
name: string;
|
|
11
|
+
execute(prompt: string, cwd: string, options?: ExecuteOptions): Promise<AgentResult>;
|
|
12
|
+
}
|
|
13
|
+
export type AgentType = 'claude';
|
|
14
|
+
export declare const SUPPORTED_AGENTS: AgentType[];
|
|
15
|
+
export declare function isValidAgent(agent: string): agent is AgentType;
|
|
16
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CACrF;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAA;AAEhC,eAAO,MAAM,gBAAgB,EAAE,SAAS,EAAe,CAAA;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/agents/base.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,gBAAgB,GAAgB,CAAC,QAAQ,CAAC,CAAA;AAEvD,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,KAAkB,CAAC,CAAA;AACtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAA+B,MAAM,WAAW,CAAA;AAmBnE,eAAO,MAAM,MAAM,EAAE,KAqEpB,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
function parseStreamJson(line) {
|
|
3
|
+
try {
|
|
4
|
+
const data = JSON.parse(line);
|
|
5
|
+
// Only parse assistant messages, skip result (already streamed)
|
|
6
|
+
if (data.type === 'assistant' && data.message?.content) {
|
|
7
|
+
for (const block of data.message.content) {
|
|
8
|
+
if (block.type === 'text') {
|
|
9
|
+
return block.text;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// Not valid JSON, ignore
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export const claude = {
|
|
20
|
+
name: 'claude',
|
|
21
|
+
async execute(prompt, cwd, options) {
|
|
22
|
+
const startTime = Date.now();
|
|
23
|
+
const onOutput = options?.onOutput;
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const proc = spawn('claude', [
|
|
26
|
+
'-p',
|
|
27
|
+
'--dangerously-skip-permissions',
|
|
28
|
+
'--output-format', 'stream-json',
|
|
29
|
+
'--verbose',
|
|
30
|
+
], {
|
|
31
|
+
cwd,
|
|
32
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
33
|
+
shell: true,
|
|
34
|
+
});
|
|
35
|
+
let output = '';
|
|
36
|
+
let stderr = '';
|
|
37
|
+
let buffer = '';
|
|
38
|
+
proc.stdout.on('data', (data) => {
|
|
39
|
+
buffer += data.toString();
|
|
40
|
+
const lines = buffer.split('\n');
|
|
41
|
+
buffer = lines.pop() || ''; // Keep incomplete line in buffer
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
if (!line.trim())
|
|
44
|
+
continue;
|
|
45
|
+
const text = parseStreamJson(line);
|
|
46
|
+
if (text) {
|
|
47
|
+
output += text;
|
|
48
|
+
onOutput?.(text);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
proc.stderr.on('data', (data) => {
|
|
53
|
+
const chunk = data.toString();
|
|
54
|
+
stderr += chunk;
|
|
55
|
+
});
|
|
56
|
+
proc.on('error', (err) => {
|
|
57
|
+
reject(new Error(`Failed to spawn claude: ${err.message}`));
|
|
58
|
+
});
|
|
59
|
+
proc.on('close', (code) => {
|
|
60
|
+
// Process any remaining buffer
|
|
61
|
+
if (buffer.trim()) {
|
|
62
|
+
const text = parseStreamJson(buffer);
|
|
63
|
+
if (text) {
|
|
64
|
+
output += text;
|
|
65
|
+
onOutput?.(text);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const duration = Date.now() - startTime;
|
|
69
|
+
resolve({
|
|
70
|
+
output: output + (stderr ? `\n[stderr]\n${stderr}` : ''),
|
|
71
|
+
exitCode: code ?? 1,
|
|
72
|
+
duration,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
proc.stdin.write(prompt);
|
|
76
|
+
proc.stdin.end();
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAOjD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAE/C;AAED,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,MAAM,GAA6B;IACvC,MAAM;CACP,CAAA;AAED,MAAM,UAAU,QAAQ,CAAC,IAAe;IACtC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;AACrB,CAAC;AAED,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAsB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EzD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getAgent, isValidAgent } from '../agents/index.js';
|
|
3
|
+
import { createSession, writeLog, getSessionDir } from '../session/index.js';
|
|
4
|
+
import { buildPrompt, COMPLETION_MARKER } from '../utils/index.js';
|
|
5
|
+
export async function run(opts) {
|
|
6
|
+
// Validate agent
|
|
7
|
+
if (!isValidAgent(opts.agent)) {
|
|
8
|
+
console.error(chalk.red(`Unknown agent: ${opts.agent}`));
|
|
9
|
+
console.error(`Supported agents: claude`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
// Validate iterations
|
|
13
|
+
const iterations = parseInt(opts.iterations, 10);
|
|
14
|
+
if (isNaN(iterations) || iterations <= 0) {
|
|
15
|
+
console.error(chalk.red(`Iterations must be a positive number, got: ${opts.iterations}`));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const agent = getAgent(opts.agent);
|
|
19
|
+
// Build prompt with completion instructions
|
|
20
|
+
let prompt;
|
|
21
|
+
try {
|
|
22
|
+
prompt = await buildPrompt(opts.prompt);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
26
|
+
console.error(chalk.red(`Failed to read prompt files: ${message}`));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
// Create session
|
|
30
|
+
const sessionId = await createSession({
|
|
31
|
+
promptFiles: opts.prompt,
|
|
32
|
+
agent: opts.agent,
|
|
33
|
+
iterations,
|
|
34
|
+
});
|
|
35
|
+
console.log(chalk.blue(`Session: ${sessionId}`));
|
|
36
|
+
console.log(chalk.gray(`Agent: ${agent.name}`));
|
|
37
|
+
console.log(chalk.gray(`Iterations: ${iterations}`));
|
|
38
|
+
console.log();
|
|
39
|
+
// Run loop
|
|
40
|
+
let completed = false;
|
|
41
|
+
let actualIterations = 0;
|
|
42
|
+
for (let i = 0; i < iterations; i++) {
|
|
43
|
+
actualIterations++;
|
|
44
|
+
console.log(chalk.yellow(`[${i + 1}/${iterations}] Running ${agent.name}...`));
|
|
45
|
+
console.log();
|
|
46
|
+
const result = await agent.execute(prompt, process.cwd(), {
|
|
47
|
+
onOutput: (chunk) => process.stdout.write(chunk),
|
|
48
|
+
});
|
|
49
|
+
console.log();
|
|
50
|
+
await writeLog(sessionId, i, result);
|
|
51
|
+
if (result.exitCode !== 0) {
|
|
52
|
+
console.log(chalk.red(` Exit code: ${result.exitCode}`));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log(chalk.green(` Done (${result.duration}ms)`));
|
|
56
|
+
}
|
|
57
|
+
// Check for completion marker
|
|
58
|
+
if (result.output.includes(COMPLETION_MARKER)) {
|
|
59
|
+
console.log(chalk.cyan(` Agent signaled task complete`));
|
|
60
|
+
completed = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
console.log();
|
|
65
|
+
if (completed) {
|
|
66
|
+
console.log(chalk.green(`Task completed after ${actualIterations} iteration(s)`));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log(chalk.yellow(`Reached max iterations (${iterations})`));
|
|
70
|
+
}
|
|
71
|
+
console.log(chalk.gray(`Logs: ${getSessionDir(sessionId)}`));
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.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":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { run } from './commands/run.js';
|
|
4
|
+
program
|
|
5
|
+
.name('ralph')
|
|
6
|
+
.description('Loop coding agent CLI - run agents headlessly in a loop')
|
|
7
|
+
.version('0.1.0');
|
|
8
|
+
program
|
|
9
|
+
.command('run')
|
|
10
|
+
.description('Run an agent in a loop')
|
|
11
|
+
.requiredOption('-p, --prompt <files...>', 'Prompt files to pass to agent')
|
|
12
|
+
.option('-a, --agent <agent>', 'Agent type', 'claude')
|
|
13
|
+
.option('-i, --iterations <n>', 'Number of loop iterations', '4')
|
|
14
|
+
.action(run);
|
|
15
|
+
program.parse();
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAEvC,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,wBAAwB,CAAC;KACrC,cAAc,CAAC,yBAAyB,EAAE,+BAA+B,CAAC;KAC1E,MAAM,CAAC,qBAAqB,EAAE,YAAY,EAAE,QAAQ,CAAC;KACrD,MAAM,CAAC,sBAAsB,EAAE,2BAA2B,EAAE,GAAG,CAAC;KAChE,MAAM,CAAC,GAAG,CAAC,CAAA;AAEd,OAAO,CAAC,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentResult } from '../agents/base.js';
|
|
2
|
+
export interface LogEntry {
|
|
3
|
+
iteration: number;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
duration: number;
|
|
6
|
+
exitCode: number;
|
|
7
|
+
output: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function writeLog(sessionId: string, iteration: number, result: AgentResult): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/session/logger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGpD,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getSessionDir } from './manager.js';
|
|
4
|
+
export async function writeLog(sessionId, iteration, result) {
|
|
5
|
+
const sessionDir = getSessionDir(sessionId);
|
|
6
|
+
const logPath = join(sessionDir, `${iteration}.log`);
|
|
7
|
+
const header = [
|
|
8
|
+
`# Iteration ${iteration}`,
|
|
9
|
+
`Timestamp: ${new Date().toISOString()}`,
|
|
10
|
+
`Duration: ${result.duration}ms`,
|
|
11
|
+
`Exit Code: ${result.exitCode}`,
|
|
12
|
+
'---',
|
|
13
|
+
'',
|
|
14
|
+
].join('\n');
|
|
15
|
+
await writeFile(logPath, header + result.output);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/session/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAU5C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,SAAiB,EACjB,SAAiB,EACjB,MAAmB;IAEnB,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,SAAS,MAAM,CAAC,CAAA;IAEpD,MAAM,MAAM,GAAG;QACb,eAAe,SAAS,EAAE;QAC1B,cAAc,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;QACxC,aAAa,MAAM,CAAC,QAAQ,IAAI;QAChC,cAAc,MAAM,CAAC,QAAQ,EAAE;QAC/B,KAAK;QACL,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;AAClD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SessionMeta {
|
|
2
|
+
id: string;
|
|
3
|
+
promptFiles: string[];
|
|
4
|
+
agent: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
iterations: number;
|
|
7
|
+
startTime: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getRalphDir(): string;
|
|
10
|
+
export declare function getSessionsDir(): string;
|
|
11
|
+
export declare function getSessionDir(sessionId: string): string;
|
|
12
|
+
export interface CreateSessionOpts {
|
|
13
|
+
promptFiles: string[];
|
|
14
|
+
agent: string;
|
|
15
|
+
iterations: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function createSession(opts: CreateSessionOpts): Promise<string>;
|
|
18
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB5E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { nanoid } from 'nanoid';
|
|
5
|
+
export function getRalphDir() {
|
|
6
|
+
return join(homedir(), '.ralph');
|
|
7
|
+
}
|
|
8
|
+
export function getSessionsDir() {
|
|
9
|
+
return join(getRalphDir(), 'sessions');
|
|
10
|
+
}
|
|
11
|
+
export function getSessionDir(sessionId) {
|
|
12
|
+
return join(getSessionsDir(), sessionId);
|
|
13
|
+
}
|
|
14
|
+
export async function createSession(opts) {
|
|
15
|
+
const sessionId = nanoid(10);
|
|
16
|
+
const sessionDir = getSessionDir(sessionId);
|
|
17
|
+
await mkdir(sessionDir, { recursive: true });
|
|
18
|
+
const meta = {
|
|
19
|
+
id: sessionId,
|
|
20
|
+
promptFiles: opts.promptFiles,
|
|
21
|
+
agent: opts.agent,
|
|
22
|
+
cwd: process.cwd(),
|
|
23
|
+
iterations: opts.iterations,
|
|
24
|
+
startTime: new Date().toISOString(),
|
|
25
|
+
};
|
|
26
|
+
await writeFile(join(sessionDir, 'meta.json'), JSON.stringify(meta, null, 2));
|
|
27
|
+
return sessionId;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAW/B,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAA;AAClC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,CAAC,CAAA;AAC1C,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAuB;IACzD,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,CAAA;IAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IAE3C,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE5C,MAAM,IAAI,GAAgB;QACxB,EAAE,EAAE,SAAS;QACb,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAA;IAED,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAE7E,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,mCAAmC,CAAA;AAmBjE,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBvE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAGnE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFile, access } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
export const COMPLETION_MARKER = '<ralph>RALPH_COMPLETED</ralph>';
|
|
4
|
+
const COMPLETION_INSTRUCTIONS = `
|
|
5
|
+
---
|
|
6
|
+
When you have fully completed the task with no remaining work, include this marker in your final response:
|
|
7
|
+
${COMPLETION_MARKER}
|
|
8
|
+
|
|
9
|
+
Only use this marker when the task is 100% complete.
|
|
10
|
+
`;
|
|
11
|
+
async function fileExists(path) {
|
|
12
|
+
try {
|
|
13
|
+
await access(path);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function readPromptFiles(inputs) {
|
|
21
|
+
const contents = [];
|
|
22
|
+
for (const input of inputs) {
|
|
23
|
+
const absolutePath = resolve(process.cwd(), input);
|
|
24
|
+
if (await fileExists(absolutePath)) {
|
|
25
|
+
const content = await readFile(absolutePath, 'utf-8');
|
|
26
|
+
contents.push(content);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// treat as direct text
|
|
30
|
+
contents.push(input);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return contents.join('\n\n');
|
|
34
|
+
}
|
|
35
|
+
export async function buildPrompt(inputs) {
|
|
36
|
+
const content = await readPromptFiles(inputs);
|
|
37
|
+
return content + COMPLETION_INSTRUCTIONS;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,CAAC,MAAM,iBAAiB,GAAG,gCAAgC,CAAA;AAEjE,MAAM,uBAAuB,GAAG;;;EAG9B,iBAAiB;;;CAGlB,CAAA;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAgB;IACpD,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAA;QAElD,IAAI,MAAM,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;YACrD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,CAAC;aAAM,CAAC;YACN,uBAAuB;YACvB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAgB;IAChD,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAA;IAC7C,OAAO,OAAO,GAAG,uBAAuB,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rlph-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Loop coding agent CLI - run agents headlessly in a loop",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ralph": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsc --watch",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"test:coverage": "vitest run --coverage",
|
|
21
|
+
"prepublishOnly": "bun run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"cli",
|
|
25
|
+
"agent",
|
|
26
|
+
"claude",
|
|
27
|
+
"loop",
|
|
28
|
+
"automation"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/rem4ik4ever/ralph.git"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.3.0",
|
|
37
|
+
"commander": "^12.1.0",
|
|
38
|
+
"nanoid": "^5.0.9"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^22.10.5",
|
|
42
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
43
|
+
"typescript": "^5.7.3",
|
|
44
|
+
"vitest": "^2.1.8"
|
|
45
|
+
}
|
|
46
|
+
}
|