How Many Tokens Does Success Cost?
I'm setting up a new system and a new set of workflows, which means rebuilding some of my old scripts. One of them is hush.
Want your own copy? The requirements are at the bottom, ready to give to your agent.
About ten months ago, over the Christmas holiday break, I read Dexter Horthy's article on context-efficient backpressure. I think it was the first time I'd come across Dex or HumanLayer.
That article inspired hush: a tiny script that swallows a command's output when it succeeds. I use it for tests, builds and lints. It's a core part of my tooling now, and I'm pretty sure I've used it every day since.
I wrote about the principle behind it in Success Is Silent, and about backpressure in These Aren't New Principles.
How Hush Works
I put hush in front of a command:
❯ hush npm testEvery command returns an exit code when it finishes. 0 means it was successful, and anything else means it failed. If the tests pass and the command returns 0, hush swallows the output and prints nothing. If the command fails, I get all of it.
For example, when an agent runs the tests and they pass, the exit code is all it needs. The hundreds of lines proving it clog up the context window and burn tokens.
Rebuilding Hush
Today I rebuilt it. I knew the old version had problems with signals, so that's what I wanted to fix. The new version handles timeouts and cancellation much more gracefully.
I'd also noticed it couldn't handle a command that stops to wait for input. An agent running in the background can't provide input, so now hush fails with a message telling the agent it doesn't work with interactive commands.
Once those changes were done, I asked the agent how hush could improve itself, and kept going round that loop. It found a few more holes with signals, and fixed them too.
The new version is completely vibe-coded, and I think this is where vibe coding is perfect. I haven't read every line, and I don't intend to. hush simply prefixes a command, so it's easy for me to just test it from the outside: I give it a command, and check whether there's output, or not.
It doesn't need anything like automated testing, either. I'll make small changes, and if I find a problem, I'll prompt the agent to fix it.
Counting What It Swallows
I want to know how many tokens hush saves.
My background agents run in a sandbox, with hush mounted as a read-only file. The sandbox sets an environment variable that my host doesn't have, and that's the flag that enables the counting. If the variable's there, hush logs how many bytes it swallowed. So the counting only happens when a workflow runs autonomously.
Every job through my workflow engine already produces a report. That report now reads the log, divides the bytes by 4, and adds the number of tokens hush saved.
Why divide by 4? A token is roughly 4 characters of English, and most characters in a log are a single byte. So bytes ÷ 4 gives a rough token count. It's not exact, but it's close enough for me.
I already count the tokens each ticket uses. I'm looking forward to seeing the tokens hush saved as a percentage of the total it took to implement the ticket.
That percentage won't tell the whole story, though. Every time an agent talks to the model, it sends the whole conversation again. Output that hush swallowed never joins the conversation, so it's never sent again on the turns after it. The total will automatically be lower because of hush, so we can't use it as a before/after comparison.
Still, some metrics are better than no metrics.
The numbers aren't in yet. My new setup is only just running, so I'll give it a few weeks.
Build Your Own
My script is tiny, and it uses tools I have installed on my machine. I had to install some of them in the sandbox to make it work there too.
Instead of sharing the code, I've asked my agent to articulate what hush does as a set of requirements.
I think this is one of the best things about sharing ideas in software engineering right now. I can describe the requirements, and your agent can build a tool tailored to your own system. How good is that?
Give these requirements to your agent, and it'll build a hush for your machine, using whatever you've already got installed.
Build a command-line tool called hush for this machine. It runs a command, prints nothing if the command succeeds, and prints all of its output if it fails.
Requirements:
Core- hush <command> [args...] runs the command with its arguments exactly as given.- Success (exit 0): print nothing. The exit code is the report.- Failure: print all output, complete and not truncated, with no header or footer.- Capture stdout and stderr into one stream and keep the original line order.- Keep the exact exit code (127 not found, 126, 128+N signal, etc.).- No arguments: usage on stderr, exit 2.- No limit on output size (buffer to a file).- Main rule: any result that is not "success" is the same as running without hush.
Input- stdin passes through: pipe, file and terminal.
Interruption- Ctrl-C / SIGINT, SIGTERM, SIGHUP: stop the whole command tree, dump the output so far, then exit by the same signal (130/143/129).- Works when the signal goes to the process group or only to the hush pid. This includes an agent harness that stops a task.- No orphan processes after a signal.- SIGKILL: output is lost (cannot fix), but no temp file stays.
Terminal / job control- Ctrl-Z suspends hush and the command. fg resumes both. Exit code and output stay correct.- A stop from another tool (SIGSTOP): hush stops with the command and resumes with it.- Interactive command: fail loudly, do not hang. Dump the output, give a clear message with the copyable command ("hush does not work with interactive commands"), stop the command, exit 128+TTIN.- Give that message only for a real TTIN/TTOU stop, not for a command that only exits 149.
Resources- Delete the temp file immediately after you open it, so nothing stays on disk.- The command does not inherit hush's internal file descriptors.- Set the signal traps before the command starts.- No extra processes on the normal path.
Out of scope- Success message, truncation, colour/TTY, separate stdout and stderr in the dump.- Pipelines (use hush sh -c 'a | b'), shell functions and aliases.Once it's built and tested (and you're comfortable with it), you can move it to a directory on your path and make it executable:
❯ chmod +x hush