Docs / Operate
Where state lives
ivralo keeps its state in three places: your PostgreSQL, a few files in the ivralo home, and a .ivralo/ folder inside the workspace. This page says what is where, and what to back up.
PostgreSQL
Everything conversational is in PostgreSQL, in a schema of its own, ivralo (IVRALO_PG_SCHEMA renames it). The tables are created on first use.
| What | Holds |
|---|---|
| Sessions | Each conversation, its title, and which one a terminal is on |
| Runs | Every run in full: the prompt, every tool call with its arguments and output, the reply |
| Memories | Long-term memory about you, used across sessions |
| Knowledge index | The chunks of your documents with their vectors (pgvector), and a record of what is indexed |
| Jobs | Each job: its state, its lease, its question and its log |
Nothing conversational is written to local disk, so pointing a second machine at the same database brings back the same conversations. Two files in the workspace do carry a request's text: a plan file holds its plan, and a change record holds the turn's first line as its title.
Compaction (/compact, ivralo compact) folds older runs into a summary and hides them from the model. It deletes nothing; the runs stay in the database. ivralo memory list, forget and clear manage long-term memory.
The database comes from Docker Compose, a URL you give, or a cluster ivralo makes under the home. See PostgreSQL.
The ivralo home
The home is the folder ivralo's own configuration lives in (IVRALO_HOME). It holds files, not conversations:
| File | Holds |
|---|---|
.env | Settings: the model, the database, integrations. Owner-only. |
permissions.json | Shell policy and tool approvals for every workspace |
trusted.json | The folders a person trusted, or declined |
mcp.json | MCP servers |
schedules.json | Schedules |
databases.json, identifiers.json | Named databases; identifiers to mask in incident evidence |
skills.local/ | Skills you installed or wrote, and assignments.json |
brand.json | Colours for the documents ivralo writes |
api-token | The local API's token, owner-only, written by the first ivralo serve |
gitconfig | ivralo's own git identity, written by ivralo init --server |
google-token.json | The Google token, after ivralo google login |
pg/ | The PostgreSQL cluster, when ivralo made one |
worktrees/ | The git worktrees of parallel coders, one folder per workspace |
The Python worker's code can write none of these. See Settings files for their formats.
The workspace's .ivralo/ folder
Inside the workspace ivralo keeps a .ivralo/ folder. In a repository it is added to .git/info/exclude, so none of it ends up in a commit. ivralo's file tools never list, search or index it.
| Path | Holds |
|---|---|
history/ | A file's previous version, kept before each overwrite |
changes/ | One record per turn that changed files: which files, when, which run |
plans/ | Plan files, with each step's verdict |
index/index.sqlite | The code index: a cache of what the language server and git say |
changesets/ | Each changeset's record, and its staged copy outside a repository |
cassettes/ | Cassettes and their blobs |
incidents/ | Each investigation's report.md, report.json and digest.json, and mask.json, the workspace's table of masked identifiers |
schedules/ | Each schedule's run logs and task.log |
traces/, exports/ | Files written by trace --html and export |
spill/ | Tool answers too long for the model's context, read back in ranges |
python-worker.log | The Python worker's own errors |
permissions.json, databases.json, identifiers.json, .env | This workspace's own settings. In a folder nobody trusted, only the permission file's denials apply. |
Spill files stay at most seven days, and at most the newest 64 are kept. Change records and cassettes are never pruned.
Alert investigations write their evidence stubs to alerts/ at the workspace root, outside .ivralo/, because an investigation reads them like any other bundle.
File history and restore
Before an existing workspace file is overwritten, by an edit, by Python, by a shell command that names it, by a restore or a landed changeset, it is copied to .ivralo/history/. The newest 10 versions of each file are kept (IVRALO_HISTORY_KEEP); IVRALO_HISTORY=false turns it off.
ivralo history app/main.py
ivralo restore app/main.py
ivralo restore app/main.py --at 20261002-1015
ivralo history with no file lists every file that has versions. ivralo restore brings back the newest version, or the one --at names by its stamp or the start of it. The current file is kept first, so a restore can itself be undone. /history and /restore do the same in the session.
History is a safety net for the common case, not a backup. What the write guard cannot see, such as a file removed or moved by code, history cannot see either. In a repository, git is the real undo.
Backups
Back up two things:
- The database. It holds every conversation, run, memory, job and the knowledge index. For a cluster ivralo made,
ivralo doctorprints the exactpg_dumpline for it. For Docker Compose or your own server, usepg_dumpagainst the URL in.env. - The home.
.env,permissions.json,trusted.json,mcp.json,schedules.json,skills.local/and the rest are small files. Keep their owner-only permissions when you copy them.
The workspace's .ivralo/ folder can be lost without losing a conversation. Back up incidents/ if you keep investigation reports nowhere else; its mask.json is what ivralo why reads a masked placeholder back with.