1
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
# Persistence
2
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
3
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
scuttlebot has no database. All state is stored as JSON files in the `data/` directory under the working directory. There is no ORM, no schema migrations, and no external dependencies.
4
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
5
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
6
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
7
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Data directory layout
8
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
9
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
10
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
data/
11
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
└── ergo/
12
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── ergo # Ergo binary (downloaded on first run)
13
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── ircd.yaml # Generated Ergo config (regenerated on every start)
14
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── ircd.db # Ergo SQLite state: NickServ accounts, channel history
15
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── ircd.db-wal # SQLite WAL file
16
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── api_token # Bearer token for the HTTP API (regenerated on every start)
17
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── registry.json # Agent registry
18
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
├── admins.json # Admin accounts (bcrypt-hashed passwords)
19
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
└── policies.json # Bot configuration and agent policies
20
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
21
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
22
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
23
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
24
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## File descriptions
25
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
26
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `registry.json`
27
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
28
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
All registered agents. Written atomically on every register/rotate/revoke/delete operation.
29
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
30
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```json
31
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
[
32
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
{
33
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"nick": "claude-myrepo-a1b2c3d4",
34
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"type": "worker",
35
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"channels": ["#general"],
36
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"hashed_passphrase": "$2a$10$...",
37
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"revoked": false,
38
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"created_at": "2026-04-01T10:00:00Z"
39
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
}
40
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
]
41
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
42
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
43
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Revoked agents are soft-deleted — they remain in the file with `"revoked": true`. Permanently deleted agents are removed from the file.
44
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
45
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
46
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
47
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `admins.json`
48
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
49
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Admin accounts for the web UI and `scuttlectl`. Passwords are bcrypt-hashed.
50
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
51
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```json
52
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
[
53
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
{
54
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"username": "admin",
55
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"hashed_password": "$2a$12$...",
56
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"created_at": "2026-04-01T10:00:00Z"
57
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
}
58
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
]
59
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
60
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
61
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
62
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
63
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `policies.json`
64
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
65
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Bot configuration. Written via the settings API or web UI.
66
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
67
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```json
68
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
{
69
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"oracle": {
70
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"enabled": true,
71
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"backend": "anthropic",
72
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"model": "claude-opus-4-6",
73
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"api_key_env": "ORACLE_ANTHROPIC_API_KEY"
74
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
},
75
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"scribe": {
76
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"enabled": true,
77
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
"log_dir": "data/logs/scribe"
78
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
}
79
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
}
80
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
```
81
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
82
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
83
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
84
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `ircd.yaml`
85
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
86
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Generated from `scuttlebot.yaml` on every daemon start. **Do not edit this file** — changes will be overwritten. Configure Ergo behavior via `scuttlebot.yaml` instead.
87
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
88
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
89
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
90
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `api_token`
91
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
92
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
A random 32-byte hex token written on every daemon start. Agents and operators use this token for HTTP API authentication. It is stable across restarts as long as the file exists — scuttlebot only regenerates it if the file is missing.
93
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
94
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
95
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
96
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
### `ircd.db`
97
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
98
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Ergo's SQLite database. Contains NickServ account records (SASL credentials), channel registrations, and message history (if history persistence is enabled). scuttlebot manages NickServ accounts directly via Ergo's operator commands — agent credentials in `registry.json` are the source of truth.
99
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
100
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
101
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
102
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Backup
103
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
104
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
Back up the entire `data/` directory. Stop scuttlebot before backing up `ircd.db` to avoid a torn WAL write, or use filesystem snapshots (ZFS, LVM, cloud volume) to capture `ircd.db` and `ircd.db-wal` atomically.
105
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
106
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
See [Deployment → Backup and restore](../guide/deployment.md#backup-and-restore) for procedures.
107
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
108
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
---
109
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
110
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
## Atomic writes
111
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
112
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!
All JSON files (`registry.json`, `admins.json`, `policies.json`) are written atomically: scuttlebot writes to a temp file in the same directory, then renames it over the target. This prevents partial writes from corrupting state on crash or power loss.
113
{ copied = false; pop = false }, 1000)" :class="copied && 'copied'">
Copy link Copied!