handback 0.2.0__tar.gz
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.
- handback-0.2.0/LICENSE +21 -0
- handback-0.2.0/PKG-INFO +300 -0
- handback-0.2.0/README.md +269 -0
- handback-0.2.0/handback/__init__.py +3 -0
- handback-0.2.0/handback/__main__.py +3 -0
- handback-0.2.0/handback/adapters/__init__.py +18 -0
- handback-0.2.0/handback/adapters/antigravity.py +702 -0
- handback-0.2.0/handback/adapters/base.py +44 -0
- handback-0.2.0/handback/adapters/claude.py +38 -0
- handback-0.2.0/handback/adapters/codex.py +471 -0
- handback-0.2.0/handback/assets/icon-16.png +0 -0
- handback-0.2.0/handback/assets/icon-256.png +0 -0
- handback-0.2.0/handback/assets/icon-32.png +0 -0
- handback-0.2.0/handback/assets/icon-48.png +0 -0
- handback-0.2.0/handback/assets/icon-64.png +0 -0
- handback-0.2.0/handback/assets/icon.ico +0 -0
- handback-0.2.0/handback/cli.py +816 -0
- handback-0.2.0/handback/collector.py +231 -0
- handback-0.2.0/handback/config.py +182 -0
- handback-0.2.0/handback/dashboard.py +1485 -0
- handback-0.2.0/handback/diagnostics.py +326 -0
- handback-0.2.0/handback/envelope.py +69 -0
- handback-0.2.0/handback/hook_install.py +365 -0
- handback-0.2.0/handback/hooks.py +472 -0
- handback-0.2.0/handback/inbox.py +224 -0
- handback-0.2.0/handback/invocation.py +18 -0
- handback-0.2.0/handback/migration.py +383 -0
- handback-0.2.0/handback/router.py +165 -0
- handback-0.2.0/handback/skill_install.py +102 -0
- handback-0.2.0/handback/skills/SKILL.md +60 -0
- handback-0.2.0/handback/skills/antigravity/SKILL.md.in +3 -0
- handback-0.2.0/handback/skills/codex/SKILL.md.in +3 -0
- handback-0.2.0/handback/state.py +462 -0
- handback-0.2.0/handback/state_transition.py +79 -0
- handback-0.2.0/handback/watcher.py +84 -0
- handback-0.2.0/handback.egg-info/PKG-INFO +300 -0
- handback-0.2.0/handback.egg-info/SOURCES.txt +63 -0
- handback-0.2.0/handback.egg-info/dependency_links.txt +1 -0
- handback-0.2.0/handback.egg-info/entry_points.txt +5 -0
- handback-0.2.0/handback.egg-info/top_level.txt +1 -0
- handback-0.2.0/pyproject.toml +32 -0
- handback-0.2.0/setup.cfg +4 -0
- handback-0.2.0/tests/test_antigravity.py +475 -0
- handback-0.2.0/tests/test_cli.py +274 -0
- handback-0.2.0/tests/test_codex.py +220 -0
- handback-0.2.0/tests/test_collector.py +281 -0
- handback-0.2.0/tests/test_config.py +160 -0
- handback-0.2.0/tests/test_dashboard.py +142 -0
- handback-0.2.0/tests/test_dashboard_compact.py +294 -0
- handback-0.2.0/tests/test_dashboard_gui.py +524 -0
- handback-0.2.0/tests/test_dashboard_links.py +61 -0
- handback-0.2.0/tests/test_diagnostics.py +262 -0
- handback-0.2.0/tests/test_envelope.py +79 -0
- handback-0.2.0/tests/test_first_task.py +227 -0
- handback-0.2.0/tests/test_hook_install.py +340 -0
- handback-0.2.0/tests/test_hooks.py +350 -0
- handback-0.2.0/tests/test_inbox.py +184 -0
- handback-0.2.0/tests/test_lead_handoff.py +107 -0
- handback-0.2.0/tests/test_migration.py +302 -0
- handback-0.2.0/tests/test_rename.py +147 -0
- handback-0.2.0/tests/test_router.py +390 -0
- handback-0.2.0/tests/test_skill_install.py +123 -0
- handback-0.2.0/tests/test_state.py +262 -0
- handback-0.2.0/tests/test_state_transition.py +121 -0
- handback-0.2.0/tests/test_watcher.py +147 -0
handback-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 handback contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
handback-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: handback
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local, durable relay between coding-agent apps
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 handback contributors
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Femur-0607/handback/main/docs/assets/handback-logo.png" alt="handback" width="420"></p>
|
|
33
|
+
|
|
34
|
+
https://github.com/user-attachments/assets/b9927ffd-ec73-4980-a128-65842894e269
|
|
35
|
+
|
|
36
|
+
# handback
|
|
37
|
+
|
|
38
|
+
Previously developed as **agent-relay**; legacy state is detected with migration guidance.
|
|
39
|
+
|
|
40
|
+
A local tool for handing work between coding-agent apps and bringing the results back to the conversation where you started.
|
|
41
|
+
|
|
42
|
+
**Experimental · Windows verified · Python 3.10+ · One computer, one OS user**
|
|
43
|
+
|
|
44
|
+
[First task](#try-your-first-task) · [Use-your-own-project guide](#use-it-on-your-own-project) · [Detailed setup](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) · [한국어 사용 설명서](https://github.com/Femur-0607/handback/blob/main/docs/usage.ko.md)
|
|
45
|
+
|
|
46
|
+
## What is handback?
|
|
47
|
+
|
|
48
|
+
handback connects coding agents running on your computer. You work with one main conversation, called the **Lead**, and let it send a defined task to another conversation, called a **worker**. The relay creates the worker conversation, sends the task, and saves its reply in a local inbox for the Lead to review.
|
|
49
|
+
|
|
50
|
+
For example, you can discuss a change with Claude, have a Codex worker inspect the relevant code, and review its findings back in Claude. The apps perform the reasoning and coding; handback handles task delivery, result collection, and recovery.
|
|
51
|
+
|
|
52
|
+
It runs as an installed Python package or directly from this repository, using only Python's standard library. You need the supported agent apps installed and signed in. Everything is scoped to one computer and one OS user, and no other project repository is required.
|
|
53
|
+
|
|
54
|
+
## When to use it / when not to
|
|
55
|
+
|
|
56
|
+
Use it to hand bounded tasks between **different agent apps** when results must survive interruptions without duplicate submission. Within one app, prefer its built-in subagents. This tool is not for teams, multiple machines, or parallel writes to one checkout.
|
|
57
|
+
|
|
58
|
+
Delegating heavy reading, investigation, and implementation to workers helps keep the Lead conversation small.
|
|
59
|
+
|
|
60
|
+
## Why it exists
|
|
61
|
+
|
|
62
|
+
handback started from a simple wish: let the agent apps already on my computer talk to each other while I can still watch every conversation in the apps themselves. That is why a worker is a real conversation inside its own app, not a hidden subprocess. You can open it at any time and follow the work as it happens.
|
|
63
|
+
|
|
64
|
+
Working across multiple coding agents creates repeated handoffs: send the task, remember which conversation is working on it, find the answer, and bring it back to the original discussion. If a conversation closes or a wait times out, it can also become unclear whether a task finished or should be sent again.
|
|
65
|
+
|
|
66
|
+
handback gives each request an identity and keeps its result on disk. The Lead can retrieve an existing request after an interruption and mark a reviewed result as handled. This makes the handoff easier to follow and reduces the risk of submitting the same work twice.
|
|
67
|
+
|
|
68
|
+
It is intended for developers who already use multiple supported coding-agent apps and want to coordinate bounded tasks in their own projects. You still decide what work is allowed and review the results. A message from an agent is task information, never user authorization.
|
|
69
|
+
|
|
70
|
+
## How a task moves
|
|
71
|
+
|
|
72
|
+
1. **You give the Lead a goal and limits**, such as reviewing a module without changing files.
|
|
73
|
+
2. **The Lead delegates a task to a worker.** The worker receives its own conversation and a brief describing the work.
|
|
74
|
+
3. **The relay collects the reply into an inbox.** The saved result remains available if the Lead closes or collection is interrupted.
|
|
75
|
+
4. **The Lead reviews the result and acknowledges it.** An acknowledgement, or **ACK**, marks it as handled so it stops replaying. The original message is retained.
|
|
76
|
+
|
|
77
|
+
You can also run these steps from a terminal. The first example below uses terminal commands so you can check the complete handoff before relying on automatic reception in an app.
|
|
78
|
+
|
|
79
|
+
## Supported combinations
|
|
80
|
+
|
|
81
|
+
| Lead | Workers | Result reception |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| Claude | Codex, Antigravity, or both | Monitor and explicit inbox reads; session recovery hooks where available |
|
|
84
|
+
| Codex | Antigravity only | External Codex queue, inbox, and ACK |
|
|
85
|
+
|
|
86
|
+
Start with **Claude Lead → Codex worker**. Claude workers, Codex Lead → Codex worker, Antigravity Lead, and automatic quota fallback are unsupported.
|
|
87
|
+
|
|
88
|
+
Windows has live integration coverage. macOS and Linux are unverified. App queue, transcript, and hook contracts can change with updates; see the [verification summary](https://github.com/Femur-0607/handback/blob/main/docs/verification/README.md) for tested behavior and remaining gaps.
|
|
89
|
+
|
|
90
|
+
## Install
|
|
91
|
+
|
|
92
|
+
After the PyPI release (not published yet), install into an isolated tool environment:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
uv tool install handback
|
|
96
|
+
# Or, with Python already available:
|
|
97
|
+
pipx install handback
|
|
98
|
+
handback install-skills --dry-run
|
|
99
|
+
handback install-skills
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
uv can provision Python when needed. From a source checkout today, use `uv tool install .` or `pipx install .`, then the same `handback` commands. No runtime dependencies are installed. The optional `handback-dashboard` GUI requires a Python build with Tk support.
|
|
103
|
+
|
|
104
|
+
`handback install-skills --dry-run --target-home <absolute-test-home>` previews an isolated installation without consulting host PATH or CODEX_HOME. Existing skills get timestamp backups. Claude is always installed; Codex and Antigravity require app detection, and Antigravity also requires a registered skill directory. Without `--target-home`, detection checks the known Windows app paths and PATH on all platforms.
|
|
105
|
+
|
|
106
|
+
Packaged skills and hooks use the environment's absolute Python executable with `-m handback`. A direct, uninstalled checkout uses its absolute entry script instead, so hooks and workers also run from other project directories. Keep that environment (or checkout) available, and reinstall skills/hooks if you move it. Existing hook ownership manifests still support removing or upgrading old script-based hooks.
|
|
107
|
+
|
|
108
|
+
The source-only walkthrough below remains supported; `install.ps1` is a thin wrapper around `python handback.py install-skills`. Package users can replace `python "$relayScript"` in later examples with `handback`.
|
|
109
|
+
|
|
110
|
+
## Try your first task
|
|
111
|
+
|
|
112
|
+
Start with **Claude Lead → Codex worker**. Have these ready:
|
|
113
|
+
|
|
114
|
+
- Windows, PowerShell, and Python 3.10 or newer available as `python`.
|
|
115
|
+
- Git if you clone the repository, or an extracted source archive.
|
|
116
|
+
- Claude and Codex installed and signed in; start the apps before testing.
|
|
117
|
+
|
|
118
|
+
After installation, run this from your project in a normal terminal, outside an agent sandbox:
|
|
119
|
+
|
|
120
|
+
```powershell
|
|
121
|
+
handback try
|
|
122
|
+
# From an uninstalled source checkout:
|
|
123
|
+
python handback.py try
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`try` checks configuration and Codex detection, creates one read-only worker, sends a reply-only task, verifies its saved `RELAY_OK` result and request identity, then ACKs it. It prints the worker handle, request ID, elapsed time, result, and ACK status. It does not install skills or hooks. App detection alone does not verify login or queue compatibility; the task checks the round trip.
|
|
127
|
+
|
|
128
|
+
Use `--root <path>` for another project, `--lead claude:<session-id>` when selecting a new topology, `--timeout 300` for the wait limit (default; `0` waits indefinitely), `--keep` to leave the result unread, or `--json` for machine output. An existing topology with a Codex worker is reused; an incompatible one is left untouched with a suggested `use` command. On timeout or unknown delivery, run the printed `wait --request ...` command; never resubmit.
|
|
129
|
+
|
|
130
|
+
<details>
|
|
131
|
+
<summary>What `try` does, step by step (manual setup and recovery)</summary>
|
|
132
|
+
|
|
133
|
+
The manual route below includes optional skill setup. Keep the same state home and PowerShell session throughout.
|
|
134
|
+
|
|
135
|
+
### 1. Get the tool and check your setup
|
|
136
|
+
|
|
137
|
+
```powershell
|
|
138
|
+
git clone https://github.com/Femur-0607/handback.git
|
|
139
|
+
Set-Location handback
|
|
140
|
+
$relayRoot = (Get-Location).Path
|
|
141
|
+
$relayScript = Join-Path $relayRoot 'handback.py'
|
|
142
|
+
python --version
|
|
143
|
+
python "$relayScript" doctor --root "$relayRoot"
|
|
144
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 -DryRun
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
If you downloaded an archive, open its extracted `handback` folder in PowerShell and continue from `$relayRoot = ...`. No `pip install` is required. Review the diagnostic output and planned installation paths. `doctor` checks app availability; it does not prove a task can complete. See [setup and troubleshooting](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) if it reports a missing app or an existing-state warning.
|
|
148
|
+
|
|
149
|
+
### 2. Install the skills and select the Lead inbox
|
|
150
|
+
|
|
151
|
+
```powershell
|
|
152
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1
|
|
153
|
+
$leadAddress = "claude:lead"
|
|
154
|
+
python "$relayScript" use --root "$relayRoot" --lead "$leadAddress" --workers codex
|
|
155
|
+
python "$relayScript" status --root "$relayRoot"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Check that `status` shows the Claude Lead and Codex worker combination. `claude:lead` is an inbox address for this first test; you do not need to discover a real Claude session ID to read its results manually. Session-specific recovery hooks require a real session ID later.
|
|
159
|
+
|
|
160
|
+
The installer writes agent skills and backs up existing skill files. It does not start the apps, a Lead conversation, or a watcher. Keep the checkout after installation because the installed skills refer to its files. The Windows default state home is `%USERPROFILE%\.handback`; if you already set `HANDBACK_HOME`, keep the same value throughout.
|
|
161
|
+
|
|
162
|
+
### 3. Send one small task
|
|
163
|
+
|
|
164
|
+
This command creates a real Codex worker conversation and sends one task:
|
|
165
|
+
|
|
166
|
+
```powershell
|
|
167
|
+
python "$relayScript" new --worker codex --cwd "$relayRoot" --name "relay first task" --sandbox read-only --text "Do not modify files or delegate. Reply with RELAY_OK in this conversation." --no-wait
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Save the returned JSON, especially `request_id` and `handle`. With `--no-wait`, a successful exit means the task was accepted; its result may still be pending. A detached collector gathers the reply.
|
|
171
|
+
|
|
172
|
+
### 4. Collect and review the answer
|
|
173
|
+
|
|
174
|
+
Replace the placeholder with the `request_id` returned above:
|
|
175
|
+
|
|
176
|
+
```powershell
|
|
177
|
+
$requestId = "<request_id from the previous command>"
|
|
178
|
+
python "$relayScript" wait --root "$relayRoot" --request "$requestId" --timeout 300
|
|
179
|
+
python "$relayScript" inbox list --root "$relayRoot" --for "$leadAddress"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Check that the result belongs to this request and contains `RELAY_OK`. If waiting times out, keep this request ID and follow the recovery section below. Do not send the task again.
|
|
183
|
+
|
|
184
|
+
### 5. Mark the result as handled
|
|
185
|
+
|
|
186
|
+
Use the same request ID after reviewing its result:
|
|
187
|
+
|
|
188
|
+
```powershell
|
|
189
|
+
python "$relayScript" inbox ack --root "$relayRoot" --for "$leadAddress" --request "$requestId"
|
|
190
|
+
python "$relayScript" inbox list --root "$relayRoot" --for "$leadAddress"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The handled result should disappear from the pending list while its original file stays on disk. You have now checked task submission, collection, review, and acknowledgement.
|
|
194
|
+
|
|
195
|
+
</details>
|
|
196
|
+
|
|
197
|
+
## Use it on your own project
|
|
198
|
+
|
|
199
|
+
Install the relay once, then select the project you want to work on. **The relay installation folder and your working project are separate paths.** Keep `$relayScript` pointing to the installed tool, and set `$projectRoot` to your existing source folder:
|
|
200
|
+
|
|
201
|
+
```powershell
|
|
202
|
+
$projectRoot = (Resolve-Path "<path-to-your-existing-project>").Path
|
|
203
|
+
python "$relayScript" use --root "$projectRoot" --lead "$leadAddress" --workers codex
|
|
204
|
+
python "$relayScript" status --root "$projectRoot"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Open that project in your Lead app and confirm the installed `handback` skill is available. Here is an example request to give a Claude Lead; replace both paths and the module name:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
Use the handback skill for the project at <absolute-project-path>.
|
|
211
|
+
The relay script is <absolute-relay-installation>/handback.py.
|
|
212
|
+
Use claude:lead as the Lead inbox and Codex as the worker.
|
|
213
|
+
Ask one worker to review error handling in <module-path> without changing files.
|
|
214
|
+
Collect its result, review the findings, summarize them here, and ACK the result after review.
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
For terminal commands, use `--cwd "$projectRoot"` when creating a worker and `--root "$projectRoot"` for topology, status, waiting, and inbox commands. The worker works on that project. Use one worker conversation per unit of work and run units sequentially when they share a checkout. Send corrections to the same worker only after its previous request finishes.
|
|
218
|
+
|
|
219
|
+
For automatic results in a Claude conversation, have the Lead run `inbox watch` through its **Monitor** tool. A watcher in an ordinary terminal prints only to that terminal. Started with `--idle-exit 1200`, the watcher stops after 20 idle minutes; re-arm Monitor only while requests are open. If Monitor is unavailable, use explicit `wait` and `inbox list` commands. Fresh skill auto-loading and global recovery hook loading remain incompletely verified; the [detailed setup guide](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) covers these limits and the exact watcher command.
|
|
220
|
+
|
|
221
|
+
For Antigravity, register **your working project** in its app, enable its adapter, and install its relay hooks before selecting it. Follow the [Antigravity setup](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md#optional-antigravity-setup); the Codex-only test above does not configure that combination.
|
|
222
|
+
|
|
223
|
+
## Delivery and recovery
|
|
224
|
+
|
|
225
|
+
Submission, completion, Lead delivery, and ACK are separate events. An asynchronous submission returning success means the request was accepted. It does not mean the task finished.
|
|
226
|
+
|
|
227
|
+
### Result did not come back
|
|
228
|
+
|
|
229
|
+
Start with `doctor`, then `explain --request` for the saved request ID. Both are read-only; `explain` ends with one next action and never sends, collects, or ACKs:
|
|
230
|
+
|
|
231
|
+
```powershell
|
|
232
|
+
python "$relayScript" doctor --root "$projectRoot"
|
|
233
|
+
python "$relayScript" explain --root "$projectRoot" --request "<saved-request-id>"
|
|
234
|
+
python "$relayScript" wait --root "$projectRoot" --request "<saved-request-id>" --timeout 300
|
|
235
|
+
python "$relayScript" inbox list --root "$projectRoot" --for "$leadAddress"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Use the same project, Lead inbox, and state home as the original request. For the first test above, use `$relayRoot` instead of `$projectRoot`. `wait` recovers the existing request without submitting it again. Reading a result does not ACK it.
|
|
239
|
+
|
|
240
|
+
`doctor` prints OK/WARN/FAIL checks and one next step for each warning/failure (exit 5 for FAIL, 0 otherwise). `doctor --json` preserves the original JSON interface; `explain --json` provides the timeline as JSON. For an issue, copy the redacted block from `doctor --report`. `status --stats --days 30` summarizes local request outcomes, latency, additional delivery attempts, and unACKed results without telemetry. Collection timeouts, recovery via `wait`, and explicit redeliveries are not independently recorded and cannot be counted reliably.
|
|
241
|
+
|
|
242
|
+
The [detailed guide](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) covers timeouts, replay, custom state homes, cleanup, and uninstall; the [Korean manual](https://github.com/Femur-0607/handback/blob/main/docs/usage.ko.md) describes the full command set and adapter limits.
|
|
243
|
+
|
|
244
|
+
## Optional dashboard
|
|
245
|
+
|
|
246
|
+
Run `pythonw dashboard.pyw` from the relay installation folder to see project activity, in-progress tasks, and unacknowledged results. The dashboard is optional; it is not required for delegation. `python handback.py dashboard --autostart on` starts the dashboard at Windows login, not the Lead or its Monitor.
|
|
247
|
+
|
|
248
|
+
<details>
|
|
249
|
+
<summary>Dashboard memory measurements</summary>
|
|
250
|
+
|
|
251
|
+
The optional dashboard was measured on **October 8, 2026**, using Windows, Python 3.13.15, and Tk 8.6.15. These figures describe the dashboard process, excluding the separately running agent apps.
|
|
252
|
+
|
|
253
|
+
| Check | Observed result | Conditions |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| GUI footprint | About **33 MiB working set** and **19 MiB private memory** | A fresh process with a hidden window, 5 projects, no unread results, normal 3-second refresh, and a 15-second observation |
|
|
256
|
+
| Context-menu leak fix | Menu widgets, Tcl commands, Windows GUI resources, and handles stayed constant from 100 to 500 menu openings | Real Tk widgets with native popup display suppressed; the previous menu tree and its callbacks are destroyed before replacement |
|
|
257
|
+
| Large unread inbox | About **60.3 MiB peak additional Python heap**; **2.7 seconds median per snapshot** | Snapshot only, without Tk: 1,000 unread results with 60 KiB bodies plus 1,000 completed requests; 5 timed runs |
|
|
258
|
+
|
|
259
|
+
The large-inbox figure measures Python allocations, not total process memory, and timing can vary with concurrent filesystem activity. Refreshes scan stored history and load unread message bodies; showing fewer rows does not cap that work. Usage therefore depends on the amount of stored data and the environment. These short checks do not establish a memory limit or guarantee leak-free operation over hours or days.
|
|
260
|
+
|
|
261
|
+
[Menu regression tests](https://github.com/Femur-0607/handback/blob/main/tests/test_dashboard_gui.py) cover repeated menu creation, callback cleanup, current settings, and closing the dashboard. They use hidden Tk windows and skip when Tk or a display is unavailable.
|
|
262
|
+
|
|
263
|
+
</details>
|
|
264
|
+
|
|
265
|
+
## Limitations
|
|
266
|
+
|
|
267
|
+
- Long-running Lead and reused worker conversations accumulate context; use bounded units and documented stage handoffs.
|
|
268
|
+
- Replacing the Lead preserves old requests' return addresses; explicitly read and ACK the old inbox.
|
|
269
|
+
- Windows has live verification; operation is local to one computer and OS user, with restricted agent combinations.
|
|
270
|
+
- App updates, uncertain delivery, and Monitor expiry require deliberate diagnostics and recovery; Antigravity cannot enforce read-only access.
|
|
271
|
+
- Shared-checkout work should be sequential, and dashboard scan cost grows with history. See [known limitations and workarounds](https://github.com/Femur-0607/handback/blob/main/docs/limitations.md) for details and commands.
|
|
272
|
+
|
|
273
|
+
## Development
|
|
274
|
+
|
|
275
|
+
Implementation lives in `handback/`, the CLI entry point is `handback.py`, and tests are in `tests/`.
|
|
276
|
+
|
|
277
|
+
```powershell
|
|
278
|
+
python -m unittest
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Unit tests use isolated fixtures. They do not establish compatibility with a current app build; live integration results are tracked separately in the [verification summary](https://github.com/Femur-0607/handback/blob/main/docs/verification/README.md). See [Contributing](https://github.com/Femur-0607/handback/blob/main/CONTRIBUTING.md) for test and bug-report requirements.
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
[MIT](https://github.com/Femur-0607/handback/blob/main/LICENSE). The license covers this repository's code; the agent applications are separately installed and retain their own licenses and terms.
|
|
286
|
+
|
|
287
|
+
## Migrating a previous local installation
|
|
288
|
+
|
|
289
|
+
`HANDBACK_HOME` selects the state directory. Defaults are `%USERPROFILE%\.handback`
|
|
290
|
+
on Windows, `~/Library/Application Support/handback` on macOS, and
|
|
291
|
+
`${XDG_STATE_HOME:-~/.local/state}/handback` on Linux. `AGENT_RELAY_HOME` is never
|
|
292
|
+
used as the new state setting. `handback doctor` warns about legacy state and prints
|
|
293
|
+
`handback migrate-state --from '<old-state-path>'`. Stop requests, collectors, and
|
|
294
|
+
watchers before copying. Migration verifies copied bytes, retains the original files,
|
|
295
|
+
and adds a `MOVED.json` receipt to prevent accidental writes to the old store.
|
|
296
|
+
|
|
297
|
+
Reinstall hooks and skills with `handback install-hooks` and `handback install-skills`;
|
|
298
|
+
legacy hooks are recognized and original skill files receive timestamp backups.
|
|
299
|
+
Copy a legacy `.agent-relay.json` project policy to `.handback.json`. Until then the
|
|
300
|
+
legacy policy is read with a warning; when both exist, `.handback.json` takes precedence.
|
handback-0.2.0/README.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Femur-0607/handback/main/docs/assets/handback-logo.png" alt="handback" width="420"></p>
|
|
2
|
+
|
|
3
|
+
https://github.com/user-attachments/assets/b9927ffd-ec73-4980-a128-65842894e269
|
|
4
|
+
|
|
5
|
+
# handback
|
|
6
|
+
|
|
7
|
+
Previously developed as **agent-relay**; legacy state is detected with migration guidance.
|
|
8
|
+
|
|
9
|
+
A local tool for handing work between coding-agent apps and bringing the results back to the conversation where you started.
|
|
10
|
+
|
|
11
|
+
**Experimental · Windows verified · Python 3.10+ · One computer, one OS user**
|
|
12
|
+
|
|
13
|
+
[First task](#try-your-first-task) · [Use-your-own-project guide](#use-it-on-your-own-project) · [Detailed setup](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) · [한국어 사용 설명서](https://github.com/Femur-0607/handback/blob/main/docs/usage.ko.md)
|
|
14
|
+
|
|
15
|
+
## What is handback?
|
|
16
|
+
|
|
17
|
+
handback connects coding agents running on your computer. You work with one main conversation, called the **Lead**, and let it send a defined task to another conversation, called a **worker**. The relay creates the worker conversation, sends the task, and saves its reply in a local inbox for the Lead to review.
|
|
18
|
+
|
|
19
|
+
For example, you can discuss a change with Claude, have a Codex worker inspect the relevant code, and review its findings back in Claude. The apps perform the reasoning and coding; handback handles task delivery, result collection, and recovery.
|
|
20
|
+
|
|
21
|
+
It runs as an installed Python package or directly from this repository, using only Python's standard library. You need the supported agent apps installed and signed in. Everything is scoped to one computer and one OS user, and no other project repository is required.
|
|
22
|
+
|
|
23
|
+
## When to use it / when not to
|
|
24
|
+
|
|
25
|
+
Use it to hand bounded tasks between **different agent apps** when results must survive interruptions without duplicate submission. Within one app, prefer its built-in subagents. This tool is not for teams, multiple machines, or parallel writes to one checkout.
|
|
26
|
+
|
|
27
|
+
Delegating heavy reading, investigation, and implementation to workers helps keep the Lead conversation small.
|
|
28
|
+
|
|
29
|
+
## Why it exists
|
|
30
|
+
|
|
31
|
+
handback started from a simple wish: let the agent apps already on my computer talk to each other while I can still watch every conversation in the apps themselves. That is why a worker is a real conversation inside its own app, not a hidden subprocess. You can open it at any time and follow the work as it happens.
|
|
32
|
+
|
|
33
|
+
Working across multiple coding agents creates repeated handoffs: send the task, remember which conversation is working on it, find the answer, and bring it back to the original discussion. If a conversation closes or a wait times out, it can also become unclear whether a task finished or should be sent again.
|
|
34
|
+
|
|
35
|
+
handback gives each request an identity and keeps its result on disk. The Lead can retrieve an existing request after an interruption and mark a reviewed result as handled. This makes the handoff easier to follow and reduces the risk of submitting the same work twice.
|
|
36
|
+
|
|
37
|
+
It is intended for developers who already use multiple supported coding-agent apps and want to coordinate bounded tasks in their own projects. You still decide what work is allowed and review the results. A message from an agent is task information, never user authorization.
|
|
38
|
+
|
|
39
|
+
## How a task moves
|
|
40
|
+
|
|
41
|
+
1. **You give the Lead a goal and limits**, such as reviewing a module without changing files.
|
|
42
|
+
2. **The Lead delegates a task to a worker.** The worker receives its own conversation and a brief describing the work.
|
|
43
|
+
3. **The relay collects the reply into an inbox.** The saved result remains available if the Lead closes or collection is interrupted.
|
|
44
|
+
4. **The Lead reviews the result and acknowledges it.** An acknowledgement, or **ACK**, marks it as handled so it stops replaying. The original message is retained.
|
|
45
|
+
|
|
46
|
+
You can also run these steps from a terminal. The first example below uses terminal commands so you can check the complete handoff before relying on automatic reception in an app.
|
|
47
|
+
|
|
48
|
+
## Supported combinations
|
|
49
|
+
|
|
50
|
+
| Lead | Workers | Result reception |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| Claude | Codex, Antigravity, or both | Monitor and explicit inbox reads; session recovery hooks where available |
|
|
53
|
+
| Codex | Antigravity only | External Codex queue, inbox, and ACK |
|
|
54
|
+
|
|
55
|
+
Start with **Claude Lead → Codex worker**. Claude workers, Codex Lead → Codex worker, Antigravity Lead, and automatic quota fallback are unsupported.
|
|
56
|
+
|
|
57
|
+
Windows has live integration coverage. macOS and Linux are unverified. App queue, transcript, and hook contracts can change with updates; see the [verification summary](https://github.com/Femur-0607/handback/blob/main/docs/verification/README.md) for tested behavior and remaining gaps.
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
After the PyPI release (not published yet), install into an isolated tool environment:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
uv tool install handback
|
|
65
|
+
# Or, with Python already available:
|
|
66
|
+
pipx install handback
|
|
67
|
+
handback install-skills --dry-run
|
|
68
|
+
handback install-skills
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
uv can provision Python when needed. From a source checkout today, use `uv tool install .` or `pipx install .`, then the same `handback` commands. No runtime dependencies are installed. The optional `handback-dashboard` GUI requires a Python build with Tk support.
|
|
72
|
+
|
|
73
|
+
`handback install-skills --dry-run --target-home <absolute-test-home>` previews an isolated installation without consulting host PATH or CODEX_HOME. Existing skills get timestamp backups. Claude is always installed; Codex and Antigravity require app detection, and Antigravity also requires a registered skill directory. Without `--target-home`, detection checks the known Windows app paths and PATH on all platforms.
|
|
74
|
+
|
|
75
|
+
Packaged skills and hooks use the environment's absolute Python executable with `-m handback`. A direct, uninstalled checkout uses its absolute entry script instead, so hooks and workers also run from other project directories. Keep that environment (or checkout) available, and reinstall skills/hooks if you move it. Existing hook ownership manifests still support removing or upgrading old script-based hooks.
|
|
76
|
+
|
|
77
|
+
The source-only walkthrough below remains supported; `install.ps1` is a thin wrapper around `python handback.py install-skills`. Package users can replace `python "$relayScript"` in later examples with `handback`.
|
|
78
|
+
|
|
79
|
+
## Try your first task
|
|
80
|
+
|
|
81
|
+
Start with **Claude Lead → Codex worker**. Have these ready:
|
|
82
|
+
|
|
83
|
+
- Windows, PowerShell, and Python 3.10 or newer available as `python`.
|
|
84
|
+
- Git if you clone the repository, or an extracted source archive.
|
|
85
|
+
- Claude and Codex installed and signed in; start the apps before testing.
|
|
86
|
+
|
|
87
|
+
After installation, run this from your project in a normal terminal, outside an agent sandbox:
|
|
88
|
+
|
|
89
|
+
```powershell
|
|
90
|
+
handback try
|
|
91
|
+
# From an uninstalled source checkout:
|
|
92
|
+
python handback.py try
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`try` checks configuration and Codex detection, creates one read-only worker, sends a reply-only task, verifies its saved `RELAY_OK` result and request identity, then ACKs it. It prints the worker handle, request ID, elapsed time, result, and ACK status. It does not install skills or hooks. App detection alone does not verify login or queue compatibility; the task checks the round trip.
|
|
96
|
+
|
|
97
|
+
Use `--root <path>` for another project, `--lead claude:<session-id>` when selecting a new topology, `--timeout 300` for the wait limit (default; `0` waits indefinitely), `--keep` to leave the result unread, or `--json` for machine output. An existing topology with a Codex worker is reused; an incompatible one is left untouched with a suggested `use` command. On timeout or unknown delivery, run the printed `wait --request ...` command; never resubmit.
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary>What `try` does, step by step (manual setup and recovery)</summary>
|
|
101
|
+
|
|
102
|
+
The manual route below includes optional skill setup. Keep the same state home and PowerShell session throughout.
|
|
103
|
+
|
|
104
|
+
### 1. Get the tool and check your setup
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
git clone https://github.com/Femur-0607/handback.git
|
|
108
|
+
Set-Location handback
|
|
109
|
+
$relayRoot = (Get-Location).Path
|
|
110
|
+
$relayScript = Join-Path $relayRoot 'handback.py'
|
|
111
|
+
python --version
|
|
112
|
+
python "$relayScript" doctor --root "$relayRoot"
|
|
113
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 -DryRun
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If you downloaded an archive, open its extracted `handback` folder in PowerShell and continue from `$relayRoot = ...`. No `pip install` is required. Review the diagnostic output and planned installation paths. `doctor` checks app availability; it does not prove a task can complete. See [setup and troubleshooting](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) if it reports a missing app or an existing-state warning.
|
|
117
|
+
|
|
118
|
+
### 2. Install the skills and select the Lead inbox
|
|
119
|
+
|
|
120
|
+
```powershell
|
|
121
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1
|
|
122
|
+
$leadAddress = "claude:lead"
|
|
123
|
+
python "$relayScript" use --root "$relayRoot" --lead "$leadAddress" --workers codex
|
|
124
|
+
python "$relayScript" status --root "$relayRoot"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Check that `status` shows the Claude Lead and Codex worker combination. `claude:lead` is an inbox address for this first test; you do not need to discover a real Claude session ID to read its results manually. Session-specific recovery hooks require a real session ID later.
|
|
128
|
+
|
|
129
|
+
The installer writes agent skills and backs up existing skill files. It does not start the apps, a Lead conversation, or a watcher. Keep the checkout after installation because the installed skills refer to its files. The Windows default state home is `%USERPROFILE%\.handback`; if you already set `HANDBACK_HOME`, keep the same value throughout.
|
|
130
|
+
|
|
131
|
+
### 3. Send one small task
|
|
132
|
+
|
|
133
|
+
This command creates a real Codex worker conversation and sends one task:
|
|
134
|
+
|
|
135
|
+
```powershell
|
|
136
|
+
python "$relayScript" new --worker codex --cwd "$relayRoot" --name "relay first task" --sandbox read-only --text "Do not modify files or delegate. Reply with RELAY_OK in this conversation." --no-wait
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Save the returned JSON, especially `request_id` and `handle`. With `--no-wait`, a successful exit means the task was accepted; its result may still be pending. A detached collector gathers the reply.
|
|
140
|
+
|
|
141
|
+
### 4. Collect and review the answer
|
|
142
|
+
|
|
143
|
+
Replace the placeholder with the `request_id` returned above:
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
$requestId = "<request_id from the previous command>"
|
|
147
|
+
python "$relayScript" wait --root "$relayRoot" --request "$requestId" --timeout 300
|
|
148
|
+
python "$relayScript" inbox list --root "$relayRoot" --for "$leadAddress"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Check that the result belongs to this request and contains `RELAY_OK`. If waiting times out, keep this request ID and follow the recovery section below. Do not send the task again.
|
|
152
|
+
|
|
153
|
+
### 5. Mark the result as handled
|
|
154
|
+
|
|
155
|
+
Use the same request ID after reviewing its result:
|
|
156
|
+
|
|
157
|
+
```powershell
|
|
158
|
+
python "$relayScript" inbox ack --root "$relayRoot" --for "$leadAddress" --request "$requestId"
|
|
159
|
+
python "$relayScript" inbox list --root "$relayRoot" --for "$leadAddress"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The handled result should disappear from the pending list while its original file stays on disk. You have now checked task submission, collection, review, and acknowledgement.
|
|
163
|
+
|
|
164
|
+
</details>
|
|
165
|
+
|
|
166
|
+
## Use it on your own project
|
|
167
|
+
|
|
168
|
+
Install the relay once, then select the project you want to work on. **The relay installation folder and your working project are separate paths.** Keep `$relayScript` pointing to the installed tool, and set `$projectRoot` to your existing source folder:
|
|
169
|
+
|
|
170
|
+
```powershell
|
|
171
|
+
$projectRoot = (Resolve-Path "<path-to-your-existing-project>").Path
|
|
172
|
+
python "$relayScript" use --root "$projectRoot" --lead "$leadAddress" --workers codex
|
|
173
|
+
python "$relayScript" status --root "$projectRoot"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Open that project in your Lead app and confirm the installed `handback` skill is available. Here is an example request to give a Claude Lead; replace both paths and the module name:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
Use the handback skill for the project at <absolute-project-path>.
|
|
180
|
+
The relay script is <absolute-relay-installation>/handback.py.
|
|
181
|
+
Use claude:lead as the Lead inbox and Codex as the worker.
|
|
182
|
+
Ask one worker to review error handling in <module-path> without changing files.
|
|
183
|
+
Collect its result, review the findings, summarize them here, and ACK the result after review.
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
For terminal commands, use `--cwd "$projectRoot"` when creating a worker and `--root "$projectRoot"` for topology, status, waiting, and inbox commands. The worker works on that project. Use one worker conversation per unit of work and run units sequentially when they share a checkout. Send corrections to the same worker only after its previous request finishes.
|
|
187
|
+
|
|
188
|
+
For automatic results in a Claude conversation, have the Lead run `inbox watch` through its **Monitor** tool. A watcher in an ordinary terminal prints only to that terminal. Started with `--idle-exit 1200`, the watcher stops after 20 idle minutes; re-arm Monitor only while requests are open. If Monitor is unavailable, use explicit `wait` and `inbox list` commands. Fresh skill auto-loading and global recovery hook loading remain incompletely verified; the [detailed setup guide](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) covers these limits and the exact watcher command.
|
|
189
|
+
|
|
190
|
+
For Antigravity, register **your working project** in its app, enable its adapter, and install its relay hooks before selecting it. Follow the [Antigravity setup](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md#optional-antigravity-setup); the Codex-only test above does not configure that combination.
|
|
191
|
+
|
|
192
|
+
## Delivery and recovery
|
|
193
|
+
|
|
194
|
+
Submission, completion, Lead delivery, and ACK are separate events. An asynchronous submission returning success means the request was accepted. It does not mean the task finished.
|
|
195
|
+
|
|
196
|
+
### Result did not come back
|
|
197
|
+
|
|
198
|
+
Start with `doctor`, then `explain --request` for the saved request ID. Both are read-only; `explain` ends with one next action and never sends, collects, or ACKs:
|
|
199
|
+
|
|
200
|
+
```powershell
|
|
201
|
+
python "$relayScript" doctor --root "$projectRoot"
|
|
202
|
+
python "$relayScript" explain --root "$projectRoot" --request "<saved-request-id>"
|
|
203
|
+
python "$relayScript" wait --root "$projectRoot" --request "<saved-request-id>" --timeout 300
|
|
204
|
+
python "$relayScript" inbox list --root "$projectRoot" --for "$leadAddress"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Use the same project, Lead inbox, and state home as the original request. For the first test above, use `$relayRoot` instead of `$projectRoot`. `wait` recovers the existing request without submitting it again. Reading a result does not ACK it.
|
|
208
|
+
|
|
209
|
+
`doctor` prints OK/WARN/FAIL checks and one next step for each warning/failure (exit 5 for FAIL, 0 otherwise). `doctor --json` preserves the original JSON interface; `explain --json` provides the timeline as JSON. For an issue, copy the redacted block from `doctor --report`. `status --stats --days 30` summarizes local request outcomes, latency, additional delivery attempts, and unACKed results without telemetry. Collection timeouts, recovery via `wait`, and explicit redeliveries are not independently recorded and cannot be counted reliably.
|
|
210
|
+
|
|
211
|
+
The [detailed guide](https://github.com/Femur-0607/handback/blob/main/docs/quickstart.md) covers timeouts, replay, custom state homes, cleanup, and uninstall; the [Korean manual](https://github.com/Femur-0607/handback/blob/main/docs/usage.ko.md) describes the full command set and adapter limits.
|
|
212
|
+
|
|
213
|
+
## Optional dashboard
|
|
214
|
+
|
|
215
|
+
Run `pythonw dashboard.pyw` from the relay installation folder to see project activity, in-progress tasks, and unacknowledged results. The dashboard is optional; it is not required for delegation. `python handback.py dashboard --autostart on` starts the dashboard at Windows login, not the Lead or its Monitor.
|
|
216
|
+
|
|
217
|
+
<details>
|
|
218
|
+
<summary>Dashboard memory measurements</summary>
|
|
219
|
+
|
|
220
|
+
The optional dashboard was measured on **October 8, 2026**, using Windows, Python 3.13.15, and Tk 8.6.15. These figures describe the dashboard process, excluding the separately running agent apps.
|
|
221
|
+
|
|
222
|
+
| Check | Observed result | Conditions |
|
|
223
|
+
|---|---|---|
|
|
224
|
+
| GUI footprint | About **33 MiB working set** and **19 MiB private memory** | A fresh process with a hidden window, 5 projects, no unread results, normal 3-second refresh, and a 15-second observation |
|
|
225
|
+
| Context-menu leak fix | Menu widgets, Tcl commands, Windows GUI resources, and handles stayed constant from 100 to 500 menu openings | Real Tk widgets with native popup display suppressed; the previous menu tree and its callbacks are destroyed before replacement |
|
|
226
|
+
| Large unread inbox | About **60.3 MiB peak additional Python heap**; **2.7 seconds median per snapshot** | Snapshot only, without Tk: 1,000 unread results with 60 KiB bodies plus 1,000 completed requests; 5 timed runs |
|
|
227
|
+
|
|
228
|
+
The large-inbox figure measures Python allocations, not total process memory, and timing can vary with concurrent filesystem activity. Refreshes scan stored history and load unread message bodies; showing fewer rows does not cap that work. Usage therefore depends on the amount of stored data and the environment. These short checks do not establish a memory limit or guarantee leak-free operation over hours or days.
|
|
229
|
+
|
|
230
|
+
[Menu regression tests](https://github.com/Femur-0607/handback/blob/main/tests/test_dashboard_gui.py) cover repeated menu creation, callback cleanup, current settings, and closing the dashboard. They use hidden Tk windows and skip when Tk or a display is unavailable.
|
|
231
|
+
|
|
232
|
+
</details>
|
|
233
|
+
|
|
234
|
+
## Limitations
|
|
235
|
+
|
|
236
|
+
- Long-running Lead and reused worker conversations accumulate context; use bounded units and documented stage handoffs.
|
|
237
|
+
- Replacing the Lead preserves old requests' return addresses; explicitly read and ACK the old inbox.
|
|
238
|
+
- Windows has live verification; operation is local to one computer and OS user, with restricted agent combinations.
|
|
239
|
+
- App updates, uncertain delivery, and Monitor expiry require deliberate diagnostics and recovery; Antigravity cannot enforce read-only access.
|
|
240
|
+
- Shared-checkout work should be sequential, and dashboard scan cost grows with history. See [known limitations and workarounds](https://github.com/Femur-0607/handback/blob/main/docs/limitations.md) for details and commands.
|
|
241
|
+
|
|
242
|
+
## Development
|
|
243
|
+
|
|
244
|
+
Implementation lives in `handback/`, the CLI entry point is `handback.py`, and tests are in `tests/`.
|
|
245
|
+
|
|
246
|
+
```powershell
|
|
247
|
+
python -m unittest
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Unit tests use isolated fixtures. They do not establish compatibility with a current app build; live integration results are tracked separately in the [verification summary](https://github.com/Femur-0607/handback/blob/main/docs/verification/README.md). See [Contributing](https://github.com/Femur-0607/handback/blob/main/CONTRIBUTING.md) for test and bug-report requirements.
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
[MIT](https://github.com/Femur-0607/handback/blob/main/LICENSE). The license covers this repository's code; the agent applications are separately installed and retain their own licenses and terms.
|
|
255
|
+
|
|
256
|
+
## Migrating a previous local installation
|
|
257
|
+
|
|
258
|
+
`HANDBACK_HOME` selects the state directory. Defaults are `%USERPROFILE%\.handback`
|
|
259
|
+
on Windows, `~/Library/Application Support/handback` on macOS, and
|
|
260
|
+
`${XDG_STATE_HOME:-~/.local/state}/handback` on Linux. `AGENT_RELAY_HOME` is never
|
|
261
|
+
used as the new state setting. `handback doctor` warns about legacy state and prints
|
|
262
|
+
`handback migrate-state --from '<old-state-path>'`. Stop requests, collectors, and
|
|
263
|
+
watchers before copying. Migration verifies copied bytes, retains the original files,
|
|
264
|
+
and adds a `MOVED.json` receipt to prevent accidental writes to the old store.
|
|
265
|
+
|
|
266
|
+
Reinstall hooks and skills with `handback install-hooks` and `handback install-skills`;
|
|
267
|
+
legacy hooks are recognized and original skill files receive timestamp backups.
|
|
268
|
+
Copy a legacy `.agent-relay.json` project policy to `.handback.json`. Until then the
|
|
269
|
+
legacy policy is read with a warning; when both exist, `.handback.json` takes precedence.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Agent adapters; unverified capabilities fail explicitly."""
|
|
2
|
+
|
|
3
|
+
from .base import AdapterError, AdapterUnavailable, BaseAdapter
|
|
4
|
+
from .codex import CodexAdapter
|
|
5
|
+
from .claude import ClaudeAdapter
|
|
6
|
+
from .antigravity import AntigravityAdapter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_adapter(name, executable=None):
|
|
10
|
+
adapters = {"codex": CodexAdapter, "claude": ClaudeAdapter, "antigravity": AntigravityAdapter}
|
|
11
|
+
try:
|
|
12
|
+
return adapters[name](executable=executable)
|
|
13
|
+
except KeyError as exc:
|
|
14
|
+
raise AdapterUnavailable(f"Unknown agent: {name}") from exc
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
__all__ = ["AdapterError", "AdapterUnavailable", "BaseAdapter", "CodexAdapter", "ClaudeAdapter",
|
|
18
|
+
"AntigravityAdapter", "get_adapter"]
|