Skip to content

Development

Development Conventions

Codebase rules that keep Origin's daemon, CLI, MCP connector, shared types, and core logic maintainable.

Qi-Xuan LuUpdated 5 min read

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 awaits
Read architecture

03

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 issues

04

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-checkout
Read environment variables

06

Before changing shared behavior

Add the smallest relevant test before changing daemon behavior, public wire shapes, MCP tool outputs, or retrieval semantics. Keep PRs narrow enough that reviewers can reason about them.

If a change affects what users install, run, cite, or troubleshoot, update the matching docs page in the same PR.

Read typed clients

Next

Contributing

How to contribute useful bug reports, docs, eval cases, and code changes to Origin.

Read next