Repository navigation
Days 219–234. Two defaults changed, and you should know both before upgrading. With no config, yoyo now runs claude-opus-5-5 (was claude-opus-4-6), and in an interactive terminal read_file, search and list_files now ask before reading outside the directory you launched in. Those are why this is a minor bump. The rest of the span is fences that actually hold (--deny-dir at symlink targets, in startup loaders and in recursive search results; /cd honouring the new directory's deny lists), named pipes that no longer hang a session, and ~25 more shell subcommands that stop exiting 0 when they failed.
Changed (defaults you will notice)
- Outside-read fence on by default at a terminal — provisional. In an interactive session,
read_file,searchandlist_filesask before reaching outside the launch directory; a yes to aread_filecovers that file's directory (not its subdirectories) for the rest of the session, and a no refuses only that call. Piped and scripted runs (no terminal on stdin) are unchanged: the fence stays off there.YOYO_ASK_OUTSIDE_READS=0turns it off everywhere;=1turns it on everywhere (with no terminal it refuses instead of asking). The fence anchors on the launch directory, not the live cwd, and fails closed if the cwd is unreadable (#879). This default is provisional: I asked @yuanhao in Discussion #1048 whether it should be on at a terminal or opt-in, and it shipped before he answered. If the answer is opt-in, this default will be reverted. - No-config default model is
claude-opus-5-5(was the supersededclaude-opus-4-6): it has its own preset (1M window), is priced in yoagent's bundled table, and its default request fits the output maximum.--helpnow derives the default instead of restating it.--provider openaiwith no model defaults togpt-6-solinstead ofgpt-5(#1037). - A malformed
.yoyo.tomlis refused. An unterminated quote or unclosed[header now stops agent entry points (REPL,-p, piped,yoyo review) with one error naming file:line and the fix, exit 2, before any provider call. Before, the stray quote went into the value (e.g. a model id that 404s) with exit 0 (#1034, #1036). - yoagent 0.24.1 → 0.25.10 (#996, #1007, #1039 and semver patch bumps). 0.24.2 is a security release: a
searchpattern starting with-(e.g.--pre=<cmd>, which made ripgrep run a command) is searched as a literal. Sub-agent bash now kills its whole process group on timeout or cancel; on Unix the terminal's Ctrl+C reaches a sub-agent's command through the run's cancel instead of directly. Model prices are opt-in upstream and yoyo enables yoagent's bundled table itself, so/costreads the same preset prices. - A single prompt is no longer silently stopped at 1,000,000 cumulative tokens or after 10 minutes of wall clock (inherited yoagent defaults); it is bounded by
--max-turns(default 200) and loop detection (#999). Sub-agents keep yoagent's caps. - An MCP stdio server whose tool names collide with a builtin (e.g.
@modelcontextprotocol/server-filesystemonread_file/write_file) is now connected with its tools renamed<prefix>__<tool>instead of being skipped (#1041).
Security
--allow-dirsymlink escapes closed, and a dangling-symlink--allow-dir/--deny-direntry resolves the same way before and after its target is created (#996, #998).--deny-dir/--allow-dirare honoured at the resolved target by everything that feeds the provider before turn one: project instruction files (CLAUDE.md, AGENTS.md, …),.yoyo/goal.md,.yoyo/memory.json, the repo map, and a skills dir symlinked into a denied folder; and by@pathmentions,/add,/explainand--image(#1002).--safe-modenow also skips.yoyo/goal.mdand says so on stderr.--deny-dirnow fences the results of a recursivesearch/list_files, not just its path argument (#1022). A ripgrep config file (RIPGREP_CONFIG_PATH) can no longer change what a fenced search returns, and the "(N matches)" footer counts only what the fence let through (#1023).permissions.denychecks every command segment with leading assignments stripped, and refuses an indirect command word (X=rm; $X -rf ~,eval) when a deny list exists (#1010).- After
/cd: the new directory's[directories]deny and allow narrow the file-tool fence (for@-mentions,/add,/explain,--image,/rename, auto-attached context, the repo map's fence check and/spawn's instruction loader too); the launch project's[permissions] allowno longer auto-approves commands in the new directory, and its hooks stop firing there (restored on/cdback);/permissionsshows the/cd-appended deny entries;/cdback home no longer re-appends or re-announces the launch deny list, nor warns that its own.yoyo.tomlis not applied; and/cdinto a trusted dir no longer claims its MCP servers, allow and hooks "are live here" (none of them load; reloading is #1040) (#869, #1032, #1042). /contextand/doctorlist instruction files through the same fence the loader uses (#1043).
Added
--no-hintsflag andhints = falseconfig key turn off the contextual REPL hints (Discussion #420).retry_after_partial = true(config key, default off): a transient error after text has streamed to a pipe retries instead of ending the run, at the cost of a duplicated partial on stdout (#997)./todolists are saved with the session and restored on resume (#682).- Claude Haiku 5.5, Sonnet 5.5 and Opus 5.5 / Fable 5.1 get their own preset windows and prices (before, several were billed as an older sibling);
/costprices Haiku 5.5 prompts above its context tier at the tier rate;/model inforeads the context window from the preset. GPT-6 Astra/Sol/Luna and gpt-6.1-sol, gemini-4-argon, gemini-3.8-flash, grok-4.7 and mistral-large-4 use yoagent's priced presets instead of generic defaults (#1003, #1021, #1037). - An OpenAI-compatible model id with no preset says it is running on guessed limits (128K window,
max_tokens4096) (#1019, #1020: no false "declared output ceiling" warning where no preset declares one).
Fixed
- Pipes and signals.
-pinterrupted by Ctrl+C exits 130 with(interrupted)on stderr (#993).-pto a pipe uses yoagent's retry-safe events, so a mid-stream retry that succeeds prints one answer and exits 0 (#991). Held text is flushed on SIGTERM (#1015), SIGHUP (exit 129), SIGQUIT (exit 131), a panic, and an event stream that closes mid-attempt (#1016).yoyo -pexits promptly when a backgrounded grandchild of the bash tool keeps the output pipe open (#1049). A reply cut off at the output-token limit now says so on stderr. - Named pipes no longer hang.
read_file,/add, the write_file diff preview, and startup reads of instruction files,.yoyo.toml,.yoyo/goal.md,.yoyo/memory.json,system_file, the--continuesession file and the trusted-dirs store refuse or skip a FIFO/device with a warning instead of blocking (#1047, #1052).yoyo config get/showno longer hang either. - A read failure is no longer an empty file to write over.
/config set,/todo boardevidence and the trusted-dirs store used to treat an unreadable file (e.g. invalid UTF-8) as empty and overwrite it; now only a missing file starts empty, and anything else is an error that leaves the file untouched (#1053). - Shell subcommands that fail now exit nonzero (#982 slices):
yoyo lint(linter's own code) andyoyo health(1 when any check failed);diff/blameoutside a git repo or on a bad rev or missing file;commitwhen nothing was committed;grepwhen the path is missing or unreadable (instead of "No matches found.");findwhen a directory in the walk could not be read;mapon a missing path;index <path>(it reported the cwd);config showwhen the config can't be read; usage errors and unknown verbs intree,undo,def,outline, baregrep/blame/docs/watch/ast,risk,skill,goal,todo,config,lint; refusals that need an interactive session; and stray arguments tostatus,version,memories,permissions,security,evolution,init(which no longer writes YOYO.md on a typo),doctor,update,help(yoyo help <command>prints that topic) andhealthexit 2. #982 stays open. - Quoted arguments mean what you typed (#1008, #1009):
yoyo commit "two words"commits without literal quotes;yoyo run "echo a b"runs the command line;yoyo findrefuses extra positional args instead of folding them into the pattern;yoyo blameandyoyo mapfind a path with a space. yoyo setupwith non-terminal stdin refuses (exit 2, writes nothing) instead of writing.yoyo.tomland claiming "Starting yoyo..." (#1024).- A bad numeric value in
.yoyo.toml(max_tokens,temperature,max_turns,context_window), a typo'dcost_warn_usd/--cost-warn/YOYO_COST_WARN_USD, and a badmax_auto_continueswarn on stderr instead of silently using the default or disabling the feature (#1028, #1030). edit_fileon a CRLF file: a multi-lineold_textwritten with\nmatches, and the file keeps its CRLF endings.StreamingBashToolkills the whole process group on timeout/cancel, not justbash.- A sub-agent cancelled by Ctrl+C is reported as cancelled, not as a failure, and is no longer re-run on the fallback model.
- Streamed markdown no longer shows
##heading markers or leaks**after a list or quote marker; output streamed in pieces matches the same text rendered whole (#1029). --print-system-promptno longer demands an API key.yoyo --versionon a crates.io install shows the published commit (from.cargo_vcs_info.json), neverdev(#994); local builds rerun build.rs on new commits so the hash is not stale (#995).
Price table audit
price_drift_audit(DeepSeek rows): passed, 3 rows compared.- General sweep (run 2026-10-20):
price audit: SUMMARY compared 115, matched 29, drifted 73, cache_read_only 13, unpriced 66 of 181 catalogue rows (rel_tol 1%). The 73 drifted rows are UNRECONCILED and owned by #1012 (75 on 2026-10-11, so 2 fewer; the table was not edited in this release). By provider: Google 24, OpenAI 20, Z.ai 13, Mistral 9, xAI 6, DeepSeek 1./costfigures for those models may be wrong. The 13cache_read_onlyrows are the known unmodelled-cache gap.