7. Operations
Requirements
- Bun >= 1.1 (tested on 1.3.10). Nothing to install: no dependencies.
- A claude-mem database. Without one the page loads and shows "Local work-state database is unavailable."
- For the refresh:
python3(stdlib only) and either theclaudeCLI (logged in) or an OpenAI-compatible key. - Linux or macOS. Windows is untested.
Run
bun bin/aletheia-server.mjs
It prints the port, the database path, the data directory and whether the refresh is on. Stop with Ctrl-C (SIGINT/SIGTERM close the database handles).
Run as a user service (systemd)
scripts/aletheia.service:
[Unit]
Description=aletheia-mem
After=default.target
[Service]
WorkingDirectory=%h/Projects/aletheia-mem
ExecStart=%h/.bun/bin/bun bin/aletheia-server.mjs
Environment=ALETHEIA_PORT=37790
# Environment=ALETHEIA_PROVIDER=claude-cli
Restart=on-failure
[Install]
WantedBy=default.target
mkdir -p ~/.config/systemd/user
cp scripts/aletheia.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now aletheia
journalctl --user -u aletheia -f
Sharing the original's ledger
By default the clone keeps its own ledger. To read what the original's refresh already produced, set ALETHEIA_LEDGER_DIR=~/.claude-mem/work-view. Both servers then read the same files. Do not enable the clone's refresh on that directory while the original's refresh is also on: two writers, one ledger. (A refresh in one process refuses to start while another live pid holds state: running, but the check is a courtesy, not a lock.)
Security model
- Binds
127.0.0.1only. Refuses any request whose peer,Hostor forwarding headers say it is not local. - POSTs must be same-origin JSON.
- The database is opened read-only with
query_only. The server writes only under its data directory, plus two explicit user actions: Load in Claude Code appends one@<rules file>line toALETHEIA_CLAUDE_MD, and saving a rule rewritesALETHEIA_RULES_FILE. - The file route serves only absolute,
..-free paths with an allow-listed extension that exist as regular files, withnosniffand a sandbox CSP. - Do not put the server behind a reverse proxy: the proxy headers make it refuse.
- The page and API expose your prompts and tool calls. Treat the port like a local password manager.
Files and growth
| Path | Grows with | Safe to delete? |
|---|---|---|
<data>/overlay.db | each rule or "finished" action | no: your saved rules live here |
<data>/work-view-reviews.db | each checked card | yes (marks are lost) |
<ledger>/ | refreshes | yes; the next refresh rebuilds it (costs model calls) |
<data>/human-copy.json, human-copy-usage.jsonl | model calls | yes |
<ledger>/failed-answers/ | refused model answers | yes |
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| Page says the work-state database is unavailable | CLAUDE_MEM_DB wrong or claude-mem not installed. ls ~/.claude-mem/claude-mem.db. |
| 403 "available only on this computer" | You used a non-loopback host name, a proxy, or 0.0.0.0. Use http://localhost:<port>. |
| 403 on a POST | Browser sent another Origin (a different port or host) or a non-JSON content type. |
| No agents shown, 0 observations | Running with ALETHEIA_BUG_COMPAT=1, or your database has no observations rows. |
| Cards but no progress meters | The refresh has not run. Set a provider, then check <ledger>/refresh.json. |
refresh.json says failed | Read error and steps; look in <ledger>/failed-answers/. A provider error shows the CLI's first line. |
waiting-for-agent | (original only) no logged-in agent CLI; the clone reports failed with the provider error instead. |
| Rule saved but Claude Code does not follow it | Click Load in Claude Code, or add @<rules path> to your CLAUDE.md yourself. |
| Port in use | ALETHEIA_PORT=<n>. |