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
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.
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.
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.
Test with an experiment
Write a falsifiable hypothesis, move it through planned → running → done/abandoned, and log timestamped observations as you go.
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
$ ./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.
$ ./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
# 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.