# Data Layout

Where KuraDB keeps its files on disk and the structure of each database's SQLite table.

## Directory Tree

```text
~/.config/kuradb/
├── db.json            registry: [{"db": "<name>", "createAt": "<RFC 3339 UTC>"}]
├── config.json        port and remote settings
├── endpoint           daemon URL, present while the HTTP server runs
├── runtime.uid        {"uid", "pid", "started_at"} of the running daemon
├── daemon.log         daemon output, appended
└── <name>/
    ├── inbox/         watched folder; drop files here
    ├── data.db        SQLite database (WAL mode, plus -wal and -shm files)
    └── record.json    watcher snapshot of the inbox tree
~/Kura_<name>          symlink to ~/.config/kuradb/<name>/inbox
```

`~/Kura_<name>` is recreated on every daemon start if it is missing or points elsewhere; if a non-symlink file sits at that path, the database is skipped with a warning.

## file_data Table

Every database has one table, created by `internal/database/schema/file_data.sql`:

| Column | Type | Meaning |
|---|---|---|
| `id` | `INTEGER PRIMARY KEY` | Row id; second ranking key in search |
| `source` | `TEXT NOT NULL` | Absolute file path inside the inbox |
| `chunk` | `INTEGER NOT NULL` | 1-based chunk number within the file |
| `total` | `INTEGER NOT NULL` | Chunk count of the file at write time |
| `content` | `TEXT NOT NULL` | Chunk text |
| `dismiss` | `BOOLEAN NOT NULL DEFAULT FALSE` | `TRUE` once the chunk was replaced or its file removed |
| `created_at`, `updated_at` | `TIMESTAMP` | Set to `CURRENT_TIMESTAMP` on insert and update |

`(source, chunk)` is unique, and `idx_file_data_source` indexes `source`.

## SQLite Connections

Each `data.db` is opened through `go-sqlkit` with one write connection and a read pool of 8. Both use WAL journaling and a 50-second busy timeout; the read pool opens the file read-only. This lets a `kura mcp` process read while the daemon writes.

## Related Pages

- [Indexing Pipeline](/indexing-pipeline)
- [Configuration](/configuration)
