Skip to content

Repository files navigation

JobBox

Time is money. Your agent spends both, standing still.

A five-minute build runs. The agent waits. You wait. Nothing else happens — and you are billed for all of it twice: your hour, and the tokens burning in a session doing nothing.

No single wait is worth stopping for. It is their sum that costs, and the sum is invisible until something counts it.

$ jbx gain
jbx gain — last 30d

  commands wrapped         142
  of those, detached        11  (7.7% of them)
  they took              3h04m
  you stood still       35m12s
  given back             2h29m  ███████████████████░░░░░  81.0%

project  calls  detached  elapsed  waited  saved        impact
acme     142    11        3h04m    35m12s  2h29m (81%)  ████████████████████████
  api    96     7         2h11m    18m03s  1h53m (86%)  ██████████████████░░░░░░
  front  34     4         39m      3m17s   36m (92%)    ██████░░░░░░░░░░░░░░░░░░
  *self  12     0         14m      13m52s  8.0s (1%)    ░░░░░░░░░░░░░░░░░░░░░░░░

last hour       6 calls ·    1 detached ·   8m12s saved (73%)
last day       38 calls ·    4 detached ·  40m05s saved (77%)
last week     142 calls ·   11 detached ·   2h29m saved (81%)
last month    142 calls ·   11 detached ·   2h29m saved (81%)

That is one week. Put your own rate on it.


JobBox wraps every command your agent runs. The quick ones come back untouched — output as written, exit code unchanged, as though nothing were there. The slow ones detach themselves, say so, and tell whoever needs to know when they end.

Nobody judges in advance which is which. That judgement is the thing everybody gets wrong, so JobBox does not make it: it runs the line and finds out.

JobBox is the project; jbx is the command. One binary — Rust, serde_json and yaml-rust2, nothing else. Linux, macOS, Windows.

Five agent CLIs

$ jbx hook --list
claude   Bash                 PreToolUse   ~/.claude/settings.json
gemini   run_shell_command    BeforeTool   ~/.gemini/settings.json
droid    Execute              PreToolUse   declare by hand
cursor   Shell                preToolUse   declare by hand  (no unasked endings)
copilot  bash                 preToolUse   declare by hand

They agree on almost nothing — not the name of the shell tool, not the event, not the shape of the answer, not the file it is declared in. jbx init handles the first two; the rest take one block of JSON, and CLI-AI.md has the exact block for each, along with the two it deliberately does not support and why.

Install

$ curl -fsSL https://raw.githubusercontent.com/quazardous/jobbox/main/install.sh | sh

It checks the download against the sums published with the release, puts it on your PATH, and asks before declaring its hooks — they go in a settings file other tools share. On Windows, irm https://raw.githubusercontent.com/quazardous/jobbox/main/install.ps1 | iex, and WINDOWS.md has the rest. No script at all: cargo install --git https://github.com/quazardous/jobbox, then jbx init — that builds main, and --tag builds a release. On Claude Code, jbx init also places the skills /jbx, /jbx-after and /jbx-slots.

Or, on Claude Code, the plugin — one or the other, not both, since each brings the same skills under its own names. It declares the announcing hooks as well — the ones that make an ending report itself unasked — along with the background watch:

$ claude plugin marketplace add quazardous/jobbox
$ claude plugin install jbx@jobbox

The plugin does not carry the binary, and the order above is the reason. A marketplace installs from the repository, and binaries do not live in a repository; the release archives carry them, a git checkout does not. So the plugin uses the jbx you already have, and says so plainly if there is none.

Run jbx init as well if you have rtk. A plugin declares hooks; it cannot displace somebody else's, and two hooks rewriting one field is a race no harness documents. init settles that by calling rtk itself.

What it looks like

a long command taken off the agent's hands

Nothing changes — until something is slow:

$ npm run build
> building…
jbx: this passed 30s, so it is in the BACKGROUND as j7f3a91c — nothing lost.
DO NOT WAIT FOR IT, DO SOMETHING ELSE.

  jbx help j7f3a91c

The build output arrived as it was written, not replayed at the end.

The ending reaches you two ways, and one is better. Left alone, it is announced on the next turn — free, and it costs that delay. Handed to Monitor, it arrives the moment it happens: jbx wait <id> ends exactly when the job does, so whatever is watching is woken then. jbx watch does that for every job at once, one line each.

The message does not hand over that command, on purpose. Saying "do not wait" and then offering the line that waits is a contradiction, and an agent resolves it the easy way. jbx help <id> lists it, one step further away — and allow_wait: false takes the foreground use away entirely, for a project where the habit has already set in.

That is the difference between waiting and being told. Polling is neither — it is waiting with extra steps.

The one judgement left to make

The old answer to "when should this go to the background?" was a document telling an agent to estimate how long a command would take. Agents get that wrong, and so do people. jbx removes the question and leaves a smaller one:

Do you need this result before you can do anything else?

Almost always, no. When the answer is yes, say so — jbx fg -- '<line>' runs without ever letting go, and jbx gain counts what that cost.

The rest

  • USAGE.md — every verb, every setting, how saved is counted and why it is a ceiling, and what was deliberately left out.
  • CLI-AI.md — every agent CLI jbx answers, what to paste where, and the two it leaves alone.
  • MACOS.md — why the install command never trips Gatekeeper, and what to do if you downloaded by hand.
  • WINDOWS.md — Smart App Control, which shell runs your commands, and the two things that differ there.
  • TROUBLESHOOTING.md — why nothing is detaching, which is usually on purpose.
  • MIGRATING.md — what each jobbox command became, and the one rename that goes wrong without a word.
  • CONTRIBUTING.md — what belongs in a test, and what has already been ruled out.
  • CODE-SIGNING-POLICY.md — who may release this, what it never sends anywhere, and how to undo everything it does.
  • CHANGELOG.md — what changed, and why it mattered.

The demo

Made with simai-cli, from demo/detach.txt.

License

MIT — see LICENSE.

About

Every command your agent runs is wrapped; the slow ones put themselves in the BACKGROUND and tell you when they end. `jbx stats` says how much time that saved. One Rust binary — Linux, macOS, Windows.

Resources

Contributing

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages