Files and folders
OAR keeps everything it owns in one folder, the state folder: the config file, the database with your conversations, the logs and the uploaded files. This page says where that folder is, what is in it, which parts you can delete, which hold secrets and what the relay removes by itself. Some data is not in the state folder at all: each provider keeps its own session data and logins in its own folders.
The state folder #
| Install | State folder |
|---|---|
Installer or npm install -g, macOS, Linux and WSL |
~/. |
Installer or npm install -g, Windows |
%APPDATA%\ |
Global install with OAR_ set |
the folder it names |
| Git checkout | inside the checkout: server/, server/, server/, server/ |
npm install -g and oar update replace the package but never touch the
state folder. OAR_ has to be set in every shell where you run
oar, or the command looks in the default folder; see
Environment variables. oar doctor
prints the paths in use: the state folder, the config file, the database and
its size. The same paths are listed for each install in
Install.
Three environment variables move single parts: COPILOT_ the
config file, COPILOT_ the data folder (database, lock and
uploads) and COPILOT_ the log folder. In config. the
key data moves the data folder too; the environment variable wins. A
relative data counts from the folder of config..
Added in 0.9.14 Uploads follow the data folder too: <data.
Uploads that earlier versions left in server/, or that a migration
copied into the state folder's uploads/, are still read there in place.
Added in 0.9.14 A global install's relay runs on the state folder's data
folder however it is started: oar start, the Linux service, both Windows
autostart modes and a plain gh copilot with OAR's extension. A data in
config. that an earlier autostart relay used is copied from once and
left as it is.
Before 0.9.14: Windows autostart and gh copilot
Up to 0.9.13 the two Windows autostart entries, and the relay a plain
gh copilot started, set only the config file (gh copilot not even that).
A relay they started kept its database, lock file, uploads and logs in
server\, server\ and server\ inside the installed package
folder, which npm install -g and oar update replace. The update to 0.9.14
copies that data before npm removes it; see the
upgrade note.
On macOS and Linux the relay makes the data folder readable by you only (mode 700), and the config file and the database files owner-only (mode 600).
Moving an old install #
Before the project was renamed, state lived in a git checkout's server/
folder, and the config file and logs of a checkout's launcher in
~/. ($XDG_ when that is set;
Windows: %LOCALAPPDATA%\). A global install copies the config
file and logs of that folder into the state folder once, with its first
oar setup or oar copilot. oar start does not migrate. To import the state
of a checkout, which includes its database:
oar setup --migrate-from /home/dev/projects/old-oar
The folder is the checkout itself, not its server/ folder. What happens:
- It copies the database (with its
-waland-shmfiles), the config file, the Cursor agent stores that were indata/(only when there was a database), theuploadsfolder and thelogsfolder when that is 50 MB or smaller. - It never changes the source. Delete the old folder yourself when you are satisfied.
- It refuses while a relay still runs from the source, and says so.
- It checks the copy before it counts: the database must pass SQLite's integrity check and hold the same number of conversations and messages. If not, it removes what it copied, Added in 0.9.14 no longer the whole state folder, and leaves a message.
- Added in 0.9.14 It never overwrites. A
config.already in the state folder is kept. The empty database an installer's relay created is moved intojson backups/(stop the relay first:oar stop); a database with conversations makes it refuse and say what to do instead. While it copies a database it holds the relay's lock, so no relay starts on it meanwhile. - It writes a receipt to
backups/and a marker fileMIGRATION. md .in the state folder.migrated
After the installer Added in 0.9.14
The marker is written only after a real copy, and a folder you name with
--migrate- is always migrated, with a line saying what was copied or why
nothing was. So the option also works after an installer has run oar setup.
The same folder a second time only says it is already migrated. Before 0.9.14
the first oar setup or oar copilot wrote the marker even with nothing to
import, and a later --migrate- did nothing without a word.
Added in 0.9.14 Migrated uploads land in data/, where the relay reads
them, and the Cursor agent stores in data/, which the relay
reads by default. Uploads an earlier migration left in the state folder's
uploads/ are merged into data/ at the next relay start; nothing is
overwritten or deleted. Symlinked folders in the checkout are copied as real
folders.
What is inside #
Paths are relative to the state folder. "Safe to delete" means the relay works afterwards; it says nothing about what you lose.
| Path | What it holds | Safe to delete? |
|---|---|---|
config. |
Port, access, the access token, timers and optional tunnels and previews. See config.json | Stop the relay first. oar setup writes a new one with a new token, which signs every device out. Tunnel settings in it are lost |
data/ |
The database: your conversations and settings. See The database | No: this is your history. Back it up first |
data/, data/ |
The database's write-ahead log and its index, present while the relay runs | Never alone. Delete them only together with copilot. |
data/ |
One file per uploaded or pasted attachment, named by its SHA-256 hash, so the same file is stored once. A <sha256>.<pid>.<number>. file exists while an upload is written |
Not by hand: the database refers to these files, and a conversation that used one shows a missing attachment. The relay removes unused ones, see Retention |
data/ |
The one-relay-per-folder lock, see One relay per data folder | Only when no relay runs |
data/ |
Added in 0.9.14 One folder per Cursor conversation: its agent's state. See Outside the state folder | Not while you use Cursor: a conversation without its store gets a new agent |
data/ |
Added in 0.9.17 The Claude Code state of DeepSeek chats: transcripts and session folders under projects/, what each Claude Code process leaves (sessions/, session-, shell-), Claude Code's own settings, and oar-, the relay's record of each Claude Code start, which a delete uses to find the right shell snapshots. No Claude login. Readable by you only (mode 700 on macOS and Linux). Deleting a DeepSeek conversation removes its part, see Retention |
Not while you use DeepSeek chats: their Claude Code sessions are here. The worker creates the folder again when it starts |
data/ |
Added in 0.9.19 Heap snapshots (*.) the relay writes when its heap nears its limit, see The relay ran out of memory. Readable by you only (mode 700 on macOS and Linux). A snapshot holds the access token and the API keys |
Yes. The relay never deletes snapshots: delete each one once it has been read |
data/ |
Added in 0.9.14 The data an earlier version kept inside the package, copied there by the update before npm removed it. The relay takes it over at its next start | Once the relay has brought it over ([data] Brought over the database … in relay-) |
backups/<time>/ |
Added in 0.9.14 A database the relay replaced with a newer one it brought over; also the empty database a migration moved aside | Once you are sure you do not need it |
data/ |
The port and token the running relay started with, kept between an oar setup that changed them and the restart that applies them. Removed by itself |
Yes |
logs/, logs/ |
What oar start or oar copilot printed when it started the relay itself, standard output and errors. Only written when oar starts the relay itself; the service and a relay run in a terminal do not write them |
Yes. They never rotate and grow |
logs/ |
A copy of the relay's console with a time stamp per line, written by every relay | Yes |
logs/ |
Output of one session worker, see Logs | Yes |
logs/ |
The tool configuration of one session. It holds no secrets | Yes. The relay writes a new one when the session's worker starts |
logs/, logs/ |
Written by the Copilot extension engine's extension | Yes |
npm/ |
The OAR package, when the installer put it here because npm's global folder needed root | Not while you use this install. It is the program |
runtime/ |
OAR's own Node.js, when the machine had none new enough | Not while oar runs on it |
logs/ |
Added in 0.9.15 npm's outcome after oar uninstall, and any hidden . folder npm left behind. With --purge it goes to the system's temp folder instead |
Yes |
oar-, oar- (Windows) |
The launcher the boot task runs, and the task definition OAR registers. See Autostart | Not while the relay starts at boot. oar autostart off removes both |
*., *., <task>. (Windows) |
Added in 0.9.15 Copies of hand-made autostart entries that oar autostart --replace replaced, and of the tasks a failed switch put back: a launcher, a Startup entry, a task's exported XML (schtasks / takes it back). Copies of entries OAR generated go once a switch has worked |
Yes, once you do not want the entry back |
backups/, . |
The receipt and marker of a migration | The receipt: yes. The marker: leave it, or the automatic migration from the earlier config folder could run again |
Outside the state folder, the installer's oar launcher is in
~/. (only in the cases where it installs into ~/.),
and the Linux service is ~/.. Removing them
is described in Removing OAR.
Added in 0.9.15 oar uninstall removes the service and the package and
leaves the state folder as it is; oar uninstall --purge deletes it, after
you type delete.
A git checkout keeps the same files in server/. Generated images are not in
the state folder, see Outside the state folder.
The database #
The database is one SQLite file, copilot.. The relay creates it on first
start. It holds what you would call your data:
- conversations and their messages, with the transcript, attachments' index and pinned messages
- the message queue, queued and waiting messages, and questions an agent asked
- the relay's settings that you change in the web UI (the app-wide switches, provider settings, retention choice, update preferences, the model lists)
- the OpenAI, Cursor and Added in 0.9.17 DeepSeek API keys, if you entered them
- paired relays and their tokens, and the subscriptions that watch sessions on this and on paired relays
- the web-push subscriptions of your devices and the relay's push keys
- shared-conversation links
- sub-agent and workflow records, activity and thoughts per conversation
- the index of uploaded files and which messages use them
- usage snapshots for the plan meters (Check Usage), and Added in 0.9.17 what the DeepSeek card counts: the tokens and searches of DeepSeek turns per model and per day, the last totals each DeepSeek session reported, and the balance readings its bar is measured against
- image chats: their operations and the links between generated images
- preview cards
Migrations run by themselves every time the relay starts. They create what is missing and add columns, and running them again changes nothing. You do not run them and cannot skip them.
Backing up #
OAR has no backup command. The database runs in SQLite's write-ahead mode, so
recent changes can sit in the -wal file next to it. To back it up:
- Stop the relay with
oar stop. - Copy
copilot.and, if they exist,db copilot.anddb- wal copilot.together.db- shm - Start the relay again.
To restore, stop the relay and put the copied files back as they were. Do not
copy copilot. alone while the relay runs, and do not mix a database file
with the -wal file of another copy. A backup contains your API keys and
tokens, see Where secrets live; keep it as private as the state
folder.
Logs #
| File | Written by | Rotation |
|---|---|---|
relay- |
the relay, always | At 5 MB the file becomes relay-, the older ones shift to . and ., and the oldest is dropped. Lines show your access token as [token]. OAR_ switches the file off |
server., server- |
the shell of oar start or oar copilot, when it starts the relay in the background |
none |
worker-<session>. |
each Node session worker (Claude, Claude Cloud, Cursor, Grok, Added in 0.9.17 DeepSeek and the Copilot SDK engine), appended across worker restarts | At each launch a file over 10 MB becomes worker-<session>., replacing the previous one. Files of deleted conversations stay |
ext- |
the extension of the Copilot extension engine | none |
The Copilot extension engine has no worker log: it is the Copilot CLI's own terminal. A relay run as a systemd service also writes to the journal, see Start the relay automatically.
A git checkout started with npm start keeps its logs in server/. One
started with oar start or oar copilot keeps them in
~/. (Windows: %LOCALAPPDATA%\),
unless COPILOT_ names another folder.
Where secrets live #
| Secret | Where it is stored |
|---|---|
| The access token | config., in plain text. Treat the file, copies of it and the sign-in address (?token=) like a password. A browser holds it as a sign-in cookie for 30 days. The relay's lock file keeps only a hash of it |
The previous access token, between oar setup and the restart |
data/, in plain text, readable by you only; removed by itself |
| A Cloudflare tunnel token (managed tunnel) | config., key cloudflared, or the environment variable COPILOT_ |
| OpenAI API key | The database. The panel never shows it again and it is not sent to browsers |
| Cursor API key | The database, the same way |
| DeepSeek API key | Added in 0.9.17 The database, the same way (setting deepseek_). The relay sends it only to the DeepSeek base URL, and hands it only to the workers of DeepSeek chats. See DeepSeek |
| A paired relay's token | The database. Never sent to browsers or agents. A pairing that uses this relay's own token stores none |
| Shared-conversation link tokens | The database |
| Web-push keys and device subscriptions | The database |
| Heap snapshots | Added in 0.9.19 data/: everything that was in the relay's memory, the access token and the API keys included. Never share one as it is. See The relay ran out of memory |
| Claude login | The Claude CLI's own folder on the relay's machine: ~/., or the folder in CLAUDE_. The relay stores none. Claude Cloud reads the same login and keeps it in memory. DeepSeek chats do not use it |
| Grok login | The Grok CLI's own folder: ~/. |
| GitHub Copilot login | The Copilot CLI's own login on the relay's machine |
While a worker starts under tmux, the relay writes its provider key (the
OpenAI, Cursor or Added in 0.9.17 DeepSeek key, or a CLAUDE_
from the relay's environment for a Claude Cloud or, Added in 0.9.17, a Claude
worker) to a temporary file in the system's temp folder, readable by you
only. The worker's shell reads it once and deletes it. Each worker gets only
its own provider's key.
Retention #
The relay removes these by itself. Nothing else is deleted unless you delete a conversation.
| What | Rule |
|---|---|
| Unused uploads | A file that no message or draft refers to is removed once it is older than 24 hours. The check runs when the relay starts and every 6 hours. There is no setting. Deleting a conversation also removes the files only it used |
| Sub-agent records | The tool inputs and results of finished sub-agents are removed after Keep sub-agent tool output days, in Settings → General: 7, 14, 30 or 90 days, or Always. The default is 90. Thoughts, replies, notes and the one-line summary of each call stay. The check runs 30 seconds after start, once a day and 5 seconds after you change the setting. The database file does not shrink; SQLite reuses the freed space |
| Relay events for watching sessions | Events the watching conversation has been given are removed after 2 hours. A subscription that ended is removed after 7 days. Details in Watching sessions. The sweep runs every 10 minutes |
| Events a paired relay has not fetched | Per subscription the newest 500 are kept, none older than 7 days, and a subscription nobody fetched for 7 days ends. Questions and errors are dropped last. See Remote relays |
relay- |
Rotates at 5 MB and keeps three older files, see Logs |
worker-<session>. |
Moves to . over 10 MB at launch. Nothing removes the logs of deleted conversations |
| Generated images | Never by age. Deleting the conversation deletes its images |
| The lock file | Removed when the relay stops. After a crash, the next start replaces it, see One relay per data folder |
Deleting a conversation removes its messages, queue entries, questions and
sub-agent records from the database, and the Claude transcript and the
generated images belonging to it. Added in 0.9.17 For a DeepSeek
conversation it also removes, in data/, the transcript, the
session's folders, what its stopped Claude Code left (its registration, hook
environment and shell snapshot) and the project folder once no other session
uses it, and from the database the last totals its sessions reported. What
it added to the DeepSeek card's totals and days stays. What each provider
keeps itself is in the next section.
Outside the state folder #
| What | Where |
|---|---|
| Claude transcripts and session folders | Under projects in the Claude configuration folder (~/., or CLAUDE_). Deleting a conversation deletes its transcript. See Claude. Added in 0.9.17 DeepSeek chats keep theirs in the data folder instead: data/ above |
| GitHub Copilot session state | ~/., or the folder in COPILOT_ |
| Pictures from OpenAI Image chats | In the Copilot session-state folder, in <session>/ under the conversation. See OpenAI |
| Cursor agent stores | Added in 0.9.14 One folder per conversation, in cursor- in the relay's data folder (~/., %APPDATA%\), or in the folder named by CURSOR_. In the state folder on a global install; listed here because earlier versions kept them elsewhere. See Cursor |
| The Grok CLI and its login | ~/. |
| The Copilot extension wrapper | ~/., written by oar copilot, or oar copilot --install-. Added in 0.9.15 oar uninstall removes it when it is the one OAR wrote for this install |
| Claude Cloud | Nothing on disk. A cloud session runs at Anthropic; its results come back as pushed branches |
| Temporary files | The short-lived provider-key file above, in the system's temp folder |
Before 0.9.14 the Cursor stores sat in server/ inside the
package folder by default, which an update replaces, so a conversation could
lose its stored agent and get a new one (see
Cursor). A conversation whose store is
still at that old place keeps using it there, and one with a store in both
places uses the one changed last; nothing is moved or deleted.
Your agents' work, the files in your project folders, is outside OAR's storage entirely.
One relay per data folder #
The relay creates relay- in the data folder when it starts and
removes it when it stops. The file holds the relay's process number, a hash of
its token and its start time.
If a second relay starts on the same data folder while the first one runs, the second one prints one line and exits, Added in 0.9.14 with code 78 (code 1 before), which the Linux service does not retry:
Relay already running (pid=4242, startedAt=2026-01-05T09:12:40.000Z; lock /home/dev/.oar/data/relay-server.lock). It is held by relay process 4242: oar stop, or end process 4242.
Relay appears to be owned by another live process instead of Relay already running means the running relay has another token. When the holder cannot be
told to be a relay, the hint reads If no relay is running, end process 4242 or delete the lock. oar start prints the same hint after The relay did not come up. The first relay is not touched. Messages stay pending when the relay
you expected is not the one that runs; oar doctor shows the config and
database in use.
After a crash or a power loss the lock file is left behind. Added in 0.9.14 A
lock from before the last boot, or whose process number now belongs to a
process started after it, is stale: the next start moves it aside, logs
Recovered stale singleton lock, and takes the lock over. This no longer goes
by the clock, so a clock step does not make a running relay look gone, and two
starts recovering the same lock do not both run. A lock that cannot be read
(an empty one a power loss left) is read again and counts as held unless its
time is more than 10 seconds off. oar start no longer removes a lock this
version wrote; it still removes one of an earlier version when nothing answers
on the relay's port.
Two relays can run side by side when they have separate data folders and
ports. See The oar command for how oar
finds the relay, and Restarts and resume
for what a restart keeps.