Skip to content

Use cases

The same flags combine into quite different setups. A few common ones:

Run an agent, ask about the rest (default)

$ hallpass -- copilot

The project, a private $TMPDIR, the usual devices and the terminal are writable; every other write pauses the agent and asks you. Add --allow-path for the agent's own state, so it is not asked about at each start:

$ hallpass --allow-path ~/.copilot --allow-path ~/.cache/copilot -- copilot

Just audit: allow everything, log it

$ hallpass --prompt=allow --log=writes.jsonl -- make install

Nothing is ever asked or denied, except the always-denied paths (--deny-path, ~/.config/hallpass and the hallpass binary). Each write is logged with the reason audit when it would have been asked, policy when the rules allow it anyway:

{"time":"...","pid":60083,"exe":"/usr/bin/dash","syscall":"openat","path":"/home/me/elsewhere","decision":"allow","reason":"audit"}

List what would have been asked: jq -r 'select(.reason=="audit") | .path' writes.jsonl | sort -u. Add --no-implicit (below) to log the project's writes too.

Check a tool against the paths it declares

A tool, for example an MCP tool provider, declares where it writes. Check that it writes nowhere else:

$ hallpass --no-implicit --allow-path ~/.cache/mytool --allow-path /dev/null --log=writes.jsonl -- mytool

With --no-implicit, only the --allow-path paths are writable: not the working directory, not a $TMPDIR, not /dev/null. Any other write is an undeclared one: asked about, or, combined with --prompt=deny or --prompt=allow, denied or allowed, and logged.

The terminal is off too. Pass --allow-tty to keep the session's own terminal writable, since its /dev/pts/N cannot be known in advance.

Unattended: deny what is not allowed

$ hallpass --prompt=deny --log=writes.jsonl -- ./ci-step.sh

Nobody is there to answer: writes outside the policy fail with EACCES, and the log says which.

Commands that leave processes behind

Daemons, language servers, nohup jobs and MCP servers can outlive the command that started them. hallpass supervises them while it runs. To keep supervising them after the command exits, until the last one exits:

$ hallpass --wait=all --log=writes.jsonl -- ./start-services.sh

Press Ctrl-] then s, or send SIGTERM, to stop early. Needs Linux 5.9.

Answer from elsewhere

When the agent owns the whole screen, or runs without a terminal:

$ hallpass --prompt=answer -- copilot     # in one terminal
$ hallpass answer                      # in another

Or --prompt=desktop for desktop notifications. See over ssh.

Code you don't trust

Lite mode is about honest mistakes: a deliberately malicious process can race its checks. Strict mode enforces the answers in the kernel on the real file:

$ hallpass --mode=strict -- copilot

It asks just like lite mode. See strict mode for the requirements, and limitations for what neither mode covers yet.