Running Commands Yourself
A prompt that begins with ! is not sent to the model. Heph runs it as a shell
command, shows its output in the conversation, and attaches that output to your
next message, so you can say "look at what this prints" without asking the model
to guess the command.
> !cargo test 2>&1 | tail -5
$ cargo test 2>&1 | tail -5
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured
...
> the last test above is flaky on my machine; find out why
The model receives, ahead of your prompt, the command framed as $ cmd, its
output, and its exit code, with ANSI formatting removed. Standard error is shown
in yellow unless the command supplies its own colors, and goes to the model too.
A non-zero exit shows as [exit N]; a command killed by a signal as [killed].
Waiting and cancellation
Both ! and !! select execution resources as
shell(<command>), in the original project's scope. Authorization is still
yours; there is no agent permission prompt. Contention shows immediately without
blocking input or scrolling. Esc or Ctrl-C asks before aborting a waiting or
running command. Cancellation completes after supervised cleanup.
Only one bang command runs at a time in the session. A second stays in the input until the first finishes or is cancelled.
Color and terminal behavior
Heph renders ANSI colors (including 256-color and RGB) and text attributes in
command output. Unless NO_COLOR is present in heph's environment, it requests
color with FORCE_COLOR=1, CLICOLOR_FORCE=1, CARGO_TERM_COLOR=always, and a
Git color.ui=always environment config entry. Existing Git environment config
entries are preserved. Explicit command options such as git --color=never (for
commands that accept it) can still disable color; programs that only check for a
terminal may need their own --color=always option.
Commands still run with stdout and stderr captured through pipes and no stdin, not in an interactive terminal. Git normally skips its pager in this mode; use heph's conversation scrollback for long output. An explicitly invoked pager or another interactive program is not supported yet. Cursor movement, screen clearing, titles, hyperlinks, and other terminal controls are discarded, not executed. This is styled line output, not a terminal emulator.
It is you, not the model
A ! command is yours. It goes through no permission prompt, records no tool
call, and runs outside any sandbox heph would put a model's command in. The
output is your content, in your message, exactly as if you had pasted it.
Because nothing is recorded but the output, ! is also the way to do things the
model is not allowed to: commit, push, or run something the permission patterns
deny.
Where it runs
!cmd runs in heph's worktree for the conversation, the copy the model
edits, because the conversation is about what the model built there and you
usually want to show the model something about it. !!cmd runs in your own tree
instead.
[input] bang_runs_in = "tree" swaps the two: ! in your tree, !! in the
worktree.
You can run !ls immediately after opening a new session, before sending a
prompt. If the selected worktree does not exist yet, heph prepares it in the
background before running the command. Existing worktrees are left untouched.
This starts neither a model turn nor a naming request, and never falls back to
running the command in your checkout.
For a repository, a fresh worktree contains committed files from the
conversation's branch or base. If no base has been selected yet, heph previews
[git] base_branch, or the first offered branch (current branch first,
otherwise the most recently committed local branch before remote-tracking
branches). This does not settle the base; the first model turn still uses normal
base selection. Uncommitted checkout files are not imported. Projects without a
repository or without commits use the usual project observation instead. A
resumed conversation's missing worktree is restored from its recorded snapshot,
or its base if the turn never ended.
Setup errors appear in command output with exit code 125, without spawning the shell. Cancellation during setup waits for preparation to finish and prevents the command from starting. Commands targeting your own tree need no private worktree setup. Edits you make in the private tree before the first model turn are carried into that turn for review.
What it is good for
-
Running the tests yourself before asking the model to look at a failure:
!cargo test -p heph-shadow 2>&1 | tail -30 -
Showing the model the actual state of something it would otherwise have to ask permission to inspect:
!git log --oneline -5,!ls -la target/ -
Checking the model's work in the worktree before review opens, since the worktree is where it runs by default.
Output accumulates: several ! commands before one prompt all ride along with
it, in order. Sending the prompt clears them.