openrune 0.2.1 → 0.3.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 +61 -93
- package/bin/rune.js +76 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,10 +44,6 @@ Building a Claude Code harness usually means wiring up process management, I/O p
|
|
|
44
44
|
|
|
45
45
|
**Scriptable** — Chain agents, set up triggers, or call agents from your own code via the Node.js API. One file format, multiple ways to use it.
|
|
46
46
|
|
|
47
|
-
<p align="center">
|
|
48
|
-
<img src="demo.gif" width="100%" alt="Rune demo" />
|
|
49
|
-
</p>
|
|
50
|
-
|
|
51
47
|
---
|
|
52
48
|
|
|
53
49
|
## Quick Start
|
|
@@ -63,31 +59,24 @@ Building a Claude Code harness usually means wiring up process management, I/O p
|
|
|
63
59
|
npm install -g openrune
|
|
64
60
|
```
|
|
65
61
|
|
|
66
|
-
### 2. Create
|
|
62
|
+
### 2. Create an agent
|
|
67
63
|
|
|
68
64
|
```bash
|
|
69
65
|
cd ~/my-project
|
|
70
|
-
rune new
|
|
66
|
+
rune new reviewer --role "Code reviewer, security focused"
|
|
71
67
|
```
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<p align="center">
|
|
76
|
-
<img src="Screenshot.png" width="500" alt="Right-click to create a Rune agent" />
|
|
77
|
-
</p>
|
|
78
|
-
|
|
79
|
-
### 3. Use it
|
|
80
|
-
|
|
81
|
-
**Desktop UI** — Double-click the `.rune` file, or:
|
|
69
|
+
### 3. Run it
|
|
82
70
|
|
|
83
71
|
```bash
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
# Headless — run from CLI, get results in your terminal
|
|
73
|
+
rune run reviewer.rune "Review the latest commit"
|
|
86
74
|
|
|
87
|
-
|
|
75
|
+
# Pipe input from other commands
|
|
76
|
+
git diff | rune run reviewer.rune "Review this diff"
|
|
88
77
|
|
|
89
|
-
|
|
90
|
-
rune
|
|
78
|
+
# Desktop UI — open the chat interface
|
|
79
|
+
rune open reviewer.rune
|
|
91
80
|
```
|
|
92
81
|
|
|
93
82
|
---
|
|
@@ -120,71 +109,7 @@ rune watch ops.rune --on cron --interval 10m --prompt "Check if the API is healt
|
|
|
120
109
|
|
|
121
110
|
---
|
|
122
111
|
|
|
123
|
-
##
|
|
124
|
-
|
|
125
|
-
### Harness
|
|
126
|
-
|
|
127
|
-
- **Headless execution** — `rune run` lets you run agents from the CLI, scripts, or CI/CD. No GUI needed.
|
|
128
|
-
- **Agent chaining** — `rune pipe` connects agents in sequence. Each agent's output feeds into the next.
|
|
129
|
-
- **Automated triggers** — `rune watch` runs agents on file changes, git commits, or a cron schedule.
|
|
130
|
-
- **Node.js API** — `require('openrune')` to use agents programmatically in your own code.
|
|
131
|
-
- **Persistent context** — Role, memory, and chat history are saved in the `.rune` file across sessions.
|
|
132
|
-
|
|
133
|
-
### Desktop UI
|
|
134
|
-
|
|
135
|
-
- **Chat interface** — Markdown rendering, file attachment, stream cancellation.
|
|
136
|
-
- **Real-time activity** — See every tool call, result, and permission request as it happens via [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks).
|
|
137
|
-
- **Built-in terminal** — Raw Claude Code output and your own commands, side by side.
|
|
138
|
-
|
|
139
|
-
### Agent Roles
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
# General assistant
|
|
143
|
-
rune new assistant
|
|
144
|
-
|
|
145
|
-
# Specialized agents
|
|
146
|
-
rune new designer --role "UI/UX design expert"
|
|
147
|
-
rune new backend --role "Backend developer, Node.js specialist"
|
|
148
|
-
rune new reviewer --role "Code reviewer, focused on security and performance"
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### The `.rune` File
|
|
152
|
-
|
|
153
|
-
A `.rune` file is just JSON:
|
|
154
|
-
|
|
155
|
-
```json
|
|
156
|
-
{
|
|
157
|
-
"name": "myagent",
|
|
158
|
-
"role": "General assistant",
|
|
159
|
-
"icon": "bot",
|
|
160
|
-
"createdAt": "2025-01-01T00:00:00Z",
|
|
161
|
-
"history": []
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Edit the `role` field anytime to change the agent's behavior.
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## CLI Commands
|
|
170
|
-
|
|
171
|
-
| Command | Description |
|
|
172
|
-
|---------|-------------|
|
|
173
|
-
| `rune install` | Build app, register file association, install Quick Action |
|
|
174
|
-
| `rune new <name>` | Create a `.rune` file in the current directory |
|
|
175
|
-
| `rune new <name> --role "..."` | Create with a custom role |
|
|
176
|
-
| `rune open <file.rune>` | Open a `.rune` file (desktop GUI) |
|
|
177
|
-
| `rune run <file.rune> "prompt"` | Run agent headlessly (no GUI) |
|
|
178
|
-
| `rune pipe <a.rune> <b.rune> "prompt"` | Chain agents in a pipeline |
|
|
179
|
-
| `rune watch <file.rune> --on <event>` | Set up automated triggers |
|
|
180
|
-
| `rune list` | List `.rune` files in the current directory |
|
|
181
|
-
| `rune uninstall` | Remove Rune integration (keeps your `.rune` files) |
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Harness Mode
|
|
186
|
-
|
|
187
|
-
Rune isn't just a desktop app — it's a full agent harness. Use it from scripts, CI/CD, or your own tools.
|
|
112
|
+
## Harness
|
|
188
113
|
|
|
189
114
|
### Headless execution
|
|
190
115
|
|
|
@@ -245,6 +170,55 @@ const { finalOutput } = await rune.pipe(
|
|
|
245
170
|
|
|
246
171
|
---
|
|
247
172
|
|
|
173
|
+
## Desktop UI
|
|
174
|
+
|
|
175
|
+
Rune also includes a desktop app for interactive use. Double-click a `.rune` file or run `rune open`.
|
|
176
|
+
|
|
177
|
+
- **Chat interface** — Markdown rendering, file attachment, stream cancellation.
|
|
178
|
+
- **Real-time activity** — See every tool call, result, and permission request as it happens via [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks).
|
|
179
|
+
- **Built-in terminal** — Raw Claude Code output and your own commands, side by side.
|
|
180
|
+
- **Right-click to create** — macOS Quick Action lets you create agents from Finder.
|
|
181
|
+
|
|
182
|
+
<p align="center">
|
|
183
|
+
<img src="demo.gif" width="100%" alt="Rune demo" />
|
|
184
|
+
</p>
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## The `.rune` File
|
|
189
|
+
|
|
190
|
+
A `.rune` file is just JSON:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"name": "reviewer",
|
|
195
|
+
"role": "Code reviewer, security focused",
|
|
196
|
+
"createdAt": "2025-01-01T00:00:00Z",
|
|
197
|
+
"history": [],
|
|
198
|
+
"memory": []
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Edit the `role` field anytime to change the agent's behavior. History and memory persist across sessions automatically.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## CLI Commands
|
|
207
|
+
|
|
208
|
+
| Command | Description |
|
|
209
|
+
|---------|-------------|
|
|
210
|
+
| `rune new <name>` | Create a `.rune` file in the current directory |
|
|
211
|
+
| `rune new <name> --role "..."` | Create with a custom role |
|
|
212
|
+
| `rune run <file.rune> "prompt"` | Run agent headlessly (no GUI) |
|
|
213
|
+
| `rune pipe <a.rune> <b.rune> "prompt"` | Chain agents in a pipeline |
|
|
214
|
+
| `rune watch <file.rune> --on <event>` | Set up automated triggers |
|
|
215
|
+
| `rune open <file.rune>` | Open a `.rune` file (desktop GUI) |
|
|
216
|
+
| `rune list` | List `.rune` files in the current directory |
|
|
217
|
+
| `rune install` | Build app, register file association, install Quick Action |
|
|
218
|
+
| `rune uninstall` | Remove Rune integration (keeps your `.rune` files) |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
248
222
|
## Architecture
|
|
249
223
|
|
|
250
224
|
```
|
|
@@ -273,8 +247,8 @@ const { finalOutput } = await rune.pipe(
|
|
|
273
247
|
|
|
274
248
|
**Two modes of operation:**
|
|
275
249
|
|
|
276
|
-
1. **
|
|
277
|
-
2. **
|
|
250
|
+
1. **Harness** — Direct CLI execution via `claude -p`. Agents run headlessly with context from the `.rune` file.
|
|
251
|
+
2. **Desktop UI** — Chat input → MCP channel → Claude Code, with hooks for real-time activity monitoring.
|
|
278
252
|
|
|
279
253
|
---
|
|
280
254
|
|
|
@@ -319,12 +293,6 @@ Rune/
|
|
|
319
293
|
lib/ # Utilities
|
|
320
294
|
```
|
|
321
295
|
|
|
322
|
-
### Hooks Configuration
|
|
323
|
-
|
|
324
|
-
Rune automatically sets up Claude Code hooks in `~/.claude/settings.json`. The hooks only fire when `RUNE_CHANNEL_PORT` is set, so they don't affect standalone Claude Code usage.
|
|
325
|
-
|
|
326
|
-
Captured events: `PreToolUse`, `PostToolUse`, `PermissionRequest`, `UserPromptSubmit`, `Stop`, `Notification`, `SessionStart`, `SessionEnd`.
|
|
327
|
-
|
|
328
296
|
---
|
|
329
297
|
|
|
330
298
|
## Important Notice
|
package/bin/rune.js
CHANGED
|
@@ -656,8 +656,9 @@ function openRune(file) {
|
|
|
656
656
|
|
|
657
657
|
function runRune(file, restArgs) {
|
|
658
658
|
if (!file) {
|
|
659
|
-
console.log('Usage: rune run <file.rune> "prompt" [--output json|text]')
|
|
659
|
+
console.log('Usage: rune run <file.rune> "prompt" [--auto] [--output json|text]')
|
|
660
660
|
console.log('Example: rune run reviewer.rune "Review the latest commit"')
|
|
661
|
+
console.log(' rune run coder.rune "Build a REST API server" --auto')
|
|
661
662
|
process.exit(1)
|
|
662
663
|
}
|
|
663
664
|
|
|
@@ -670,10 +671,13 @@ function runRune(file, restArgs) {
|
|
|
670
671
|
// Parse args: prompt and flags
|
|
671
672
|
let prompt = ''
|
|
672
673
|
let outputFormat = 'text'
|
|
674
|
+
let autoMode = false
|
|
673
675
|
for (let i = 0; i < restArgs.length; i++) {
|
|
674
676
|
if (restArgs[i] === '--output' && restArgs[i + 1]) {
|
|
675
677
|
outputFormat = restArgs[i + 1]
|
|
676
678
|
i++
|
|
679
|
+
} else if (restArgs[i] === '--auto') {
|
|
680
|
+
autoMode = true
|
|
677
681
|
} else if (!prompt) {
|
|
678
682
|
prompt = restArgs[i]
|
|
679
683
|
}
|
|
@@ -710,7 +714,76 @@ function runRune(file, restArgs) {
|
|
|
710
714
|
|
|
711
715
|
const systemPrompt = systemParts.join('\n')
|
|
712
716
|
|
|
713
|
-
//
|
|
717
|
+
// Auto mode: agent can read/write files, run commands, fix errors autonomously
|
|
718
|
+
if (autoMode) {
|
|
719
|
+
console.log(`🔮 [auto] ${rune.name} is working on: ${prompt}\n`)
|
|
720
|
+
|
|
721
|
+
const claudeArgs = ['-p', '--print',
|
|
722
|
+
'--permission-mode', 'auto',
|
|
723
|
+
'--output-format', 'stream-json',
|
|
724
|
+
'--include-hook-events',
|
|
725
|
+
]
|
|
726
|
+
if (systemPrompt) {
|
|
727
|
+
claudeArgs.push('--system-prompt', systemPrompt)
|
|
728
|
+
}
|
|
729
|
+
claudeArgs.push(prompt)
|
|
730
|
+
|
|
731
|
+
const child = spawn('claude', claudeArgs, {
|
|
732
|
+
cwd: folderPath,
|
|
733
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
734
|
+
env: { ...process.env },
|
|
735
|
+
})
|
|
736
|
+
|
|
737
|
+
let fullOutput = ''
|
|
738
|
+
|
|
739
|
+
child.stdout.on('data', (data) => {
|
|
740
|
+
const lines = data.toString().split('\n').filter(Boolean)
|
|
741
|
+
for (const line of lines) {
|
|
742
|
+
try {
|
|
743
|
+
const event = JSON.parse(line)
|
|
744
|
+
|
|
745
|
+
if (event.type === 'assistant' && event.subtype === 'tool_use') {
|
|
746
|
+
const tool = event.tool_name || event.name || 'unknown'
|
|
747
|
+
const input = event.input || {}
|
|
748
|
+
if (tool === 'Bash') {
|
|
749
|
+
console.log(` ▶ Bash: ${(input.command || '').slice(0, 120)}`)
|
|
750
|
+
} else if (tool === 'Write') {
|
|
751
|
+
console.log(` ▶ Write: ${input.file_path || ''}`)
|
|
752
|
+
} else if (tool === 'Edit') {
|
|
753
|
+
console.log(` ▶ Edit: ${input.file_path || ''}`)
|
|
754
|
+
} else if (tool === 'Read') {
|
|
755
|
+
console.log(` ▶ Read: ${input.file_path || ''}`)
|
|
756
|
+
} else {
|
|
757
|
+
console.log(` ▶ ${tool}`)
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
if (event.type === 'result') {
|
|
762
|
+
fullOutput = event.result || ''
|
|
763
|
+
console.log(`\n${fullOutput}`)
|
|
764
|
+
}
|
|
765
|
+
} catch {}
|
|
766
|
+
}
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
child.stderr.on('data', (d) => { process.stderr.write(d) })
|
|
770
|
+
|
|
771
|
+
child.on('close', (code) => {
|
|
772
|
+
// Save to history
|
|
773
|
+
rune.history = rune.history || []
|
|
774
|
+
rune.history.push({ role: 'user', text: prompt, ts: Date.now() })
|
|
775
|
+
rune.history.push({ role: 'assistant', text: fullOutput.trim(), ts: Date.now() })
|
|
776
|
+
fs.writeFileSync(filePath, JSON.stringify(rune, null, 2))
|
|
777
|
+
|
|
778
|
+
if (code !== 0) console.error(`\n ⚠️ Agent exited with code ${code}`)
|
|
779
|
+
else console.log(`\n✓ ${rune.name} finished`)
|
|
780
|
+
process.exit(code || 0)
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
return
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Normal mode: print-only, no tool execution
|
|
714
787
|
const claudeArgs = ['-p', '--print']
|
|
715
788
|
if (systemPrompt) {
|
|
716
789
|
claudeArgs.push('--system-prompt', systemPrompt)
|
|
@@ -1133,6 +1206,7 @@ Usage:
|
|
|
1133
1206
|
--role "description" Set the agent's role
|
|
1134
1207
|
rune open <file.rune> Open a .rune file (desktop GUI)
|
|
1135
1208
|
rune run <file.rune> "prompt" Run agent headlessly (no GUI)
|
|
1209
|
+
--auto Auto mode: agent writes files, runs commands, fixes errors
|
|
1136
1210
|
--output json|text Output format (default: text)
|
|
1137
1211
|
rune pipe <a.rune> <b.rune> ... "prompt" Chain agents in a pipeline
|
|
1138
1212
|
--output json|text Output format (default: text)
|
package/package.json
CHANGED