Rust · Self-hosted · Engineering memory

Causelog

A place to record the trade-offs you weigh, the experiments that test them, and the lessons you'd otherwise re-learn the hard way. One binary. Your server. Your data.

Self-hosted · No Node.js · No database server · AGPL-3.0

Built for the goal → decision → experiment loop

🎯

Projects & goals

Every project says what "done" looks like. Goals carry Markdown bodies — bullet points for success criteria, context, anything. Open, done, or dropped: the project statistics page tracks it all.

⚖️

Decisions

The options you weighed, the choice you made, and why. Every edit appends an immutable revision — the record of what you decided and the reasoning behind it can't be silently rewritten.

🧪

Experiments

A falsifiable hypothesis, a lifecycle (planned → running → done/abandoned), and timestamped observations. When you finish, capture the lesson — or let the timeline tell the story.

📝

Notes

Durable knowledge, extracted from experiments or written directly. Every note has the same immutable revision history as decisions, so context is never lost.

🔗

Graph

How everything connects: what serves a goal, what an experiment tests, where a note came from. Typed links — supports, rejects, follows, related — make the structure explorable.

📅

Timeline

The story of a project in order: when things started, when you measured, when you stopped. Newest first — so the latest context is always right there.

🔍

Full-text search

SQLite FTS5 keeps every goal, decision, experiment, and note searchable. The index is kept in sync by database triggers — content written before the index existed is still found.

📊

Statistics

Progress bars for goals completed and decisions decided, plus cards for every status — open, dropped, rejected, planned, abandoned — and knowledge counts. The whole picture, at a glance.

📦

One binary, solo mode

Single causelog binary with embedded SQLite. Argon2 password hashing, session cookies, CSRF protection, and a seeded demo to try it out in seconds.

How the loop works

1

Create a project

Open the dashboard, create a project with a title and summary. The project is the container for everything — goals, decisions, experiments, notes.

2

Define what done looks like

Add goals with Markdown bodies — bullet points for success criteria, metrics, context. The statistics page tracks open, done, and dropped goals with a progress bar.

3

Weigh options and decide

Record the alternatives you considered, the choice you made, and the rationale. Every edit is an immutable revision — future-you always has the context.

4

Test with an experiment

Write a falsifiable hypothesis, move it through planned → running → done/abandoned, and log timestamped observations as you go.

5

Capture the lesson

When the experiment is done, extract a note or write one directly. Link it back to the experiment, the decision, the goal — the graph keeps the web of relationships visible.

See it in action

causelog serve
$ ./target/release/causelog serve
[info] database ready database_url=sqlite://causelog.db
[info] listening on http://127.0.0.1:8080

→ open http://127.0.0.1:8080 — no user exists yet, so you land on
  /setup to create the owner account. After that: /login.
try it instantly with the demo
$ ./target/release/causelog seed-demo

 user created — login with demo / demo-password
 3 projects seeded (Gloria the plant, Tidy the repo, ...)

→ http://127.0.0.1:8080 — log in and explore the golden path
  Goals → Decisions → Experiments → Notes → Timeline → Graph
the graph shows how everything connects
# automatic HTTPS — no reverse proxy needed
$ causelog serve --tls-domain causelog.example.com --addr 0.0.0.0:443

 certificate issued (TLS-ALPN-01) · auto-renewing
 HTTP :80 → HTTPS redirect running

# back up the single SQLite file any time
$ sqlite3 causelog.db .backup causelog-backup.db

Get started in two minutes

Build the single binary, run it, and finish setup in the browser. No Node.js in production, no database server, no config files for 90% of installs.

# Build the release binary
cargo build --release --bin causelog

# Start the server (creates causelog.db)
./target/release/causelog serve

# Open http://127.0.0.1:8080 → /setup wizard, then explore the demo

# Or try the pre-seeded demo
./target/release/causelog seed-demo
# login: demo / demo-password

# Automatic HTTPS
./target/release/causelog serve --tls-domain causelog.example.com --addr 0.0.0.0:443

# Back up the database
sqlite3 causelog.db .backup causelog-backup.db

The tests that keep it honest

cargo test --workspace                     # unit, integration, E2E
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check
cd e2e && npm run test:e2e                    # real browser vs the real binary

Three layers of tests: pure-function unit tests, full HTTP integration tests against an in-memory database, and browser E2E via Playwright that drives the golden path through real Chromium.

Docs: README · License