harnex 0.2.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.
- checksums.yaml +7 -0
- data/GUIDE.md +242 -0
- data/LICENSE +21 -0
- data/README.md +119 -0
- data/TECHNICAL.md +595 -0
- data/bin/harnex +18 -0
- data/lib/harnex/adapters/base.rb +134 -0
- data/lib/harnex/adapters/claude.rb +105 -0
- data/lib/harnex/adapters/codex.rb +112 -0
- data/lib/harnex/adapters/generic.rb +14 -0
- data/lib/harnex/adapters.rb +32 -0
- data/lib/harnex/cli.rb +115 -0
- data/lib/harnex/commands/guide.rb +23 -0
- data/lib/harnex/commands/logs.rb +184 -0
- data/lib/harnex/commands/pane.rb +251 -0
- data/lib/harnex/commands/recipes.rb +104 -0
- data/lib/harnex/commands/run.rb +384 -0
- data/lib/harnex/commands/send.rb +415 -0
- data/lib/harnex/commands/skills.rb +163 -0
- data/lib/harnex/commands/status.rb +171 -0
- data/lib/harnex/commands/stop.rb +127 -0
- data/lib/harnex/commands/wait.rb +165 -0
- data/lib/harnex/core.rb +286 -0
- data/lib/harnex/runtime/api_server.rb +187 -0
- data/lib/harnex/runtime/file_change_hook.rb +111 -0
- data/lib/harnex/runtime/inbox.rb +207 -0
- data/lib/harnex/runtime/message.rb +23 -0
- data/lib/harnex/runtime/session.rb +380 -0
- data/lib/harnex/runtime/session_state.rb +55 -0
- data/lib/harnex/version.rb +3 -0
- data/lib/harnex/watcher/inotify.rb +43 -0
- data/lib/harnex/watcher/polling.rb +92 -0
- data/lib/harnex/watcher.rb +24 -0
- data/lib/harnex.rb +25 -0
- data/recipes/01_fire_and_watch.md +82 -0
- data/recipes/02_chain_implement.md +115 -0
- data/skills/chain-implement/SKILL.md +234 -0
- data/skills/close/SKILL.md +47 -0
- data/skills/dispatch/SKILL.md +171 -0
- data/skills/harnex/SKILL.md +304 -0
- data/skills/open/SKILL.md +32 -0
- metadata +88 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dispatch
|
|
3
|
+
description: Fire & Watch — the standard pattern for launching and monitoring harnex agent sessions. Use when dispatching implementation, review, or fix agents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dispatch — Fire & Watch
|
|
7
|
+
|
|
8
|
+
Every harnex agent dispatch follows three phases: **spawn**, **watch**, **stop**.
|
|
9
|
+
|
|
10
|
+
## 1. Spawn
|
|
11
|
+
|
|
12
|
+
Launch the agent in a tmux window so the user can observe it live:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
harnex run codex --id cx-impl-NN --tmux cx-impl-NN \
|
|
16
|
+
--context "Implement koder/plans/NN_name.md. Run tests when done. Commit after each phase."
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
For reviews (Claude):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
harnex run claude --id cl-rev-NN --tmux cl-rev-NN \
|
|
23
|
+
--context "Review the implementation of plan NN against the spec in koder/plans/NN_name.md. Write findings to koder/reviews/NN_name.md"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For complex task prompts, write to a temp file and reference it:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cat > /tmp/task-impl-NN.md <<'EOF'
|
|
30
|
+
Detailed instructions here...
|
|
31
|
+
EOF
|
|
32
|
+
|
|
33
|
+
harnex run codex --id cx-impl-NN --tmux cx-impl-NN \
|
|
34
|
+
--context "Read and execute /tmp/task-impl-NN.md"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 2. Watch
|
|
38
|
+
|
|
39
|
+
Poll the agent's screen with `harnex pane`. Checking is cheap — a 20-line
|
|
40
|
+
tail is a few hundred bytes.
|
|
41
|
+
|
|
42
|
+
**Default: poll every 30 seconds.** This is fine for most work. The check
|
|
43
|
+
itself costs almost nothing and catches completion quickly.
|
|
44
|
+
|
|
45
|
+
**Progressive intervals** when you expect longer work:
|
|
46
|
+
|
|
47
|
+
| Elapsed | Interval | Rationale |
|
|
48
|
+
|---------|----------|-----------|
|
|
49
|
+
| 0–2 min | 30s | Catch fast completions and early errors |
|
|
50
|
+
| 2–10 min | 60s | Steady state for typical implementations |
|
|
51
|
+
| 10+ min | 120s | Long-running work, reduce noise |
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Quick check — last 20 lines is enough to see if done or stuck
|
|
55
|
+
harnex pane --id cx-impl-NN --lines 20
|
|
56
|
+
|
|
57
|
+
# JSON metadata (includes capture timestamp)
|
|
58
|
+
harnex pane --id cx-impl-NN --lines 20 --json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When checking, look for:
|
|
62
|
+
- **At prompt** → agent finished, read last output for results
|
|
63
|
+
- **Still working** → agent is reading files, running tests, editing code
|
|
64
|
+
- **Error/stuck** → agent hit a blocker, may need intervention
|
|
65
|
+
- **Permission prompt** → agent waiting for user approval, intervene
|
|
66
|
+
|
|
67
|
+
### Background poll from Claude Code
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Run as a background task, check result when notified
|
|
71
|
+
harnex pane --id cx-impl-NN --lines 20
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or use `--follow` for continuous monitoring:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
harnex pane --id cx-impl-NN --lines 20 --follow
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 3. Stop
|
|
81
|
+
|
|
82
|
+
When the agent is done (at prompt, work committed):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
harnex stop --id cx-impl-NN
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Always verify the agent's work landed before stopping:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Quick sanity check
|
|
92
|
+
harnex pane --id cx-impl-NN --lines 20
|
|
93
|
+
# Confirm commits exist
|
|
94
|
+
git log --oneline -5
|
|
95
|
+
# Then stop
|
|
96
|
+
harnex stop --id cx-impl-NN
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Naming Conventions
|
|
100
|
+
|
|
101
|
+
| Step | ID pattern | tmux window | Example |
|
|
102
|
+
|------|-----------|-------------|---------|
|
|
103
|
+
| Implement | `cx-impl-NN` | `cx-impl-NN` | `cx-impl-42` |
|
|
104
|
+
| Review | `cl-rev-NN` | `cl-rev-NN` | `cl-rev-42` |
|
|
105
|
+
| Fix | `cx-fix-NN` | `cx-fix-NN` | `cx-fix-42` |
|
|
106
|
+
| Plan write | `cx-plan-NN` | `cx-plan-NN` | `cx-plan-42` |
|
|
107
|
+
| Plan fix | `cx-fix-plan-NN` | `cx-fix-plan-NN` | `cx-fix-plan-42` |
|
|
108
|
+
|
|
109
|
+
**Rule**: Always use `--tmux <same-as-id>` so the tmux window name matches
|
|
110
|
+
the session ID. Never use a different tmux name.
|
|
111
|
+
|
|
112
|
+
## Full Dispatch Lifecycle
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
1. Mark plan IN_PROGRESS, commit
|
|
116
|
+
2. harnex run codex --id cx-impl-NN --tmux cx-impl-NN
|
|
117
|
+
3. Poll with harnex pane --lines 20 every 30s
|
|
118
|
+
4. When done: verify commits, harnex stop
|
|
119
|
+
5. harnex run claude --id cl-rev-NN --tmux cl-rev-NN (review)
|
|
120
|
+
6. Poll with harnex pane --lines 20 every 30s
|
|
121
|
+
7. When done: harnex stop, read review
|
|
122
|
+
8. If NEEDS FIXES: harnex run codex --id cx-fix-NN (fix pass)
|
|
123
|
+
9. If PASS: done
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Worktree Option
|
|
127
|
+
|
|
128
|
+
Use worktrees only when you need **parallel isolation** — e.g., implementing
|
|
129
|
+
one plan while another is being reviewed, or when the user explicitly asks.
|
|
130
|
+
Do not default to worktrees for serial work.
|
|
131
|
+
|
|
132
|
+
### Worktree Setup
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Commit all files the agent will need BEFORE creating the worktree
|
|
136
|
+
# (untracked files don't carry over)
|
|
137
|
+
git add koder/plans/NN_name.md
|
|
138
|
+
git commit -m "docs(plan-NN): add plan"
|
|
139
|
+
|
|
140
|
+
# Create worktree
|
|
141
|
+
WORKTREE="$(pwd)/../$(basename $(pwd))-plan-NN"
|
|
142
|
+
git worktree add ${WORKTREE} -b plan/NN_name master
|
|
143
|
+
|
|
144
|
+
# Launch from worktree
|
|
145
|
+
cd ${WORKTREE}
|
|
146
|
+
harnex run codex --id cx-impl-NN --tmux cx-impl-NN \
|
|
147
|
+
--context "Implement koder/plans/NN_name.md. Run tests when done."
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Worktree Caveats
|
|
151
|
+
|
|
152
|
+
- **cd first**: launch and manage sessions from the worktree directory
|
|
153
|
+
- **Merge conflicts**: `koder/` state files may diverge — on merge, keep
|
|
154
|
+
master's versions of session-state files
|
|
155
|
+
- **Cleanup**: `git worktree remove <path>` then `git branch -d plan/<branch>`
|
|
156
|
+
|
|
157
|
+
## Checking Status
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
harnex status # current repo sessions
|
|
161
|
+
harnex status --all # all repos
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## What NOT to Do
|
|
165
|
+
|
|
166
|
+
- **Never** launch agents with raw `tmux send-keys` or `tmux new-window`
|
|
167
|
+
- **Never** use `--tmux NAME` where NAME differs from `--id`
|
|
168
|
+
- **Never** pass `-- --cd <path>` to Claude sessions (unsupported flag)
|
|
169
|
+
- **Never** poll with raw `tmux capture-pane` — use `harnex pane`
|
|
170
|
+
- **Never** rely on `--wait-for-idle` alone — always use Fire & Watch
|
|
171
|
+
- **Never** use `c-zai-dangerous` or direct CLI spawning outside harnex
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harnex
|
|
3
|
+
description: Collaborate with other AI agents (Codex, Claude) via harnex. Use when the user asks to send a message to another agent, check agent sessions, spawn workers, relay instructions, or coordinate multi-agent work. Also activates when incoming messages contain "[harnex relay" headers.
|
|
4
|
+
allowed-tools: Bash(harnex *)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Harnex — Cross-Agent Collaboration
|
|
8
|
+
|
|
9
|
+
If this is your first time using harnex, run `harnex guide` for the full
|
|
10
|
+
getting started walkthrough, and `harnex recipes` for tested workflow patterns.
|
|
11
|
+
|
|
12
|
+
Harnex wraps interactive terminal agents (Claude Code, Codex) and opens a local
|
|
13
|
+
control plane so they can discover and message each other. You use it to **send
|
|
14
|
+
messages to a peer agent**, **check session status**, **spawn worker sessions**,
|
|
15
|
+
and **wait for them to finish**.
|
|
16
|
+
|
|
17
|
+
## Detect your context
|
|
18
|
+
|
|
19
|
+
Check environment variables to understand your role:
|
|
20
|
+
|
|
21
|
+
| Variable | Meaning |
|
|
22
|
+
|----------|---------|
|
|
23
|
+
| `HARNEX_SESSION_CLI` | Which CLI you are (`claude` or `codex`) |
|
|
24
|
+
| `HARNEX_ID` | Your session ID |
|
|
25
|
+
| `HARNEX_SESSION_REPO_ROOT` | Repo root this session is scoped to |
|
|
26
|
+
| `HARNEX_SESSION_ID` | Internal instance identifier |
|
|
27
|
+
|
|
28
|
+
If these are set, you are **inside a harnex session** and can send messages to
|
|
29
|
+
peer sessions or spawn new worker sessions.
|
|
30
|
+
|
|
31
|
+
## Mode preference
|
|
32
|
+
|
|
33
|
+
When starting another agent session for the user, default to a visible tmux
|
|
34
|
+
session via `harnex run <cli> --tmux`. That is the preferred interactive mode
|
|
35
|
+
because the user can watch the peer's work live.
|
|
36
|
+
|
|
37
|
+
Use other modes only when the user asks for them or when visibility is not
|
|
38
|
+
wanted:
|
|
39
|
+
|
|
40
|
+
- prefer `--tmux` over a hidden foreground PTY for peer-agent work
|
|
41
|
+
- use plain foreground `harnex run` only when the current terminal is meant to
|
|
42
|
+
become that peer's UI
|
|
43
|
+
- use `--detach` only for explicitly headless/background workflows
|
|
44
|
+
|
|
45
|
+
## Return channel first
|
|
46
|
+
|
|
47
|
+
Before you start a peer session or send it work, decide how the result will get
|
|
48
|
+
back to you.
|
|
49
|
+
|
|
50
|
+
Preferred pattern when you are inside harnex:
|
|
51
|
+
- Use your own `HARNEX_ID` as the return address
|
|
52
|
+
- Tell the peer to send its final result back with `harnex send --id <YOUR_ID>`
|
|
53
|
+
- Wait for the peer's reply; do not rely on scraping logs or tmux panes as the
|
|
54
|
+
primary way to collect the answer
|
|
55
|
+
|
|
56
|
+
Fallback when you are not inside harnex:
|
|
57
|
+
- Define another explicit return channel before delegating, such as a known file
|
|
58
|
+
path in the repo
|
|
59
|
+
|
|
60
|
+
Do not launch a worker/reviewer without an explicit completion contract.
|
|
61
|
+
|
|
62
|
+
## Two rules for every send
|
|
63
|
+
|
|
64
|
+
**1. Keep messages short — use file references for long prompts.**
|
|
65
|
+
Long inline prompts can stall delivery (PTY buffer limits) and break shell
|
|
66
|
+
quoting. Instead, write the full task to a file and tell the peer to read it:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Write the task to a file
|
|
70
|
+
cat > /tmp/task-impl1.md <<'EOF'
|
|
71
|
+
Implement phase 2 from koder/plans/03_output_streaming.md.
|
|
72
|
+
... detailed instructions ...
|
|
73
|
+
EOF
|
|
74
|
+
|
|
75
|
+
# Send a short message pointing to it
|
|
76
|
+
harnex send --id impl-1 --message "Read and execute /tmp/task-impl1.md. When done, send results back: harnex send --id $HARNEX_ID --message '<summary>'"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If the task is already written down (a plan file, issue, koder doc), just
|
|
80
|
+
reference it directly — no need for a temp file.
|
|
81
|
+
|
|
82
|
+
**2. Always tell the peer how to reply.**
|
|
83
|
+
Every delegated task must include a return path. Without it, the peer finishes
|
|
84
|
+
silently and you have no way to collect the result:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Always end with the reply instruction
|
|
88
|
+
harnex send --id impl-1 --message "Review src/auth.rb. When done: harnex send --id $HARNEX_ID --message '<your findings>'"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Core commands
|
|
92
|
+
|
|
93
|
+
### Send a message to a peer agent
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
harnex send --id <ID> --message "<text>"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `--id` targets a specific session by its unique ID
|
|
100
|
+
- `--message` is the prompt text injected into the peer's terminal
|
|
101
|
+
- Message is auto-submitted (peer receives it as a prompt)
|
|
102
|
+
- `--no-submit` types without pressing Enter
|
|
103
|
+
- `--force` sends even if peer UI is not at a prompt (bypasses queue)
|
|
104
|
+
- `--submit-only` sends only Enter (submit what's already in the input box)
|
|
105
|
+
- `--wait-for-idle` blocks until the agent finishes processing (prompt→busy→prompt)
|
|
106
|
+
- `--no-wait` returns immediately with a message_id (don't wait for delivery)
|
|
107
|
+
- `--cli` filters by CLI type when multiple sessions share resolution scope
|
|
108
|
+
|
|
109
|
+
When the target agent is busy, the message is **queued** (HTTP 202) and
|
|
110
|
+
delivered automatically when the agent returns to a prompt. The sender polls
|
|
111
|
+
until delivery completes using one overall `--timeout` budget (default 120s).
|
|
112
|
+
|
|
113
|
+
### Atomic send+wait (recommended for orchestration)
|
|
114
|
+
|
|
115
|
+
Use `--wait-for-idle` instead of separate `send` + `sleep` + `wait` commands:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Instead of:
|
|
119
|
+
harnex send --id cx-1 --message "implement the plan"
|
|
120
|
+
sleep 5
|
|
121
|
+
harnex wait --id cx-1 --until prompt --timeout 600
|
|
122
|
+
|
|
123
|
+
# Use:
|
|
124
|
+
harnex send --id cx-1 --message "implement the plan" --wait-for-idle --timeout 600
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This eliminates the race condition where `wait --until prompt` sees the stale
|
|
128
|
+
prompt state before the agent starts working. The `--timeout` budget covers
|
|
129
|
+
the entire lifecycle (lookup + send + idle wait).
|
|
130
|
+
|
|
131
|
+
**Multi-line messages** (when a file reference isn't practical): use a heredoc:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
harnex send --id worker-1 --message "$(cat <<'EOF'
|
|
135
|
+
Line one of the message.
|
|
136
|
+
Line two of the message.
|
|
137
|
+
EOF
|
|
138
|
+
)"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Check session status
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
harnex status # sessions for current repo
|
|
145
|
+
harnex status --all # sessions across all repos
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Shows live sessions with their ID, CLI, port, PID, age, and input state.
|
|
149
|
+
|
|
150
|
+
### Inspect a specific session
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
harnex status --id <ID> --json
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Returns JSON with input state, agent state, inbox stats, description,
|
|
157
|
+
watch config, and timestamps.
|
|
158
|
+
|
|
159
|
+
### Only when explicitly requested: spawn a detached worker session
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Headless (no terminal)
|
|
163
|
+
harnex run codex --id impl-1 --detach -- --cd /path/to/worktree
|
|
164
|
+
|
|
165
|
+
# In a tmux window (observable)
|
|
166
|
+
harnex run codex --id impl-1 --tmux cx-p1 -- --cd /path/to/worktree
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- `--detach` starts the session in the background, returns JSON with pid/port
|
|
170
|
+
- `--tmux` creates a tmux window (implies `--detach`)
|
|
171
|
+
- `--tmux NAME` sets a custom window title (keep names terse: `cx-p3`, `cl-r3`)
|
|
172
|
+
- `--context TEXT` sets an initial prompt with session ID auto-included
|
|
173
|
+
- `--description TEXT` stores a short session description in the registry/API
|
|
174
|
+
- Returns immediately; use `harnex send` to inject work, `harnex wait` to block
|
|
175
|
+
|
|
176
|
+
Do this only if the user explicitly asks for detached/background execution.
|
|
177
|
+
|
|
178
|
+
#### Using `--context` to orient spawned agents
|
|
179
|
+
|
|
180
|
+
`--context` prepends a context string as the agent's initial prompt, with the
|
|
181
|
+
session ID automatically included as `[harnex session id=<ID>]`. The spawner
|
|
182
|
+
decides what context to provide — harnex only adds the session ID.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Fire-and-forget: give the task upfront
|
|
186
|
+
harnex run codex --id impl-1 --tmux cx-p1 \
|
|
187
|
+
--context "Implement the feature in koder/plans/03_auth.md. Commit when done." \
|
|
188
|
+
-- --cd /path/to/worktree
|
|
189
|
+
|
|
190
|
+
# Fire-and-wait: give context, then send work separately
|
|
191
|
+
harnex run codex --id reviewer --tmux cx-rv \
|
|
192
|
+
--context "You are a code reviewer. Wait for instructions via harnex relay messages." \
|
|
193
|
+
-- --cd /path/to/repo
|
|
194
|
+
harnex send --id reviewer --message "Review the changes in src/auth.rb"
|
|
195
|
+
harnex wait --id reviewer
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The context string is the spawner's responsibility — tailor it to the use case.
|
|
199
|
+
|
|
200
|
+
### Wait for a session to exit
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
harnex wait --id impl-1
|
|
204
|
+
harnex wait --id impl-1 --timeout 300
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Blocks until the session process exits. Returns JSON with exit code and timing.
|
|
208
|
+
Exit code 124 on timeout.
|
|
209
|
+
|
|
210
|
+
## Relay headers
|
|
211
|
+
|
|
212
|
+
When you send from inside a harnex session to a **different** session, harnex
|
|
213
|
+
automatically prepends a relay header:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
[harnex relay from=claude id=supervisor at=2026-03-14T12:00:00+04:00]
|
|
217
|
+
<your message>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The peer sees this header and knows the message came from another agent. When
|
|
221
|
+
you **receive** a message with a `[harnex relay ...]` header, treat it as a
|
|
222
|
+
prompt from the peer agent — read the body and respond to it.
|
|
223
|
+
|
|
224
|
+
Control relay behavior:
|
|
225
|
+
- `--relay` forces the header even outside a session
|
|
226
|
+
- `--no-relay` suppresses the header
|
|
227
|
+
|
|
228
|
+
## Collaboration patterns
|
|
229
|
+
|
|
230
|
+
### Reply to a peer
|
|
231
|
+
|
|
232
|
+
When the user (or a relay message) asks you to reply to the other agent:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
harnex send --id <TARGET_ID> --message "Your response here"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Delegate work and get the answer back
|
|
239
|
+
|
|
240
|
+
When you ask a peer agent to do work, include the return path in the task
|
|
241
|
+
itself.
|
|
242
|
+
|
|
243
|
+
Preferred when you are inside harnex:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
harnex send --id reviewer --message "$(cat <<EOF
|
|
247
|
+
Review the current working tree.
|
|
248
|
+
|
|
249
|
+
Return your final findings to me with:
|
|
250
|
+
harnex send --id $HARNEX_ID --message '<findings>'
|
|
251
|
+
|
|
252
|
+
Use findings-first format with file paths and line numbers where possible.
|
|
253
|
+
EOF
|
|
254
|
+
)"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Then wait for the peer to answer you. Do not assume you can reconstruct the
|
|
258
|
+
result later from detached logs or tmux capture.
|
|
259
|
+
|
|
260
|
+
### Supervisor pattern
|
|
261
|
+
|
|
262
|
+
Use this only when the user explicitly wants detached/background workers.
|
|
263
|
+
|
|
264
|
+
A supervisor session spawns workers, sends them tasks, and waits for completion:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Spawn workers
|
|
268
|
+
harnex run codex --id impl-1 --tmux cx-p1 -- --cd ~/repo/wt-feature-a
|
|
269
|
+
harnex run codex --id impl-2 --tmux cx-p2 -- --cd ~/repo/wt-feature-b
|
|
270
|
+
|
|
271
|
+
# Send work and wait for completion (atomic)
|
|
272
|
+
harnex send --id impl-1 --message "implement plan 150" --wait-for-idle --timeout 600
|
|
273
|
+
harnex send --id impl-2 --message "implement plan 151" --wait-for-idle --timeout 600
|
|
274
|
+
|
|
275
|
+
# Review phase
|
|
276
|
+
harnex run claude --id review-1 --tmux cl-r1
|
|
277
|
+
harnex send --id review-1 --message "review changes in wt-feature-a"
|
|
278
|
+
harnex wait --id review-1
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### File watch hook
|
|
282
|
+
|
|
283
|
+
Sessions can watch a shared file (e.g. `--watch ./tmp/tick.jsonl`). When the
|
|
284
|
+
file changes, harnex injects a `file-change-hook: read <path>` message. If you
|
|
285
|
+
receive this hook, read the file and act on its contents.
|
|
286
|
+
|
|
287
|
+
## Important rules
|
|
288
|
+
|
|
289
|
+
1. **Always confirm with the user before sending** unless they explicitly asked
|
|
290
|
+
you to send a specific message. Sending injects a prompt into the peer's
|
|
291
|
+
terminal — it's an action visible to others.
|
|
292
|
+
2. **Never auto-loop** relay conversations. One send per user request unless
|
|
293
|
+
told otherwise.
|
|
294
|
+
3. **Check status first** if unsure whether a peer is running: `harnex status`
|
|
295
|
+
4. **Use `--force` sparingly** — it bypasses the inbox queue and adapter
|
|
296
|
+
readiness checks. Can corrupt peer input if it's mid-response.
|
|
297
|
+
5. **Relay headers are automatic** when sending from inside a session. Don't
|
|
298
|
+
manually prepend them.
|
|
299
|
+
6. When composing a message to send, be concise and actionable — the peer agent
|
|
300
|
+
receives it as a prompt and will act on it.
|
|
301
|
+
7. Do not spawn detached or tmux-backed sessions unless the user explicitly
|
|
302
|
+
asked for detached/background execution.
|
|
303
|
+
8. Before delegating work, define the result return path. Prefer a reply back to
|
|
304
|
+
your own `HARNEX_ID` over logs, pane capture, or other indirect collection.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: open
|
|
3
|
+
description: Open a work session in this repo — read koder/STATE.md first, inspect the current worktree, align on the active issue or plan, and establish the starting point before editing. Use when the user says "open session", "start work", "initialize", "orient yourself", or invokes "/open".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Open Session Workflow
|
|
7
|
+
|
|
8
|
+
When the user asks to initialize or open the session, run this sequence:
|
|
9
|
+
|
|
10
|
+
## 1. Read the handoff
|
|
11
|
+
|
|
12
|
+
- Read `koder/STATE.md` first
|
|
13
|
+
- Note the `Current snapshot`, open issues and plans, and `Next step`
|
|
14
|
+
- Open only the issue or plan files relevant to the current task
|
|
15
|
+
|
|
16
|
+
## 2. Inspect the repo state
|
|
17
|
+
|
|
18
|
+
- Run `git status --short`
|
|
19
|
+
- Notice modified or untracked files before editing
|
|
20
|
+
- Do not revert unrelated changes you did not make
|
|
21
|
+
|
|
22
|
+
## 3. Establish the starting point
|
|
23
|
+
|
|
24
|
+
- Summarize the important context for this session: relevant issue or plan, repo state, and the immediate next step
|
|
25
|
+
- If the user already asked for implementation, continue into the work instead of stopping at orientation
|
|
26
|
+
- Update `koder/STATE.md` during open only if it is clearly stale enough to mislead the session
|
|
27
|
+
|
|
28
|
+
## Notes
|
|
29
|
+
|
|
30
|
+
- Treat `koder/STATE.md` as the handoff document between sessions
|
|
31
|
+
- Prefer updating existing issue or plan docs over creating new tracking files
|
|
32
|
+
- Do NOT create issue docs unless the user explicitly asks
|
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: harnex
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jikku Jose
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-03-31 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: A local PTY harness that wraps terminal AI agents (Claude, Codex) and
|
|
14
|
+
adds a control plane for discovery, messaging, and coordination.
|
|
15
|
+
email:
|
|
16
|
+
- jikkujose@gmail.com
|
|
17
|
+
executables:
|
|
18
|
+
- harnex
|
|
19
|
+
extensions: []
|
|
20
|
+
extra_rdoc_files: []
|
|
21
|
+
files:
|
|
22
|
+
- GUIDE.md
|
|
23
|
+
- LICENSE
|
|
24
|
+
- README.md
|
|
25
|
+
- TECHNICAL.md
|
|
26
|
+
- bin/harnex
|
|
27
|
+
- lib/harnex.rb
|
|
28
|
+
- lib/harnex/adapters.rb
|
|
29
|
+
- lib/harnex/adapters/base.rb
|
|
30
|
+
- lib/harnex/adapters/claude.rb
|
|
31
|
+
- lib/harnex/adapters/codex.rb
|
|
32
|
+
- lib/harnex/adapters/generic.rb
|
|
33
|
+
- lib/harnex/cli.rb
|
|
34
|
+
- lib/harnex/commands/guide.rb
|
|
35
|
+
- lib/harnex/commands/logs.rb
|
|
36
|
+
- lib/harnex/commands/pane.rb
|
|
37
|
+
- lib/harnex/commands/recipes.rb
|
|
38
|
+
- lib/harnex/commands/run.rb
|
|
39
|
+
- lib/harnex/commands/send.rb
|
|
40
|
+
- lib/harnex/commands/skills.rb
|
|
41
|
+
- lib/harnex/commands/status.rb
|
|
42
|
+
- lib/harnex/commands/stop.rb
|
|
43
|
+
- lib/harnex/commands/wait.rb
|
|
44
|
+
- lib/harnex/core.rb
|
|
45
|
+
- lib/harnex/runtime/api_server.rb
|
|
46
|
+
- lib/harnex/runtime/file_change_hook.rb
|
|
47
|
+
- lib/harnex/runtime/inbox.rb
|
|
48
|
+
- lib/harnex/runtime/message.rb
|
|
49
|
+
- lib/harnex/runtime/session.rb
|
|
50
|
+
- lib/harnex/runtime/session_state.rb
|
|
51
|
+
- lib/harnex/version.rb
|
|
52
|
+
- lib/harnex/watcher.rb
|
|
53
|
+
- lib/harnex/watcher/inotify.rb
|
|
54
|
+
- lib/harnex/watcher/polling.rb
|
|
55
|
+
- recipes/01_fire_and_watch.md
|
|
56
|
+
- recipes/02_chain_implement.md
|
|
57
|
+
- skills/chain-implement/SKILL.md
|
|
58
|
+
- skills/close/SKILL.md
|
|
59
|
+
- skills/dispatch/SKILL.md
|
|
60
|
+
- skills/harnex/SKILL.md
|
|
61
|
+
- skills/open/SKILL.md
|
|
62
|
+
homepage: https://github.com/jikkujose/harnex
|
|
63
|
+
licenses:
|
|
64
|
+
- MIT
|
|
65
|
+
metadata:
|
|
66
|
+
homepage_uri: https://github.com/jikkujose/harnex
|
|
67
|
+
source_code_uri: https://github.com/jikkujose/harnex
|
|
68
|
+
bug_tracker_uri: https://github.com/jikkujose/harnex/issues
|
|
69
|
+
post_install_message:
|
|
70
|
+
rdoc_options: []
|
|
71
|
+
require_paths:
|
|
72
|
+
- lib
|
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '3.0'
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
requirements: []
|
|
84
|
+
rubygems_version: 3.5.3
|
|
85
|
+
signing_key:
|
|
86
|
+
specification_version: 4
|
|
87
|
+
summary: PTY harness for terminal AI agents
|
|
88
|
+
test_files: []
|