Interactive Mode (REPL)
Interactive mode is the default when you run yoyo in a terminal. It gives you a read-eval-print loop where you can have a multi-turn conversation with the agent.
Starting
yoyo
# or
cargo run
The prompt
The prompt shows your current git branch (if you're in a git repo):
main π βΊ _
If you're not in a git repo, you get a plain prompt:
π βΊ _
Line editing & history
yoyo uses rustyline for a full readline experience:
- Arrow keys: Navigate within the current line (β β) and through command history (β β)
- Inline hints: As you type a slash command, a dimmed suggestion appears after the cursor showing the completion and a short description β e.g. typing
/heshowslp β Show help for commands. Press Tab or β to accept. - Tab completion: Type
/and press Tab to see available slash commands with descriptions β each command is shown alongside a short summary of what it does. Partial matches work too β/he<Tab>suggests/helpand/health. After typing a command + space, argument-aware completions kick in:/model <Tab>β suggests known model names (Claude, GPT, Gemini, etc.)/provider <Tab>β suggests known provider names (anthropic, openai, google, etc.)/think <Tab>β suggests thinking levels (off, minimal, low, medium, high)/git <Tab>β suggests git subcommands (status, log, add, diff, branch, stash)/pr <Tab>β suggests PR subcommands (list, view, diff, comment, create, checkout)/save <Tab>and/load <Tab>β suggest.jsonsession files in the current directory- File paths also complete β type
src/ma<Tab>to getsrc/main.rs, orCargo<Tab>to getCargo.toml. Directories complete with a trailing/for easy continued navigation.
- History recall: Previous inputs are saved across sessions
- Keyboard shortcuts: Ctrl-A (start of line), Ctrl-E (end of line), Ctrl-K (kill to end), Ctrl-W (delete word back)
- History file: Stored at
$XDG_DATA_HOME/yoyo/history(defaults to~/.local/share/yoyo/history)
How it works
- You type a message
- yoyo sends it to the LLM along with conversation history
- The LLM may call tools (read files, run commands, etc.)
- Tool results are streamed back β you see each tool as it executes
- The final text response is printed
- Token usage and cost are shown after each turn
Auto-continue
If the model stops mid-work (e.g., it says "Next, I'll fix the tests..." but stops), yoyo automatically sends a follow-up prompt to continue. You'll see:
β‘ auto-continuing (1/3 β response appears incomplete)...
This happens up to 3 times per user turn. Auto-continue won't fire if:
- The model encountered an error
- The session budget is exhausted
- The response doesn't show clear signs of being incomplete
Turn-end marker
When a turn actually did work (it changed at least one file), yoyo prints one dim line to stderr saying why it believes it stopped. It's a stated belief, not ground truth β but a stated one can be argued with:
β done β nothing queued
βΈ stopped with no summary β type "continue" if this looks unfinished
βΈ auto-continue budget spent (3/3) β type "continue" to resume
- done β nothing pending, no error, and the turn closed with a real summary.
- stopped β the turn hit an error, still has queued follow-up work, or went
quiet right after tool activity without wrapping up. Send
continueif the work looks unfinished. - budget spent β auto-continue used all its attempts while work was still queued.
The marker is only informational β it never changes what yoyo does. It's
suppressed for plain conversational replies (no file changes), silent under
--quiet, and prints glyph-free wording under --screen-reader.
Seeing the raw stop state (--verbose)
The marker is a verdict, and a verdict you can't audit is worth less than the
signals behind it. Run with --verbose (or -v) and yoyo prints the raw inputs
its classifier consumed, immediately above the verdict:
turn state: queue=0 tools=yes error=no continues=0/5 final_text=412ch -> done
Facts only β no glyphs, no advice, plain ASCII (so it reads identically under
--screen-reader). Unlike the marker itself, this line prints on every turn
that ends, including turns the verdict stays silent about, so you can judge the
stop state yourself instead of trusting the classifier.
Acting on silence (--continue-on-silence)
The marker tells you a turn went quiet after doing work. This flag makes yoyo act on it:
yoyo --continue-on-silence
With the flag on, auto-continue also fires when all of these hold:
- the turn used tools (it did work),
- the final text is empty or near-empty (under 20 characters, trimmed),
- the follow-up queue is empty, and
- the turn ended without an error.
A turn that used no tools and returned nothing is not continued β that's a model declining to speak, not work left on the table.
Why it's off by default. yoyo can't distinguish "stopped mid-work" from
"finished quietly" β some providers legitimately end a tool-using turn with no
closing prose. Turning this on for everyone would make those providers loop.
The worst case is bounded, not infinite: the existing auto-continue budget (5
per prompt, max_auto_continues in config) still applies, so a quiet-finishing
provider costs you up to 5 extra turns of wasted tokens per prompt β annoying,
not runaway. If your provider chats normally at the end of a turn, you'll never
notice the flag; if it goes silent mid-task, this is the knob.
With the flag off, behaviour is exactly what it was before the flag existed
(pinned by a default-off invariance test in src/repl.rs).
Shell passthrough
Prefix a line with ! to run a shell command directly β no API call, no tokens, no confirmation prompt:
π βΊ !git status
π βΊ !ls -la src/
Output streams live to your terminal (via sh -c on Unix, cmd /C on Windows), and the exit code is shown only when non-zero. A bare ! prints a usage hint.
!? β ask about the last command's output
! commands never enter the conversation, but sometimes you want yoyo to look at what just happened. Type !? to feed the last ! command β its command line, exit code, and output tail (last ~200 lines / 8KB, captured as a tee while it streamed) β into the conversation:
π βΊ !cargo test
... (output streams live) ...
exit 101
command failed (exit 101) β type !? to ask yoyo about the output
π βΊ !? why did the second test fail
- Bare
!?uses a default question: after a failure, "explain what went wrong and how to fix it"; after a success, "summarize this output". !? <question>asks your own question about the output.- Works after successful commands too (the failure hint just doesn't appear).
- If no
!command has run yet,!?prints a one-liner and does nothing. - The capture is non-consuming β you can ask
!?follow-ups about the same output more than once.
This is fully opt-in: nothing enters the conversation (and no tokens are spent) unless you type !?.
Tool output
When yoyo uses tools, you'll see status indicators:
βΆ $ cargo test β (2.1s)
βΆ read src/main.rs β (42ms)
βΆ edit src/lib.rs β (15ms)
βΆ $ cargo test β (1.8s)
βmeans the tool succeededβmeans the tool returned an error- The duration shows how long the tool took
Token usage
After each response, you'll see a compact token summary:
β³ 3.2s Β· 1523β842 tokens Β· $0.0234
Use --verbose (or -v) for the full breakdown including session totals and cache info.
This shows:
- Wall-clock time for the response
- Inputβoutput tokens for this turn
- Estimated cost for this turn
Interrupting
Press Ctrl+C to cancel the current response. The agent will stop and you can type a new prompt. Press Ctrl+C again to exit.
Completion notifications
When a prompt takes more than a few seconds, yoyo rings the terminal bell so you notice the finish even if you switched windows (disable with no_bell = true or --no-bell).
For an actionable desktop alert, set the opt-in notify_command config key β a shell command yoyo runs (fire-and-forget) whenever a long prompt finishes, at the same threshold as the bell:
# .yoyo.toml β Linux
notify_command = "notify-send 'yoyo' 'done'"
# macOS
notify_command = "osascript -e 'display notification \"done\" with title \"yoyo\"'"
Or set it from inside the REPL:
/config set notify_command notify-send 'yoyo' 'done'
Details:
- Opt-in and inert by default β when the key is absent (or empty), nothing is spawned and no tools are probed.
- Runs via
sh -con Unix andcmd /Con Windows, fully detached: yoyo never waits on it and its output is discarded, so it can never block the REPL. - The command receives two environment variables so one script can serve multiple purposes:
YOYO_EVENT=prompt_completedandYOYO_ELAPSED_SECS=<seconds>. - If the command fails to spawn, yoyo stays silent by default (one-line warning with
--verbose). - Setting it to an empty string clears it:
/config set notify_command "".
Inline @file mentions
You can reference files directly in your prompts using @path syntax. The file content is automatically read and injected into the conversation β no need for a separate /add command.
> explain @src/main.rs
β added src/main.rs (250 lines)
(1 file inlined from @mentions)
> refactor @src/cli.rs:50-100
β added src/cli.rs (lines 50-100) (51 lines)
(1 file inlined from @mentions)
> compare @Cargo.toml and @README.md
β added Cargo.toml (35 lines)
β added README.md (120 lines)
(2 files inlined from @mentions)
How it works:
@pathβ injects the entire file@path:start-endβ injects a specific line range- If the path doesn't exist, the
@mentionis left as-is (it might be a username) - Email-like patterns (
user@example.com) are not treated as file mentions - Images work too:
@screenshot.pnginlines the image into the conversation