mxr-development
GitHub提供 mxr 项目的开发规范,涵盖本地优先架构、构建验证流程、客户端契约及严格的 Crate 依赖边界。指导开发者在源码、文档及测试变更时遵循 CLI-first 和 daemon-backed 原则,确保代码质量与架构一致性。
触发场景
安装
npx skills add planetaryescape/mxr --skill mxr-development -g -y
SKILL.md
Frontmatter
{
"name": "mxr-development",
"description": "Use when changing mxr source, architecture, docs, tests, IPC, daemon handlers, store\/search\/sync\/semantic behavior, provider adapters, TUI\/web clients, release flow, or repo-level development process."
}
mxr Development
This skill holds the context that used to bloat always-on agent files. Load it only for source/docs/process work.
Product shape
- Local-first: SQLite is canonical, search indexes are rebuildable, and core mail works offline.
- Daemon-backed: TUI, CLI, web, and scripts are clients over Unix-socket IPC.
- CLI-first: new capabilities land in CLI at the same time as daemon support, with stable JSON/JSONL.
- Provider-agnostic core: Gmail/IMAP/SMTP/Outlook behavior maps into the internal model in adapters.
- Compose uses
$EDITORwith YAML frontmatter plus markdown body. - Reader mode is plain text first; no inline images in the terminal rendering path.
Build and verify loop
For feature work:
- Implement in the narrowest crate surface.
- Run
scripts/cargo-test -p <crate> --tests. - Run
cargo build -p mxr. - Restart stale daemons:
pkill -f 'mxr daemon' 2>/dev/null, thencargo run --bin mxr -- daemon --foreground. - Drive the feature through the CLI, preferably with
--format json. - Inspect daemon state with
mxr events,mxr logs,mxr doctor, andmxr activity. - Query persisted state back through the CLI, such as
mxr search ... --format json.
If the daemon will not start, check cargo build -p mxr, pgrep -af 'mxr|cargo', mxr daemon --foreground, and stale socket files.
Client and mutation contract
- TUI and CLI must use the same daemon request; avoid client-only capabilities.
- Every reusable daemon capability needs a CLI surface. TUI/web support should layer on it.
- Destructive or batch mutations need a dry-run/preview path before commit.
- Dry-run selection/query logic must match the real mutation path.
- Read/list/status/search/export surfaces must keep structured output pipeable.
Crate boundaries
coredepends on no internal crates.protocoldepends only oncore.- Provider crates depend on
coreplus shared mail utility crates such asmail-parseandoutbound. storeandsearchdepend only oncore.semanticowns embeddings/dense retrieval and must not depend on daemon, TUI, or provider crates.llmowns provider clients and prompt/result DTOs; higher layers pass plain data in.relationshipmay depend oncore,store,reader, andllm; not protocol/daemon/client/sync/search/semantic/provider crates.safetymay depend oncore,reader, andrelationship; not store/protocol/daemon/clients/sync/search/semantic/provider crates.syncdepends oncore,store, andsearch.daemonis the integration point, but talks to providers only throughMailSyncProviderandMailSendProvider.tuiandwebare clients; they must not depend on daemon, store, search, sync, semantic, or provider crates.- Use Cargo dependencies for architecture seams, never
#[path].
See docs/blueprint/01-architecture.md for longer rationale.
Domain invariants
- Semantic search is optional platform behavior layered above core mail runtime.
- Sync stores envelopes/bodies and commits lexical search before a sync batch finishes.
- Semantic chunks may be persisted during sync, but embeddings/ANN refresh only happen when semantic is enabled or explicitly reindexed.
- Hybrid search keeps BM25 exactness and adds dense recall with RRF.
- Activity log rows are local-only personal data. Never sync or transmit them, never store credentials/full bodies/attachment bytes, and write only through
state.activity.record(...). INSERT OR REPLACEcan triggerON DELETE CASCADE; preferINSERT ... ON CONFLICT UPDATEfor parent rows with dependents.mxr reset --hard/mxr burnwipe runtime state only by default; preserve config and credentials unless explicitly requested.
Release shorthand
If the user says ship it, run the full release flow:
- Commit release-ready changes.
- If the version/tag exists, bump first; never overwrite tags or GitHub releases.
- Push
main. - Create and push
v{version}. - Wait for the tag-driven release workflow.
- Verify all three install channels, in throwaway locations so they never collide with the real install:
- Homebrew:
brew update && brew upgrade mxr(the real install on this machine);mxr versionmust report the new release. - install.sh:
MXR_INSTALL_DIR="$(mktemp -d)" ./install.sh v{version}, run<tmp>/mxr version, thenrm -rfthe temp dir. - cargo:
cargo install --git https://github.com/planetaryescape/mxr --tag v{version} --locked --root "$(mktemp -d)" mxr, run<tmp>/bin/mxr version, thenrm -rfthe temp root.
- Homebrew:
- Converge this machine on Homebrew only. After verification, the sole
mxron PATH must be Homebrew's: remove any~/.cargo/bin/mxr(cargo uninstall mxr) and any~/.local/bin/mxrleft by past install.sh runs, then confirm withwhich -a mxr. Multiple mxr binaries on PATH carry different build ids, and every invocation restarts the daemon to "match the current binary" — ping-ponging the daemon between versions.
Source of truth: docs/blueprint/17-release-pipeline.md and checked-in GitHub workflows.
Useful docs
docs/blueprint/- requirements, architecture, decisions.docs/blueprint/15-decision-log.md- settled decisions.docs/activity-log.md- activity table lifecycle and privacy rules.docs/implementation-journey.md- historical context and superseded plans.
版本历史
- c4ada04 当前 2026-07-30 20:15


