harnex 0.6.0 → 0.6.2
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 +4 -4
- data/CHANGELOG.md +115 -0
- data/GUIDE.md +11 -11
- data/README.md +22 -16
- data/TECHNICAL.md +25 -59
- data/guides/01_dispatch.md +139 -0
- data/guides/02_chain.md +113 -0
- data/guides/03_buddy.md +94 -0
- data/guides/04_monitoring.md +130 -0
- data/guides/05_naming.md +106 -0
- data/lib/harnex/adapters/codex_appserver.rb +26 -5
- data/lib/harnex/cli.rb +13 -6
- data/lib/harnex/commands/agents_guide.rb +109 -0
- data/lib/harnex/commands/doctor.rb +8 -0
- data/lib/harnex/commands/events.rb +10 -0
- data/lib/harnex/commands/guide.rb +9 -0
- data/lib/harnex/commands/logs.rb +10 -0
- data/lib/harnex/commands/pane.rb +10 -0
- data/lib/harnex/commands/recipes.rb +9 -0
- data/lib/harnex/commands/run.rb +11 -0
- data/lib/harnex/commands/send.rb +13 -1
- data/lib/harnex/commands/status.rb +10 -0
- data/lib/harnex/commands/stop.rb +10 -0
- data/lib/harnex/commands/wait.rb +10 -0
- data/lib/harnex/runtime/session.rb +33 -7
- data/lib/harnex/runtime/session_state.rb +7 -0
- data/lib/harnex/version.rb +1 -1
- data/lib/harnex.rb +1 -1
- metadata +7 -8
- data/lib/harnex/commands/skills.rb +0 -226
- data/skills/close/SKILL.md +0 -47
- data/skills/harnex/SKILL.md +0 -20
- data/skills/harnex-buddy/SKILL.md +0 -104
- data/skills/harnex-chain/SKILL.md +0 -132
- data/skills/harnex-dispatch/SKILL.md +0 -294
- data/skills/open/SKILL.md +0 -32
data/guides/03_buddy.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Buddy Monitoring
|
|
2
|
+
|
|
3
|
+
A buddy is a second harnex session that watches one or more workers and nudges
|
|
4
|
+
them if they stall. Use a buddy when the work is long-running, unattended, or
|
|
5
|
+
needs interpretation that simple stall policy cannot provide.
|
|
6
|
+
|
|
7
|
+
For simple inactivity recovery, prefer built-in watch mode:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
harnex run codex --id cx-i-NN --watch --preset impl --context "Read /tmp/task-impl-NN.md"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Use a buddy when you need reasoning over pane contents, semantic checks, or
|
|
14
|
+
multi-session correlation.
|
|
15
|
+
|
|
16
|
+
## When To Use
|
|
17
|
+
|
|
18
|
+
Use a buddy for:
|
|
19
|
+
|
|
20
|
+
- Overnight or multi-hour work.
|
|
21
|
+
- Any dispatched task expected to run more than about 30 minutes unattended.
|
|
22
|
+
- Work where a stalled prompt, permission request, or disconnect would waste a
|
|
23
|
+
long slot.
|
|
24
|
+
- Monitoring multiple signals before deciding whether to nudge.
|
|
25
|
+
|
|
26
|
+
## Spawn
|
|
27
|
+
|
|
28
|
+
Spawn the worker first, then spawn the buddy:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
harnex run codex --id cx-i-42 --tmux cx-i-42 \
|
|
32
|
+
--context "Read and execute /tmp/task-impl-42.md"
|
|
33
|
+
|
|
34
|
+
harnex run claude --id buddy-42 --tmux buddy-42
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The buddy is just another harnex session. Inspect it, stop it, and read its
|
|
38
|
+
logs with the same commands as any worker.
|
|
39
|
+
|
|
40
|
+
## Buddy Prompt
|
|
41
|
+
|
|
42
|
+
Give the buddy an explicit polling loop, stall threshold, nudge rule, return
|
|
43
|
+
channel, and cleanup rule:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
You are an accountability partner for harnex session `cx-i-42`.
|
|
47
|
+
|
|
48
|
+
Every 5 minutes:
|
|
49
|
+
- Run `harnex pane --id cx-i-42 --lines 30`.
|
|
50
|
+
- Run `harnex status --id cx-i-42 --json`.
|
|
51
|
+
|
|
52
|
+
If the worker appears stuck at a prompt or permission dialog for more than
|
|
53
|
+
10 minutes with no progress, nudge it:
|
|
54
|
+
- `harnex send --id cx-i-42 --message "You appear to have stalled. Continue with your current task."`
|
|
55
|
+
|
|
56
|
+
If the worker exits or writes `/tmp/cx-i-42-done.txt`, report back:
|
|
57
|
+
- `tmux send-keys -t "$HARNEX_SPAWNER_PANE" "cx-i-42 finished. Check /tmp/cx-i-42-done.txt." Enter`
|
|
58
|
+
|
|
59
|
+
Do not interfere with active work. Stop yourself after reporting completion.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Send it:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
harnex send --id buddy-42 --message "Read and execute /tmp/buddy-42.md"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Return Channel
|
|
69
|
+
|
|
70
|
+
Every harnex-spawned session receives `HARNEX_SPAWNER_PANE` when the invoker is
|
|
71
|
+
inside tmux. The buddy can use it to report to an invoker that is not itself a
|
|
72
|
+
harnex session:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
tmux capture-pane -t "$HARNEX_SPAWNER_PANE" -p
|
|
76
|
+
tmux send-keys -t "$HARNEX_SPAWNER_PANE" "cx-i-42 finished" Enter
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If no tmux return pane is available, require the buddy to write a file and tell
|
|
80
|
+
the invoker where to read it.
|
|
81
|
+
|
|
82
|
+
## Cleanup
|
|
83
|
+
|
|
84
|
+
Stop the buddy after the worker completes:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
harnex stop --id buddy-42
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For full recipe form, use:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
harnex recipes show 03
|
|
94
|
+
```
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Monitoring Patterns
|
|
2
|
+
|
|
3
|
+
Monitoring should be based on work-level signals first and UI state second.
|
|
4
|
+
Pane state is useful for interpretation, but it should not be the only proof
|
|
5
|
+
that delegated work is finished.
|
|
6
|
+
|
|
7
|
+
## Signal Ladder
|
|
8
|
+
|
|
9
|
+
Prefer signals in this order:
|
|
10
|
+
|
|
11
|
+
| Signal | Use |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Expected artifact | Primary proof that a task produced its deliverable |
|
|
14
|
+
| Tests and git state | Confirms work landed and the tree is not mid-edit |
|
|
15
|
+
| `harnex events` | Structured runtime events, including task completion |
|
|
16
|
+
| `harnex logs` | Transcript history and last output |
|
|
17
|
+
| `harnex pane` | Live UI interpretation and prompt/error diagnosis |
|
|
18
|
+
| `harnex status` | Session liveness and coarse state |
|
|
19
|
+
|
|
20
|
+
For Codex app-server sessions, `harnex wait --until task_complete` is a strong
|
|
21
|
+
turn-level fence. It still does not know your acceptance criteria; verify the
|
|
22
|
+
expected artifact or tests afterward.
|
|
23
|
+
|
|
24
|
+
## Completion Test
|
|
25
|
+
|
|
26
|
+
For unattended work, declare done with a conjunction of work-level facts:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
test -f /tmp/cx-i-NN-done.txt &&
|
|
30
|
+
test -z "$(git status --short)" &&
|
|
31
|
+
test "$(git log -1 --format=%ct)" -lt "$(($(date +%s) - 600))"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Adjust the artifact path and commit-age window to the task. The point is to
|
|
35
|
+
avoid declaring done while a worker is between edits or between commits.
|
|
36
|
+
|
|
37
|
+
## Why Pane State Alone Is Not Enough
|
|
38
|
+
|
|
39
|
+
Avoid using `state=prompt` or a quiet pane as the only completion signal:
|
|
40
|
+
|
|
41
|
+
- A finished agent can sit at a prompt forever.
|
|
42
|
+
- Some CLIs stay in a session state while auto-fix or tool loops continue.
|
|
43
|
+
- Focus changes and UI redraws can reset idle timers.
|
|
44
|
+
- A prompt can also mean the agent is blocked, not done.
|
|
45
|
+
|
|
46
|
+
Use `harnex pane` to understand what happened after a stronger signal tells you
|
|
47
|
+
where to look.
|
|
48
|
+
|
|
49
|
+
## Polling Patterns
|
|
50
|
+
|
|
51
|
+
For active supervision:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
harnex pane --id cx-i-NN --lines 40
|
|
55
|
+
harnex events --id cx-i-NN --snapshot
|
|
56
|
+
harnex logs --id cx-i-NN --lines 80
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
For continuous viewing:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
harnex pane --id cx-i-NN --follow --interval 2
|
|
63
|
+
harnex logs --id cx-i-NN --follow
|
|
64
|
+
harnex events --id cx-i-NN
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For task completion:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
harnex wait --id cx-i-NN --until task_complete --timeout 900
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Background Sweeper
|
|
74
|
+
|
|
75
|
+
Consumers often run a small shell loop that checks the expected done marker,
|
|
76
|
+
tree state, and harnex liveness. Keep a hard wall-clock cap so an unattended
|
|
77
|
+
pipeline cannot wait forever:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
start=$(date +%s)
|
|
81
|
+
max_wait=5400
|
|
82
|
+
|
|
83
|
+
until test -f /tmp/cx-i-NN-done.txt; do
|
|
84
|
+
if test "$(($(date +%s) - start))" -gt "$max_wait"; then
|
|
85
|
+
echo "wall-clock cap hit for cx-i-NN" >&2
|
|
86
|
+
exit 2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
harnex status --id cx-i-NN --json
|
|
90
|
+
harnex pane --id cx-i-NN --lines 20
|
|
91
|
+
sleep 60
|
|
92
|
+
done
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Recommended caps:
|
|
96
|
+
|
|
97
|
+
| Work type | Cap |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| Small single dispatch | 30 minutes |
|
|
100
|
+
| Medium implementation | 90 minutes |
|
|
101
|
+
| Large unattended phase | 3 hours |
|
|
102
|
+
|
|
103
|
+
## Built-In Watch Mode
|
|
104
|
+
|
|
105
|
+
Use `harnex run --watch` when one foreground process should launch the worker
|
|
106
|
+
and apply bounded stall recovery:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
harnex run codex --id cx-i-NN --watch --preset impl \
|
|
110
|
+
--context "Read /tmp/task-impl-NN.md"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`--watch` exits with:
|
|
114
|
+
|
|
115
|
+
| Code | Meaning |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| `0` | Session exited |
|
|
118
|
+
| `1` | Operational error |
|
|
119
|
+
| `2` | Watcher escalated after bounded resumes |
|
|
120
|
+
|
|
121
|
+
Use a buddy instead when the monitoring decision needs language-level
|
|
122
|
+
interpretation.
|
|
123
|
+
|
|
124
|
+
## Anti-Patterns
|
|
125
|
+
|
|
126
|
+
- Polling `state=prompt` alone and calling it done.
|
|
127
|
+
- Letting an unattended loop run with no wall-clock cap.
|
|
128
|
+
- Reading raw tmux panes instead of `harnex pane`.
|
|
129
|
+
- Using `--wait-for-idle` as acceptance proof.
|
|
130
|
+
- Reusing a worker after a failure changes the task scope.
|
data/guides/05_naming.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Naming Conventions
|
|
2
|
+
|
|
3
|
+
Use predictable session IDs so humans, agents, tmux windows, logs, events, and
|
|
4
|
+
done markers all point at the same work.
|
|
5
|
+
|
|
6
|
+
## Session IDs
|
|
7
|
+
|
|
8
|
+
Format:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
<cli>-<phase>-<number>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Common prefixes:
|
|
15
|
+
|
|
16
|
+
| Prefix | Meaning |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `cx` | Codex worker |
|
|
19
|
+
| `cl` | Claude worker |
|
|
20
|
+
| `buddy` | Buddy monitor |
|
|
21
|
+
|
|
22
|
+
Common phases:
|
|
23
|
+
|
|
24
|
+
| Code | Phase |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `m` | Mapping or analysis |
|
|
27
|
+
| `p` | Plan writing |
|
|
28
|
+
| `r` | Plan review |
|
|
29
|
+
| `f` | Plan fix |
|
|
30
|
+
| `i` | Implementation |
|
|
31
|
+
| `cr` | Code review |
|
|
32
|
+
| `cf` | Code fix |
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
cx-m-42 Codex maps task 42
|
|
38
|
+
cx-p-42 Codex writes plan 42
|
|
39
|
+
cx-r-42 Codex reviews plan 42
|
|
40
|
+
cx-f-42 Codex fixes plan 42
|
|
41
|
+
cx-i-42 Codex implements plan 42
|
|
42
|
+
cx-cr-42 Codex reviews implementation 42
|
|
43
|
+
cx-cf-42 Codex fixes implementation 42
|
|
44
|
+
buddy-42 Buddy monitors task 42
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use names that fit your project. The important part is that the ID is stable,
|
|
48
|
+
short, and present in every artifact.
|
|
49
|
+
|
|
50
|
+
## Match `--id` And `--tmux`
|
|
51
|
+
|
|
52
|
+
Always pass both and keep them identical:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
harnex run codex --id cx-i-42 --tmux cx-i-42
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Avoid this:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
harnex run codex --tmux cx-i-42
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If `--id` is missing, harnex generates a random session ID. The tmux window may
|
|
65
|
+
look right, but `harnex status`, `harnex pane --id`, and logs need the random
|
|
66
|
+
ID.
|
|
67
|
+
|
|
68
|
+
## Retry Suffixes
|
|
69
|
+
|
|
70
|
+
If a session fails and you dispatch a fresh attempt, append a suffix:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
cx-i-42 first attempt
|
|
74
|
+
cx-i-42b second attempt
|
|
75
|
+
cx-i-42c third attempt
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Keep the old session's logs. They are useful for diagnosis.
|
|
79
|
+
|
|
80
|
+
## Task Files
|
|
81
|
+
|
|
82
|
+
Use human-readable file names for long instructions:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
/tmp/task-plan-42.md
|
|
86
|
+
/tmp/task-impl-42.md
|
|
87
|
+
/tmp/task-review-42.md
|
|
88
|
+
/tmp/task-fix-42.md
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The task file name does not need to duplicate the exact short phase code. It
|
|
92
|
+
should be easy to scan in `/tmp` and should include the same task number as the
|
|
93
|
+
session ID.
|
|
94
|
+
|
|
95
|
+
## Done Markers
|
|
96
|
+
|
|
97
|
+
Derive done markers from the session ID:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
/tmp/cx-p-42-done.txt
|
|
101
|
+
/tmp/cx-i-42-done.txt
|
|
102
|
+
/tmp/cx-cr-42-done.txt
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
When a brief asks for a completion marker, make it one line and include the
|
|
106
|
+
highest-signal result: tests passed, review clean, or the blocking issue.
|
|
@@ -34,10 +34,12 @@ module Harnex
|
|
|
34
34
|
|
|
35
35
|
EVENTS = %w[task_complete turn_started item_completed disconnected].freeze
|
|
36
36
|
|
|
37
|
-
attr_reader :thread_id, :current_turn_id, :last_completed_at
|
|
37
|
+
attr_reader :thread_id, :current_turn_id, :last_completed_at, :initial_prompt
|
|
38
38
|
|
|
39
39
|
def initialize(extra_args = [])
|
|
40
40
|
super("codex", extra_args)
|
|
41
|
+
@initial_prompt = extra_args.join(" ").strip
|
|
42
|
+
@initial_prompt = nil if @initial_prompt.empty?
|
|
41
43
|
@client = nil
|
|
42
44
|
@thread_id = nil
|
|
43
45
|
@current_turn_id = nil
|
|
@@ -55,6 +57,10 @@ module Harnex
|
|
|
55
57
|
["codex", "app-server"]
|
|
56
58
|
end
|
|
57
59
|
|
|
60
|
+
def build_command
|
|
61
|
+
base_command
|
|
62
|
+
end
|
|
63
|
+
|
|
58
64
|
def describe
|
|
59
65
|
{
|
|
60
66
|
transport: transport,
|
|
@@ -76,10 +82,19 @@ module Harnex
|
|
|
76
82
|
}
|
|
77
83
|
end
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
def build_send_payload(text:, submit:, enter_only:, screen_text:, force: false)
|
|
86
|
+
state = input_state(nil)
|
|
87
|
+
if !force && submit && !enter_only && state[:input_ready] != true
|
|
88
|
+
raise ArgumentError, blocked_message(state, enter_only: enter_only)
|
|
89
|
+
end
|
|
90
|
+
raise ArgumentError, "Codex app-server cannot stage input without submitting it" unless submit || enter_only
|
|
91
|
+
raise ArgumentError, "Codex app-server does not support submit-only input" if enter_only
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
dispatch: { prompt: text.to_s },
|
|
95
|
+
input_state: state,
|
|
96
|
+
force: force
|
|
97
|
+
}
|
|
83
98
|
end
|
|
84
99
|
|
|
85
100
|
# No-op: closing the subprocess is handled via #close.
|
|
@@ -221,6 +236,12 @@ module Harnex
|
|
|
221
236
|
[wait_thr.pid, stdin_io, stdout_io]
|
|
222
237
|
end
|
|
223
238
|
|
|
239
|
+
def blocked_message(state, enter_only:)
|
|
240
|
+
return super if enter_only
|
|
241
|
+
|
|
242
|
+
"Codex app-server is not at a prompt; wait and retry or use `harnex send --force` (state: #{state[:state]})"
|
|
243
|
+
end
|
|
244
|
+
|
|
224
245
|
# Minimal JSON-RPC 2.0 client. One JSON object per line.
|
|
225
246
|
# Responses keyed by id; everything else is a notification.
|
|
226
247
|
class JsonRpcClient
|
data/lib/harnex/cli.rb
CHANGED
|
@@ -29,8 +29,8 @@ module Harnex
|
|
|
29
29
|
Recipes.new(@argv.drop(1)).run
|
|
30
30
|
when "guide"
|
|
31
31
|
Guide.new.run
|
|
32
|
-
when "
|
|
33
|
-
|
|
32
|
+
when "agents-guide"
|
|
33
|
+
AgentsGuide.new(@argv.drop(1)).run
|
|
34
34
|
when "doctor"
|
|
35
35
|
Doctor.new(@argv.drop(1)).run
|
|
36
36
|
when "help"
|
|
@@ -71,8 +71,10 @@ module Harnex
|
|
|
71
71
|
Recipes.usage
|
|
72
72
|
when "guide"
|
|
73
73
|
Guide.usage
|
|
74
|
-
when "
|
|
75
|
-
|
|
74
|
+
when "agents-guide"
|
|
75
|
+
AgentsGuide.usage
|
|
76
|
+
when "doctor"
|
|
77
|
+
Doctor.usage
|
|
76
78
|
else
|
|
77
79
|
usage
|
|
78
80
|
end
|
|
@@ -89,6 +91,8 @@ module Harnex
|
|
|
89
91
|
harnex logs --id ID [options]
|
|
90
92
|
harnex events --id ID [options]
|
|
91
93
|
harnex pane --id ID [options]
|
|
94
|
+
harnex agents-guide [topic]
|
|
95
|
+
harnex doctor
|
|
92
96
|
harnex help [command]
|
|
93
97
|
|
|
94
98
|
Commands:
|
|
@@ -102,11 +106,13 @@ module Harnex
|
|
|
102
106
|
pane Capture the current tmux pane for a live session
|
|
103
107
|
recipes List and read workflow recipes
|
|
104
108
|
guide Show the getting started guide
|
|
105
|
-
|
|
109
|
+
agents-guide
|
|
110
|
+
Show agent dispatch, chain, buddy, monitoring, and naming guides
|
|
106
111
|
doctor Run preflight checks for adapter dependencies
|
|
107
112
|
help Show command help
|
|
108
113
|
|
|
109
114
|
New to harnex? Start with: harnex guide
|
|
115
|
+
Working with agents (dispatching tasks)? Read: harnex agents-guide
|
|
110
116
|
|
|
111
117
|
Notes:
|
|
112
118
|
CLIs with smart prompt detection: #{Adapters.known.join(', ')}
|
|
@@ -120,8 +126,9 @@ module Harnex
|
|
|
120
126
|
harnex logs --id main --follow
|
|
121
127
|
harnex events --id main --snapshot
|
|
122
128
|
harnex pane --id main --lines 40
|
|
129
|
+
harnex agents-guide dispatch
|
|
130
|
+
harnex doctor
|
|
123
131
|
harnex send --id main --message "Summarize current progress."
|
|
124
|
-
harnex skills install
|
|
125
132
|
TEXT
|
|
126
133
|
end
|
|
127
134
|
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module Harnex
|
|
2
|
+
class AgentsGuide
|
|
3
|
+
GUIDES_DIR = File.expand_path("../../../../guides", __FILE__)
|
|
4
|
+
|
|
5
|
+
def self.usage
|
|
6
|
+
<<~TEXT
|
|
7
|
+
Usage: harnex agents-guide [list|show <topic>|<topic>]
|
|
8
|
+
|
|
9
|
+
Subcommands:
|
|
10
|
+
list List available agent guide topics (default)
|
|
11
|
+
show <topic> Print a guide by name or number
|
|
12
|
+
|
|
13
|
+
Examples:
|
|
14
|
+
harnex agents-guide
|
|
15
|
+
harnex agents-guide list
|
|
16
|
+
harnex agents-guide show 01
|
|
17
|
+
harnex agents-guide show dispatch
|
|
18
|
+
harnex agents-guide monitoring
|
|
19
|
+
|
|
20
|
+
Common patterns:
|
|
21
|
+
harnex agents-guide dispatch
|
|
22
|
+
harnex agents-guide chain
|
|
23
|
+
harnex agents-guide naming
|
|
24
|
+
|
|
25
|
+
Gotchas:
|
|
26
|
+
Agent guides replace the old harnex skills install flow.
|
|
27
|
+
They are packaged with the gem and require no external project docs.
|
|
28
|
+
TEXT
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize(argv)
|
|
32
|
+
@argv = argv.dup
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def run
|
|
36
|
+
subcommand = @argv.shift
|
|
37
|
+
case subcommand
|
|
38
|
+
when nil, "list"
|
|
39
|
+
list_guides
|
|
40
|
+
when "show"
|
|
41
|
+
show_guide(@argv.first)
|
|
42
|
+
when "-h", "--help"
|
|
43
|
+
puts self.class.usage
|
|
44
|
+
0
|
|
45
|
+
else
|
|
46
|
+
show_guide(subcommand)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def list_guides
|
|
53
|
+
files = guide_files
|
|
54
|
+
if files.empty?
|
|
55
|
+
puts "No agent guides found."
|
|
56
|
+
return 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
puts "Agent guides:\n\n"
|
|
60
|
+
files.each do |file|
|
|
61
|
+
name = File.basename(file, ".md")
|
|
62
|
+
title = extract_title(file)
|
|
63
|
+
puts " #{name} #{title}"
|
|
64
|
+
end
|
|
65
|
+
puts "\nRun `harnex agents-guide show <topic>` to read one."
|
|
66
|
+
0
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def show_guide(query)
|
|
70
|
+
unless query
|
|
71
|
+
warn("harnex agents-guide show: topic required")
|
|
72
|
+
return 1
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
file = find_guide(query)
|
|
76
|
+
unless file
|
|
77
|
+
warn("harnex agents-guide: no topic matching #{query.inspect}")
|
|
78
|
+
warn("Run `harnex agents-guide list` to see available topics.")
|
|
79
|
+
return 1
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
puts File.read(file)
|
|
83
|
+
0
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def find_guide(query)
|
|
87
|
+
files = guide_files
|
|
88
|
+
|
|
89
|
+
exact = files.find { |file| File.basename(file, ".md") == query }
|
|
90
|
+
return exact if exact
|
|
91
|
+
|
|
92
|
+
prefix = files.find { |file| File.basename(file, ".md").start_with?(query) }
|
|
93
|
+
return prefix if prefix
|
|
94
|
+
|
|
95
|
+
files.find { |file| File.basename(file, ".md").include?(query) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def guide_files
|
|
99
|
+
return [] unless Dir.exist?(GUIDES_DIR)
|
|
100
|
+
|
|
101
|
+
Dir.glob(File.join(GUIDES_DIR, "*.md")).sort
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def extract_title(file)
|
|
105
|
+
first_line = File.foreach(file).first.to_s.strip
|
|
106
|
+
first_line.start_with?("#") ? first_line.sub(/^#+\s*/, "") : ""
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -12,6 +12,14 @@ module Harnex
|
|
|
12
12
|
Currently verifies that Codex CLI is installed and at version
|
|
13
13
|
>= #{MIN_CODEX_VERSION} (required for the JSON-RPC `app-server`
|
|
14
14
|
adapter).
|
|
15
|
+
|
|
16
|
+
Common patterns:
|
|
17
|
+
harnex doctor
|
|
18
|
+
harnex doctor --help
|
|
19
|
+
|
|
20
|
+
Gotchas:
|
|
21
|
+
doctor validates local adapter prerequisites; it does not start sessions.
|
|
22
|
+
Run it after installing or upgrading Codex CLI.
|
|
15
23
|
TEXT
|
|
16
24
|
end
|
|
17
25
|
|
|
@@ -18,6 +18,16 @@ module Harnex
|
|
|
18
18
|
--snapshot Print current events and exit (alias for --no-follow)
|
|
19
19
|
--from TS Replay floor (ISO-8601, inclusive)
|
|
20
20
|
-h, --help Show this help
|
|
21
|
+
|
|
22
|
+
Common patterns:
|
|
23
|
+
#{program_name} --id cx-i-42 --snapshot
|
|
24
|
+
#{program_name} --id cx-i-42
|
|
25
|
+
#{program_name} --id cx-i-42 --from 2026-05-06T10:00:00Z --snapshot
|
|
26
|
+
|
|
27
|
+
Gotchas:
|
|
28
|
+
events is structured JSONL; logs is human transcript text.
|
|
29
|
+
Default mode follows live events. Use --snapshot to print and exit.
|
|
30
|
+
Use wait --until task_complete when you only need a completion fence.
|
|
21
31
|
TEXT
|
|
22
32
|
end
|
|
23
33
|
|
|
@@ -7,6 +7,15 @@ module Harnex
|
|
|
7
7
|
Usage: harnex guide
|
|
8
8
|
|
|
9
9
|
Print the getting started guide.
|
|
10
|
+
|
|
11
|
+
Common patterns:
|
|
12
|
+
harnex guide
|
|
13
|
+
harnex agents-guide
|
|
14
|
+
harnex recipes
|
|
15
|
+
|
|
16
|
+
Gotchas:
|
|
17
|
+
guide is short human onboarding.
|
|
18
|
+
agents-guide is the deeper operational reference for dispatching agents.
|
|
10
19
|
TEXT
|
|
11
20
|
end
|
|
12
21
|
|
data/lib/harnex/commands/logs.rb
CHANGED
|
@@ -17,6 +17,16 @@ module Harnex
|
|
|
17
17
|
--follow Keep streaming appended output until session exit
|
|
18
18
|
--lines N Print the last N lines before following (default: #{DEFAULT_LINES})
|
|
19
19
|
-h, --help Show this help
|
|
20
|
+
|
|
21
|
+
Common patterns:
|
|
22
|
+
#{program_name} --id cx-i-42 --lines 80
|
|
23
|
+
#{program_name} --id cx-i-42 --follow
|
|
24
|
+
#{program_name} --id cx-i-42 --repo /path/to/repo --lines 200
|
|
25
|
+
|
|
26
|
+
Gotchas:
|
|
27
|
+
logs reads the persisted transcript, not the live tmux screen.
|
|
28
|
+
Use pane when you need the current TUI view or prompt text.
|
|
29
|
+
--follow streams until the live session exits.
|
|
20
30
|
TEXT
|
|
21
31
|
end
|
|
22
32
|
|
data/lib/harnex/commands/pane.rb
CHANGED
|
@@ -20,6 +20,16 @@ module Harnex
|
|
|
20
20
|
--interval N Refresh interval in seconds for --follow (default: #{FOLLOW_INTERVAL.to_i})
|
|
21
21
|
--json Output JSON with capture metadata
|
|
22
22
|
-h, --help Show this help
|
|
23
|
+
|
|
24
|
+
Common patterns:
|
|
25
|
+
#{program_name} --id cx-i-42 --lines 40
|
|
26
|
+
#{program_name} --id cx-i-42 --lines 40 --json
|
|
27
|
+
#{program_name} --id cx-i-42 --follow --interval 2
|
|
28
|
+
|
|
29
|
+
Gotchas:
|
|
30
|
+
pane requires a tmux-backed session.
|
|
31
|
+
Use --repo when the same ID exists in multiple repos or worktrees.
|
|
32
|
+
Do not use pane state alone as completion proof; verify artifacts/tests.
|
|
23
33
|
TEXT
|
|
24
34
|
end
|
|
25
35
|
|
|
@@ -17,6 +17,15 @@ module Harnex
|
|
|
17
17
|
harnex recipes list
|
|
18
18
|
harnex recipes show 01
|
|
19
19
|
harnex recipes show fire_and_watch
|
|
20
|
+
|
|
21
|
+
Common patterns:
|
|
22
|
+
harnex recipes show 01 # Fire and Watch
|
|
23
|
+
harnex recipes show 02 # Chain Implement
|
|
24
|
+
harnex recipes show 03 # Buddy
|
|
25
|
+
|
|
26
|
+
Gotchas:
|
|
27
|
+
Recipes are compact command walkthroughs.
|
|
28
|
+
Use `harnex agents-guide` for the deeper agent-facing guide.
|
|
20
29
|
TEXT
|
|
21
30
|
end
|
|
22
31
|
|
data/lib/harnex/commands/run.rb
CHANGED
|
@@ -48,6 +48,17 @@ module Harnex
|
|
|
48
48
|
CLIs with smart prompt detection: #{Adapters.known.join(', ')}
|
|
49
49
|
Any other CLI name is launched with generic wrapping.
|
|
50
50
|
Wrapper options may appear before or after <cli>.
|
|
51
|
+
|
|
52
|
+
Common patterns:
|
|
53
|
+
#{program_name} codex --id cx-i-42 --tmux cx-i-42 --context "Read /tmp/task-impl-42.md"
|
|
54
|
+
#{program_name} codex --id cx-i-42 --watch --preset impl --context "Read /tmp/task-impl-42.md"
|
|
55
|
+
#{program_name} claude --id cl-r-42 --tmux cl-r-42 --description "Review task 42"
|
|
56
|
+
|
|
57
|
+
Gotchas:
|
|
58
|
+
Always pair --id and --tmux with the same value for delegated work.
|
|
59
|
+
Passing --tmux without --id creates a random harnex session ID.
|
|
60
|
+
--watch is foreground-only; do not combine it with --tmux or --detach.
|
|
61
|
+
Use -- before child CLI flags when a flag could be parsed by harnex.
|
|
51
62
|
TEXT
|
|
52
63
|
end
|
|
53
64
|
|