Data Storage Ownership¶
Narnia reads from databases and directories owned by the GitHub Copilot CLI and writes only to storage it owns itself. Keeping that boundary explicit is what makes Narnia safe to run beside a live Copilot installation.
| Store | Owner | Narnia's access | Default location |
|---|---|---|---|
session-store.db |
GitHub Copilot CLI | Read, and write existing columns | ~/.copilot/session-store.db |
session-state/ |
GitHub Copilot CLI | Read | ~/.copilot/session-state/ |
installed-plugins/ |
GitHub Copilot CLI | Read | ~/.copilot/installed-plugins/ |
settings.db |
Narnia | Full ownership, including schema | <LocalAppData>/narnia/settings.db |
All paths are configurable through NarniaOptions. See
Configuration for the environment variables.
The Copilot-owned session store¶
session-store.db is created and written by an external process — the Copilot CLI itself. Its
schema is defined and maintained by that tool, not by this repository.
Narnia does not change that schema. Adding, removing, or renaming a column, table, or index would break compatibility with the CLI that owns the file and can corrupt session data that users cannot regenerate. Reading from, and writing to, columns that already exist is fine.
The decision and its consequences are recorded in ADR-0001.
Overrides never hide recorded values¶
Narnia lets a user override values the CLI recorded — a session name, a repository, a branch. Those overrides live in Narnia's own database and leave the session store untouched.
Because the underlying value still exists, the UI must never silently replace it. Any surface
that displays an overridden value also displays the original session-store value, so the user
can always see what the CLI actually recorded and tell the difference between Narnia's
presentation and Copilot's data.
Narnia's own settings database¶
settings.db holds everything Narnia itself records: overrides, favorites, session groups, work
collections, settings, recorded terminal windows, storage metadata, scheduled-job catalog
entries, and session-migration history.
It lives in a dedicated per-app folder under the platform's local application data directory —
%LOCALAPPDATA%\narnia\settings.db on Windows, and the XDG or ~/Library/Application Support
equivalent elsewhere, resolved through Environment.SpecialFolder.LocalApplicationData.
Why not ~/.copilot¶
~/.copilot belongs to the Copilot CLI. Its documentation reserves plugin-writable data for
${COPILOT_PLUGIN_DATA}, so a plugin that drops its own database beside the CLI's is writing
into someone else's directory.
A dedicated app-data folder matches what comparable tools do — the GitHub CLI, VS Code, and the
platformdirs/env-paths conventions all use a per-app directory — and it is already where
Narnia keeps web-server.json, its scheduled-job wrappers and logs, its recovery packets, and
its published app/. Keeping the settings database there makes the read-only boundary around
~/.copilot complete rather than almost complete.
This is recorded in ADR-0002.
Relocation from the legacy path¶
Earlier versions stored this database at ~/.copilot/narnia-settings.db. SettingsDatabaseRelocator
runs on startup, before migrations, and acts only when the current location is absent and a
legacy file is present.
The relocation is deliberately non-destructive. It copies the legacy database and its
-wal/-shm sidecars to the new location, then retires the legacy file by renaming it to a
timestamped .bak. Legacy bytes are never deleted, so an interrupted or failed relocation
always leaves a recoverable copy behind. The only files the relocator deletes are partial copies
it just wrote to the destination.
It is also best-effort and never fatal. If the legacy file is momentarily locked — an older server still shutting down, for example — it is left in place and the relocation is retried on a later launch.
Schema migrations¶
Narnia migrates its own database with DbUp, via the
dbup-sqlite package pinned in Directory.Packages.props.
- Migration scripts live in
src/NexusLabs.Narnia.Core/Repositories/Migrations/and are embedded into the Core assembly by anEmbeddedResourceitem inNexusLabs.Narnia.Core.csproj. - Scripts are named
NNNN_description.sql, for example0001_initial.sql. DbUp orders them by name, so the numeric prefix is what determines execution order. NarniaSettingsDbMigratorruns every pending script on startup. DbUp records which scripts it has already executed and runs only new ones.
To add a migration, create the next numbered file in that folder. Nothing else needs to be registered.
Applied scripts are effectively immutable. Editing one that has already run on a user's machine does not re-run it — DbUp has recorded it as executed — so the change silently never reaches existing installations. Correct an applied migration by adding a new script.
DbUp API notes¶
The dbup-sqlite 6.x API differs from what older samples and much of the search-result
literature show:
- The namespace is
DbUp.Sqlite, notDbUp.SQLite. - The builder method is
.SqliteDatabase(connectionString)onDeployChanges.To. - SQLite creates the database file on first connection but not its parent directory.
NarniaSettingsDbMigratorcreates the directory first; a migrator that does not will fail on a clean machine.