Development
Development Conventions
Codebase rules that keep Origin's daemon, CLI, MCP connector, shared types, and core logic maintainable.
At a glance
01
Origin's maintainer rules keep the local daemon simple, testable, and careful around private work context.
02
Use these conventions when you change daemon behavior, MCP tools, storage, typed clients, or release-facing paths.
01
Why conventions matter
Origin's daemon owns the local store that multiple AI clients read from and write to. A small boundary mistake can leak framework dependencies into core logic, change a public response shape, or make private data harder to inspect safely.
The conventions are intentionally practical: keep business logic in the core crate, keep public wire types stable, keep state snapshots short-lived, and keep user data out of public bug reports.
02
Crate boundaries
origin-core owns storage, retrieval, graph logic, pages, evals, and other business behavior. It should not depend on Axum or Tauri. origin-server should frame HTTP requests and call core logic instead of becoming a second business layer.
origin-types stays lightweight because it is shared by the daemon, MCP connector, CLI-adjacent tooling, desktop app, and downstream Rust clients. origin-mcp should deserialize daemon responses into typed structs so envelope drift fails loudly.
Boundary map
origin-core business logic; no Axum or Tauri
origin-server HTTP framing, not business logic
origin-types lightweight shared wire types
origin-mcp typed daemon responses, no JSON passthrough
route handlers snapshot state before awaits03
Data safety
Use parameterized SQL instead of interpolated query strings. Preserve Option<T> as SQL NULL so unset values stay distinguishable from empty strings.
Rust strings are UTF-8, so avoid byte indexing for user content. Wrap multi-row mutations in transactions, and redact memory contents before copying diagnostics into public issues.
Storage rules
SQL: parameterized queries only
NULL: store Option<T> as SQL NULL
UTF-8: do not byte-index Rust strings
Batch SQL: wrap multi-row mutations in BEGIN/COMMIT
Privacy: redact memory contents in issues04
Async and state
Do not hold long-lived state guards across awaits. Route handlers should clone the small pieces they need, drop the lock, and then call storage, LLM, or eval code.
This matters most around LLM calls, imports, distillation, eval paths, and any request that can take longer than a normal local HTTP round trip.
05
Development gotchas
A source checkout can talk to the same product daemon and data directory that your installed Origin uses. For isolated development, run the daemon on a different port with a temporary data directory.
Worktrees have their own gitignored caches and generated artifacts. After squash merges, git cherry can mislead; verify integration by commit message, PR body, or the actual diff instead.
Common gotchas
Product daemon: 127.0.0.1:7878 + platform data dir
Isolated dev: ORIGIN_PORT=7879 ORIGIN_DATA_DIR=/tmp/origin-test
Squash merges: verify by commit message/body, not git cherry alone
Worktrees: gitignored caches are per-checkoutNext
Contributing
How to contribute useful bug reports, docs, eval cases, and code changes to Origin.
Read next