::the working folder
Saturn works in the folder you launch it from, the way a coding agent works in a repo. The file tools, the shell, /undo, /init, and the folder's SATURN.md all work there. Launched from ~, your home folder is the workspace. The tools can't reach anything outside it on their own: /add-dir <folder> makes another folder reachable for the session, and /rm-dir takes it away. Writes and shell commands there still face the gate.
/add-dir ~/Desktop reach ~/Desktop for this session
/add-dir list the working folder and every added folder
/rm-dir ~/Desktop stop reaching it::standing instructions
~/.saturn/SATURN.md loads every turn: your tone, your rules ("always metric", "never draft to my boss without asking"). A SATURN.md in the working folder adds that folder's own instructions, and wins where the two conflict. /init surveys the working folder and drafts one. /init --force redrafts it. SATURN_HOME moves ~/.saturn.
::hooks
~/.saturn/hooks.yaml runs your own shell commands at four moments: turn-start, turn-end, before-write, and after-write. Each command gets the details in its environment (SATURN_QUERY, SATURN_ANSWER, SATURN_FILE, SATURN_TOOL, …) and as JSON on stdin. A before-write hook that exits non-zero blocks the write, and the answer says so. A mistake in the file is named at startup instead of silently skipped.
turn-end:
- command: ~/bin/log-answer.sh
timeout: 5
before-write:
- ~/bin/refuse-outside-drafts.sh # a non-zero exit blocks the write
after-write:
- git -C ~/notes add -AHooks are your commands, so they run without the gate and aren't the agent's egress. That's why the file tools refuse to write hooks.yaml.
::memory
Memory is one markdown file in six layers, persisted across sessions and yours to grep and edit. remember stores a fact and recall reads facts back. A fact you state yourself is kept without a prompt (below); any other remember asks first.
user
who you are, your preferences and constraints. Loaded every turn.
commitments
open items with a due date. Loaded every turn.
memo
dated notes. The last five load every turn.
agent
what Saturn learned about this machine. Loaded when it matches the request.
entities
the people, projects, places, and shorthand in your life. Loaded when it matches.
negative
what not to do again. Loaded when it matches.
Everything loads under one cap (memory.context_cap, 4,000 characters), and the block names any fact that didn't fit instead of silently dropping it. Every fact carries its provenance: who said it (you, or inferred), the run it came from, and when it was last used. Each fact reaches the model with the day it was saved: when two disagree the later one wins, and what you say in the conversation outranks both.
what you tell it
Say "I'm vegetarian", "Petra is my manager", or "never book anything before 10am" and Saturn keeps it with no approval prompt, then says so after the answer: remembered #12: … — you said it · /memory remove 12 undoes it. That happens only when the fact's words come from one sentence you typed and stated (a question doesn't count, and a "not" has to stay where you put it), and nothing from outside (a web page, mail, a file, an attachment) has entered the conversation. Once something has, every later fact asks, until /clear. Otherwise the prompt appears and says why. The check proves you typed the words, not that the fact means what you meant, so read the line after the answer. /memory marks these facts said. memory.auto_learn: false turns it off, and saturn -p / -q never do it.
- –A rule you give ("never…", "from now on…") is filed where it loads every turn.
- –A new fact names the stored one it may contradict, after the answer, at the prompt, and on
/memory add:similar: #3 "I live in Paris" — /memory remove 3 if that is no longer true. Nothing is removed for you. - –A recognisable secret (a card number, a Social Security number, a password, a PIN, an API key, a private key) is refused wherever a fact is written, and Saturn says why. It's a net for the common shapes, not a guarantee.
first run
Right after the first launch picks your model, Saturn offers three quick questions: what to call you, what you do, and anything it should never do. Enter starts them, n skips, and the offer is made once. Each answer is saved straight to memory in your words, with no model call, so the next answer already knows you. A "never…" answer becomes one rule per ;, filed where rules load every turn. An answer that looks like a password or a card number is refused and asked again.
/memory setup asks those three and two more: the people you mention most, and what you want help with. It shows your current answers: Enter keeps one, a new answer replaces it, and people and rules are added to. /memory marks these facts setup. An install that already has memories gets one line about /memory setup instead of the offer.
learning goes through review
Everything else Saturn learns waits for your accept. During a session it queues candidates: your mid-task corrections, gate denials, the compaction summary, and the model's own proposals from your words and its answers (never a tool result directly; memory.review_llm: false turns these off). A proposal from a conversation outside content entered says so. /memory review shows each one as a diff line and keeps it only on your y. The review also runs at /quit when anything is pending.
/memory every fact, grouped by layer, with its #id
/memory list <layer> one layer
/memory add <fact> save a fact (--layer, --replaces <n>, --sens <mark>)
/memory edit <n> <text> rewrite fact n in place
/memory remove <n> delete fact n
/memory setup the first-run questions, plus two more
/memory why <n> provenance: who said it, the run it came from, last use
/memory review accept or skip the queued candidates (--no-llm skips the model's proposals)
/memory stale facts unmatched for memory.stale_days (flagged, never auto-deleted)--replaces <n> retires the old fact so a correction never sits beside it. --sens <mark> marks a fact sensitive: it's withheld from any prompt bound for a remote inference host.
::documents (rag)
Ingest PDF, text, markdown, HTML, CSV, and Word (.docx) files into a local knowledge base the agent searches with search_knowledge_base. Every launch syncs the documents folder on its own. Embeddings come from the tier's embedder (qwen3-embedding:8b), which the first /docs add offers to pull. Retrieved passages pass through the injection quarantine.
You can also just ask. "Add notes.md to my knowledge base" copies the file in and embeds it, searchable straight away; "remove notes.md from my knowledge base" moves the knowledge base's copy to the Trash. Both always ask first, whatever /policy says, because a document's text reaches the model on every later search that matches it. The prompt warns when the file holds text that reads like instructions. Only a file in a folder Saturn can reach can be added, and headless runs refuse both. "What's in my knowledge base?" lists the documents.
/docs list the ingested documents
/docs add <path> copy a file into the knowledge base and embed it
/docs remove <name>
/docs rebuild re-embed everythingTo read a single PDF or Word file, you don't need the knowledge base: read_file and @file read them directly. The tuning knobs (rag.chunk_size, rag.chunk_overlap, rag.k) live in config.yaml, and a chunking change re-embeds on the next sync.
::undo
Every write, edit, move, and delete is snapshotted first. /undo reverts the file changes of the last turn that wrote anything: a created file is deleted, an edited one restored, a moved or trashed one moved back. Each /undo steps one turn further back, and /undo list shows what can be reverted. Shell effects aren't undoable, and the conversation isn't rewound.
::sessions
Conversations autosave after every turn and on /quit. /resume continues the last one; /resume save [name] names one, /resume list lists them, and /resume <name> restores one. Sessions are plain .json files under database/sessions/. Long histories compact on their own once the context window fills past runtime.compact_threshold. /clear starts fresh without touching memory, documents, or the trace.