Concepts
Workspace and Schema Model
Check which database a repository uses and where its data rules are stored.
Repository identity selects the database
Silo reads the repository's selection from silo.json in the common Git
directory, usually .git/silo.json. It uses that selection to find a database
in your machine's application-data directory, outside the repository.
The selection can be:
auto: useoriginwhen present, otherwise the repository's local identitydetached: use a persistent local UUID- A named remote: use the identity derived from that remote's current URL
For example, git@github.com:acme/project.git and
https://github.com/acme/project.git select the same database on one machine.
Different repository paths select different databases, even if their files
are identical.
Linked worktrees share this selection and local UUID. Clones do not copy them because the file is Git metadata, not a tracked file. Clones with matching remote identities can still select the same database on the same machine.
Do not edit the file by hand. Silo writes it atomically and stops on invalid contents rather than silently selecting a new database.
Check the mapping rather than guessing it:
silo status
The output shows:
- The Git workspace root
- The selection and resulting identity
- The local database path
- Whether a database exists there
Important
In auto mode, adding origin moves an existing unsynchronized detached database only when the origin identity has no database. If both databases exist, Silo stops and requires an explicit selection.
Select or move a Silo
Use a named Git remote when this repository should select the identity derived from that remote's current URL:
silo switch origin
silo status
The first command changes only repository-local selection. The status output
then shows remote:origin and the selected database, which may be absent.
Select the persistent repository-local identity instead:
silo switch --detach
silo status
Restore the default behavior after an explicit selection with
silo switch --auto. Automatic selection uses origin when it exists and the
detached identity otherwise.
Add --move when you want to carry the current database to that identity:
silo switch origin --move
silo status
A move requires:
- An existing source database
- No database at the destination
- Synchronization not yet configured
Silo locks both locations, verifies a copy under the new identity, and installs it before removing the old local file. A synchronized database cannot move because its remote checkpoint records the existing identity.
Changing a selected remote's URL changes the identity derived from that remote;
it does not infer that the previous database should move. To carry an
unsynchronized database across an origin URL change, stage it through the
detached identity. Replace the example remote URL with the new URL for your
repository:
silo switch --detach --move
git remote set-url origin git@github.com:acme/renamed-project.git
silo switch origin --move
silo status
The final status reports the normalized identity for the new URL. This workflow does not apply to synchronized databases, whose remote checkpoints retain the existing identity.
SILO_DATA_HOME overrides the base application-data location. Silo appends
silo/ to that path. For example, /data/silo-work becomes
/data/silo-work/silo/.
Keep active databases on local storage. Use synchronization to share checkpoints through object storage; do not put the active database on a network drive or in a cloud-synchronized folder.
The schema has two layers
The logical schema stores the table definitions and information that SQLite DDL alone does not describe:
- Semantic types and comments
- Named relationships between tables
- Policies for writes
- Imported templates and their agent instructions
- The schema revision
Silo compiles the enforceable parts into generated SQLite objects, such as
STRICT tables, checks, indexes, foreign keys, and triggers. A named semantic
relation describes an existing foreign key; it does not create one.
Read the logical schema to understand the data. Do not edit generated SQLite objects directly; they are Silo's implementation of the stored rules.
Use the layer that answers the question:
| Need | Command | Why |
|---|---|---|
| Understand domain meaning and policies | silo schema show or silo table show <table> |
Reads authoritative logical metadata. |
| Inspect semantic relationships | silo relation list or silo relation show <table> <name> |
Reads named relations and derived cardinality. |
| Copy or inspect the portable contract | silo schema export |
Emits the canonical logical schema as JSON. |
| Diagnose generated SQLite objects | silo schema ddl |
Shows compiled DDL without replacing semantic metadata. |
| Join, aggregate, or filter stored rows | silo sql '<query>' |
Opens a read-only SQLite connection. |
Whenever Silo opens a database, it checks the generated SQLite objects against the logical schema. Unexpected changes to a managed table, index, or trigger cause a schema mismatch error.
Enforcement has boundaries
SQLite enforces column types and constraints, along with policies implemented by triggers. Silo commands also:
- Convert accepted inputs to the type's stored form
- Generate IDs and timestamps
- Check revisions before updates
- Restrict which fields an upsert can replace
A direct SQLite writer bypasses those command checks. Existing SQLite constraints and triggers still apply unless that writer changes or disables them. Neither layer is a tamper-proof audit system.
A long-running reader can use the mutation journal to
notice changes made through Silo. Direct external commits can be reported as
unknown changes through SQLite's data_version; they do not receive reliable
table or row attribution.