Security and allow lists
yottacode is designed to be explicit about risk. It can inspect, edit, test, and run commands in your project, so approval and path policy matter.
Folder trust
On first launch in a directory yottacode prompts:
Accessing workspace:
/home/me/my-repo
Quick safety check: is this a project you created or one you trust?
(Your own code, a well-known open-source project, or work from your team.)
If not, take a moment to review what's in this folder first.
yottacode will be able to read, edit, and execute files here.
[1] Yes, I trust this folder
[2] No, exitThe decision is recorded in ~/.yottacode/trusted-roots.json. Every subfolder of a trusted root inherits the trust automatically, so cloning a new repo under an already-trusted parent does not re-prompt.
Skip the prompt:
--allow-paths <dir>orYOTTACODE_ALLOW_PATHS=<dir>โ passing the cwd’s tree as an allow-paths root satisfies the gate session-only (no write totrusted-roots.json).YOTTACODE_TRUST_ALL=1โ CI escape hatch. Also session-only.yottacode run(non-interactive) โ trust verification is skipped entirely, matching Claude Code’s-pbehavior.--yolodoes not skip the trust gate on its own. Combine withYOTTACODE_TRUST_ALL=1for fully unattended runs.
Manage trust roots:
yottacode trust list # show every trusted root + grant timestamp
yottacode trust add [path] # default: cwd
yottacode trust remove <path> # exact-path match
yottacode trust clear # remove every entryWorktrees and trust. yottacode --worktree <name> requires the
repo root to be trusted; it refuses on an untrusted clone with a
one-line hint to run yottacode in the repo once. Worktree
directories live in user home at
~/.yottacode/worktrees/<repo-slug>/<name>/. The first-launch trust
gate inside a worktree session resolves back to the originating repo
via git rev-parse --git-common-dir, so the worktree dir itself
never needs to appear in ~/.yottacode/trusted-roots.json โ trust
on the repo flows through. An active worktree session can write
inside its own cwd normally; write validation reads cwd dynamically
so an in-session enter_worktree swap doesn’t leave the validator
locked to the pre-swap perimeter. See worktrees.md.
Sensitive projects
Folder trust governs what yottacode may write. Sensitive projects govern what leaves the machine on their own โ specifically, automatic session recall.
Everything about recall is local: embedding, storage, and cosine similarity all run against ~/.yottacode/index.sqlite. The exposure is narrower than that and easy to miss: an excerpt that gets injected travels to the cloud LLM with the turn. For a PHI/medical or otherwise regulated repository, that is not acceptable, so those repos can be quarantined:
yottacode sensitive list # show every sensitive root + marking timestamp
yottacode sensitive add [path] # default: cwd
yottacode sensitive remove <path> # exact-path match
yottacode sensitive clear # remove every entryThe marking is recorded in ~/.yottacode/sensitive-roots.json and covers every subfolder, so marking the repository root is enough regardless of which subdirectory a session started in. It takes effect on the next launch โ the posture is resolved once at startup โ and the session announces it, so you can confirm the protection is live rather than inferring it from an absence.
It cuts both ways, which is the part worth being explicit about:
- Inbound โ automatic recall is off inside a sensitive project. Nothing is swept into its prompts.
- Outbound โ a sensitive project’s conversations are never candidates for any other project’s recall, whatever
retrieval.session_recall.scopeis set to. Without this half, settingscope = "user"would quietly carry PHI into an unrelated repo’s turn โ the same leak facing the other direction.
What it deliberately does not do. Sessions are still saved, indexed, and embedded, and the manual session_recall tool still reaches them. The gate is about what leaves automatically, not about making your own history unreachable when you deliberately ask for it. It also does not touch semantic memory retrieval โ memories are things the agent chose to write down, a different trust model from an automatic sweep over raw transcripts.
Like trusted-roots.json, the store is on the agent’s deny-list, so the model cannot un-mark a project and re-enable egress for it.
Out-of-workspace writes. When the model tries to write a file outside cwd + --allow-paths roots, yottacode shows an inline elevation prompt:
Write outside workspace
Requested path:
/home/me/elsewhere/notes.md
Session workspace:
/home/me/my-repo
[1] Allow once โ trust just this file for the session
[2] Trust for session โ trust this directory and every subfolder
[3] Reject โ model sees the original error[1] and [2] are session-scoped โ they do not write to trusted-roots.json. Cross-session expansion still goes through --allow-paths or yottacode trust add.
Approval model
By default:
- read-only tools run without prompting
- mutating filesystem tools prompt
- shell commands prompt
- git read-only commands run without prompting
- git mutations prompt
- destructive flags are called out in previews
Approval prompts can be answered once or turned into a reusable allow rule. Auto-approved calls do not render boxed notice cards in the transcript; they render as one-line system messages such as โ auto ยท edit_file(...) ยท auto-mode or โ allowed by rule ยท write_file(...) ยท permissions so approval state stays visible without adding multi-line noise.
Gate precedence
Tool calls flow through layered gates in this order:
Denyrules inpermissions.jsonalways win.- Plan-mode gate (only when plan mode is active) โ blocks every mutating tool except
todo_write,exit_plan_mode, and writes to the resolved plan file. Returns a structured error to the model so it can switch to a read-only or plan-file alternative. - Yolo mode auto-allow (when
--yolowas passed at startup or/yolotoggled the overlay on) โ every tool auto-allows silently. No safety floor. - Plan-mode auto-allow โ writes to the resolved plan file are the model’s only legitimate mutation surface while planning; they auto-allow without a prompt.
- Auto-mode auto-allow (only when auto mode is active) โ non-safety-floor mutating tools auto-allow. Safety floor (
run_bash,git_commit,git_checkpoint,rollback) normally still prompts, with one carve-out:run_bashcalls whose every segment uses a verb from a built-in read-only allowlist (ls,cat,head,tail,wc,grep,rg,find,awk,cut,sort,uniq,diff,cd,pwd,which,echo,date,tree,stat,file,du,df, โฆ) AND carries no risk flag (no>redirects, no pipe-into-shell, no sudo) auto-allow under Sourceauto-mode-safe-bash. The intent: a model’s habitualcd <project> && grep โฆchain doesn’t break flow, while any mutation (rm, mv, touch, curl, go test, sed -i, โฆ) still prompts. Allowrules inpermissions.jsonskip the prompt.Askrules force a prompt even on tools that would normally auto-execute.- Tool-default policy (the tool’s own
RequiresApproval) prompts mutating tools and auto-executes read-only ones.
Deny always wins, including over yolo mode. --yolo / /yolo is “skip prompts,” not “ignore my policy.”
Trust controls separate into modes (workflow shape, mutually exclusive) and the yolo mode overlay (orthogonal, applies on top of any mode):
| Surface | Entry point | Effect |
|---|---|---|
| Plan mode | /plan ยท Shift+Tab ยท --permission-mode plan | Read-only research; gated to plan file; ends with exit_plan_mode |
| Auto mode | Shift+Tab ยท --permission-mode auto (no slash command) | Edits auto, bash/commits prompt, 4ร iteration cap |
| Yolo mode | --yolo at startup ยท /yolo mid-session toggle | Drops all prompts, no iteration cap; sits on top of any mode |
Auto mode has no slash command (intentionally off the palette and the Shift+Tab cycle so it can’t be triggered by accident). Yolo mode, also off the Shift+Tab cycle, is the lone exception with a slash toggle (/yolo): opt in via the --yolo startup flag (one-way per process โ restart without the flag to recover) or via /yolo mid-session (toggle on, then /yolo again to toggle off). The yolo banner (โ yolo mode) takes precedence visually while it’s on; when a mode (auto or plan) is also active, the mode banner picks up a โ yolo mode suffix.
No in-process sandbox
Caution
yottacode has no in-process sandbox โ run_bash, file edits, and git commands run directly on the host. For real isolation, run yottacode inside a container or devcontainer.
yottacode does not sandbox tools inside its own process. run_bash, file edits, git commands, and other tools run on the host.
run_bash is also not confined by the path deny lists that protect the structured file tools: a shell command can read ~/.ssh or write .git/hooks/ even though read_file / write_file cannot. As a partial mitigation, the run_bash approval modal flags โ in every mode โ when a command references a credential store (~/.ssh, ~/.aws, .env, โฆ) or a git hook, so cat ~/.ssh/id_rsa and > .git/hooks/pre-commit don’t render as ordinary commands. It is a prompt aid, not a boundary โ the boundary is the container.
For real isolation, run yottacode itself inside a container or devcontainer. That isolates every tool, not just shell commands.
This is a deliberate scope choice: yottacode does not ship bwrap, firejail, landlock, or pluggable sandbox backends.
Write-path validation
Mutating filesystem tools are constrained before they run:
- paths must be inside the current working directory or configured extra allow roots
- symlink writes are rejected
- yottacode app state is denied
- canonical
.gitinternals are denied .git/hooks/is deliberately allowed- in
/planmode, the only write target outside cwd is the resolved plan file at~/.yottacode/plans/<slug>.mdโ symlink rejection and the deny list still apply
Extra write roots:
export YOTTACODE_ALLOW_PATHS=/home/me/shared-configs,/home/me/other-repoRead protection
Read tools do not prompt, so yottacode blocks common secret-bearing paths from silent reads, including examples like:
~/.ssh~/.aws~/.gnupg~/.netrc~/.kube/config~/.docker/config.json<cwd>/.env<cwd>/.env.local
If you truly need to inspect a protected file, do it through an explicit shell command that prompts for approval.
Permission files
Project-local permission rules live in <repo>/.yottacode/:
Team-shared rules that can be committed:
<repo>/.yottacode/permissions.jsonRule shape
{
"permissions": {
"allow": ["Bash(go test *)", "Edit(internal/**)"],
"deny": ["Bash(rm *)"]
}
}Rules support allow, ask, and deny policy. Explicit deny rules still apply even when --yolo is set.
Creating allow and deny rules from approvals
When an approval modal appears, choose [A] always to save a derived allow rule, or [D] never to save a derived deny rule, into permissions.local.json. Either way the modal shows the exact rule before it is saved.
[A] always is suppressed for compound shell commands and obviously dangerous verbs (rm, curl, sudo, โฆ) โ those are footgun-wide to blanket-allow. [D] never is offered even for those (blocking a dangerous command permanently is exactly the point) and is scoped to run_bash and git. Because bash rules are matched per segment, a block is derived at the verb level: hitting [D] never on curl โฆ | sh saves Bash(curl *), which then refuses curl anywhere. Since deny outranks allow, a [D] block also overrides any existing allow for the same pattern.
Examples:
Bash(go test *)Edit(internal/**)Write(docs/**)Git(commit *)MCP(filesystem/read_*)โ allow filesystem MCP server’s read tools (see MCP)MCP(github/*)โ allow every tool from the GitHub MCP server
Yolo mode (the danger setting)
Warning
--yolo drops approval prompts and raises the iteration cap to a high but finite budget. Use it only in trusted automation or disposable environments โ explicit deny rules still apply, and you must restart without the flag to recover.
yottacode --yoloThis is dangerous. It skips approval prompts for matching operations and raises the iteration cap to a high but finite budget, but explicit deny rules remain enforced. Use it only in trusted automation or disposable environments. Two ways in: yottacode --yolo at startup (restart without the flag to recover), or /yolo in the TUI to toggle the overlay on or off mid-session.
Provider-hosted search allow lists
Provider-native web search can be restricted with domain filters:
export YOTTACODE_SEARCH_ALLOWED_DOMAINS=docs.example.com,github.com
export YOTTACODE_SEARCH_EXCLUDED_DOMAINS=spam.examplexAI x_search can be restricted with handle and date filters:
export YOTTACODE_X_SEARCH_ALLOWED_HANDLES=xai,openai
export YOTTACODE_X_SEARCH_EXCLUDED_HANDLES=badhandle
export YOTTACODE_X_SEARCH_FROM_DATE=2026-01-01
export YOTTACODE_X_SEARCH_TO_DATE=2026-12-31Secrets guidance
Warning
Never put secrets in prompts, USER.md, YOTTACODE.md, or any agent-managed memory file โ those are sent to your model provider. Keep API keys in environment variables, not in config.toml.
Do not put secrets in prompts, USER.md, YOTTACODE.md, or any agent-managed memory file. Those files are included in prompts sent to your configured model provider.
Keep API keys in environment variables, not in config.toml.