A local-first macOS communication workspace with a native shell, a Node hub, and a Trinity-backed drafting runtime.
Quick Start • Dependencies • Installation • Versions • Current Runtime Shape • Contributing
This repository is intended to be understandable and operable without private tribal knowledge.
That means:
- the shipped runtime shape must be documented
- install and run steps must be reproducible from the repo
- architecture boundaries with
{trinity}and{train}must be explicit - operator-visible behavior changes must update docs in the same change
There is also one rigid runtime rule for shipped UX:
- passive UI must read precomputed local state
- heavy computation belongs in local background workers and local AI/runtime services
- online synchronization is downstream of local readiness, never a prerequisite for a fast workspace
There is also one rigid identity rule:
- contact merge and unmerge are explicit user actions only
{reply}must not auto-merge identities through phone, email, or channel heuristics
{reply} is a macOS-first local communication operating system for a single human operator.
It does four things:
- ingests local and connected communication sources
- assembles message-backed conversations and contact context
- drafts replies through
{trinity} - executes final sends through the correct local transport
The live product boundary is now explicit:
{reply}owns ingestion, local product workflow, conversation assembly, transport execution, and send-policy gates{trinity}owns live drafting, ranking, policy application, trace export, and training-bundle export{train}stays offline and bounded, learning policy artifacts from exported bundles only
Canonical docs:
- REPLY_OVERVIEW.md
- docs/TRINITY_INTEGRATION_SPINE.md
- docs/RELATION_AUDIT.md
- docs/POLICY_LOOP_REPO_BREAKDOWN.md
- docs/THIN_UI_LOCAL_PRECOMPUTE_AUDIT.md
- docs/NATIVE_WORKSPACE_HOT_PATH_SSOT.md
- CONTRIBUTING.md
This README now reflects the current product state, including:
- live drafting runtime is
{trinity}first, with bounded local fallback whensuggesttimes out or fails - if live
suggestfails but a prepared Trinity draft already exists,{reply}now recovers that prepared draft before falling back to local drafting - legacy drafting survives only as developer-only shadow comparison behavior
- structured draft outcomes now go to
/api/trinity/outcomeinstead of piggybacking on generic feedback logs - runtime failures are operator-safe and no longer expose Docker, Colima, socket, or raw substrate errors in normal UI surfaces
- the conversation sidebar is driven by a local materialized conversation index in
chat.dbrather than by request-time reconstruction or hard gating fromcontacts.db - thread loading now preloads the first 20 and last 20 messages, then fills the history gap incrementally in the background
- message threads now render explicit left/right sent-versus-received rows instead of one undifferentiated feed
- suggest and drafting routes now consume prepared local snapshot artifacts rather than assembling snippets, history, or fallback inbound context in the request path
- opening one conversation now forces a Trinity prepared-draft check and immediate refresh so the composer gets a Trinity draft even when the cached draft is missing or stale
- the visible thread now has a bounded delta lane:
/api/threadreturnsdeltaCursor/threadVersion/api/thread-deltafetches only new rows after the current cursor- send success now patches the visible thread and conversation row first, then background revalidation follows
- relation health is now causal, not only descriptive: major dependencies expose active mode, last success, last failure, failure class, and recovery state
- persisted
contact.draftno longer seeds compose on conversation open; the operator-visible input is now Trinity-owned on the hot path - native sync triggers now send the same protected approval payload/header shape as the web app, so per-source sync actions can start background work from the native shell
- native shell expectations are now first-class:
reply.appis the operator shell, the hub/runtime sit behind it - thin-read architecture is now explicit: passive UI routes are expected to consume local materialized read models instead of request-time reconstruction
- web and native compose are now capability-safe: the composer only offers channels returned by
conversation_channel_capabilities, and send routes reject stale or unauthorized conversation/channel combinations - native launch is now readiness-gated: the app and
script/build_and_run.sh --verifywait for a healthy local hub instead of treating a bare process spawn as success - Apple source mirror refresh is no longer part of the startup critical path; it runs in the background while the hub comes online
{reply}can now replay already-synced local Notes, Calendar, Contacts, Contact Intelligence, historical conversation rows, and accepted draft outcomes into the existing Trinity seam throughPOST /api/trinity/backfill-sourcesorcd chat && npm run trinity:backfill-sources- durable local writes are now explicitly serialized in the hot paths that were producing the most operational drift:
- LanceDB vector writes and text-index creation
chat.dbmessage writes and post-save maintenance
- draft learning now has a stricter reply-owned local substrate:
- generation IDs are derived locally
- generation, feedback, outcome, and revision events share one local schema
- recent learning summaries can be read back for prompt/runtime consumers
- conversation foundation work is now explicit in the repo and docs:
- canonical conversation tables exist in
chat.db - immutable participant-membership snapshots are the target model
- merge authority remains manual-only and user-owned
- canonical conversation tables exist in
- conversation integrity tooling is now checked into the repo via
npm run audit:conversations
Current documented runtime versions:
{reply}package version:0.5.15- native shell target:
macOS 15+ - Node.js:
>=20.17.0 - Python for
{trinity}:>=3.12 - Swift toolchain:
Swift 6
Repository bootstrap:
git clone https://github.com/your-org/reply.git
cd reply/chat
npm install
cd ..
make runOptional native shell:
make run-appFoundation verification:
make verify-foundationOpen:
- product UI or embedded hub:
http://127.0.0.1:45311/ - health:
http://127.0.0.1:45311/api/health - health alias:
http://127.0.0.1:45311/api/system/health
When you launch the native shell, the bundled hub prefers ports 45431 through 45446 and the app now waits for /api/health readiness instead of only checking whether a reply process exists.
The default foundation verification gate runs:
npm run lint- targeted runtime and storage hardening tests
swift buildfor the native shell on macOS- optional Trinity smoke via
cd chat && npm run verify:foundation -- --with-trinity-smoke
Required local platform dependencies:
- macOS 15+
- Xcode / Swift 6 toolchain for
app/reply-app - Node.js
>=20.17.0 - Python
>=3.12for the local{trinity}runtime CLI - Full Disk Access for the runtime host process if you want iMessage ingestion
Required repo/runtime dependencies:
chat/package.json@lancedb/lancedb@xenova/transformersdompurifydotenvimapflowlibphonenumber-jsmailparsermbox-readerollamaplaywrightsqlite3
app/reply-app/Package.swift- native shell and protected-data helper
Required sibling runtime dependency:
{trinity}repository available either:- at
/Users/Shared/Projects/trinity - via
TRINITY_REPO_ROOT - via
TRINITY_RUNTIME_ROOT - or bundled into
reply/trinity-runtime
- at
Optional external tools:
Ollamafor local drafting/ranking model routesOpenClawfor WhatsApp transport and gateway control- Mail.app configured locally for Apple Mail fallback paths
- a valid Gmail OAuth connection if you want Gmail sync instead of Apple Mail fallback
The full local install and operator runbook is in docs/LOCAL_MACHINE_DEPLOYMENT.md.
Short version:
cd /Users/Shared/Projects/reply/chat
npm installInstall and prepare {trinity}:
cd /Users/Shared/Projects/trinity
uv sync --devcd /Users/Shared/Projects/reply/chat
cp .env.example .envImportant environment knobs:
PORT=45311TRINITY_REPO_ROOT=/Users/Shared/Projects/trinityTRINITY_PYTHON_BIN=/opt/homebrew/bin/python3.12or another Python 3.12+ binaryOLLAMA_HOST=http://127.0.0.1:11434
If using Ollama:
ollama serveIf using WhatsApp transport:
openclaw channels login --channel whatsappForeground session mode:
make runNative shell:
make run-appInstall the built native bundle into /Applications:
cd app/reply-app
./install-bundle.shapp/reply-app/install-bundle.sh is the supported local install/update path for /Applications/reply.app.
- native macOS app:
app/reply-app - session-owned hub:
chat/server.js - background worker and local ingestion sidecars behind the hub
- live drafting goes through
chat/brain-runtime.js {trinity}is the primary live drafting runtime in normal product mode- if
{trinity}suggestfails or times out,{reply}falls back to bounded local drafting and recordsruntimeMode: trinity-fallback-local - developer-only
trinity-shadowmode exists for comparison against legacy output - accepted artifact provenance is carried through draft context, outcomes, traces, and training bundles
- external inbound bridge route:
POST /api/channel-bridge/inbound - event audit log:
~/Library/Application Support/reply/channel_bridge_events.jsonl - dedupe cache:
~/Library/Application Support/reply/channel_bridge_seen.json - queued bridge message outbox:
~/Library/Application Support/reply/channel_bridge_pending.json - LinkedIn now defaults to
browser_bridge; sidecar mode is explicit-only - bridge writes are fail-soft:
- vector ingest happens first
- unified
chat.dbwrites are bounded - when
chat.dbis busy, bridge messages are queued and replayed by the background worker
- dashboard source cards report raw ingestion counts
- sidebar conversations come from the local materialized
conversation_indexinchat.db - canonical message rows live in
unified_messages - canonical conversation-foundation tables also live in
chat.db:external_threadsconversation_snapshotsconversation_participantsconversation_messagesmessage_recipientsconversation_channel_capabilities
- mail conversations can be sourced from Apple Mail fallback ingestion when Gmail is unavailable
- contact rows enrich conversations when available, but valid message-backed handles are no longer hidden when
contacts.dblacks a profile row - contact merges are explicit user-owned state only; the product does not auto-merge identities
- active composer channels come from
conversation_channel_capabilities, not from handle heuristics or the last visible message alone - thread views now preload both ends of the conversation window:
- first 20 messages by oldest order
- last 20 messages by newest order
- if there is a history gap between those windows, the app fills it incrementally without blocking the UI
/api/threadis canonical-first:- it reads
conversation_messages/conversation_channel_capabilitieswhen present - it retries a local conversation-foundation rebuild before using the legacy
unified_messagescompatibility path
- it reads
- structured draft outcomes:
/api/trinity/outcome - generic operator notes and freeform logs:
/api/feedbackand/api/feedback/log - trace export and training-bundle promotion stay explicit, versioned, and replayable
Hub and native shell:
make run
make stop
make status
make doctor
make run-app
make build-appNode checks:
cd chat
npm test
npm run lint
npm run audit:conversations
npm run verify:trinity-trainUseful runtime checks:
npm run verify:openclaw
curl http://127.0.0.1:45311/api/health
curl http://127.0.0.1:45311/api/system/health
cat ~/Library/Application\\ Support/reply/channel_bridge_pending.jsonMail-specific checks:
cat ~/Library/Application\\ Support/reply/mail_sync_status.jsonnpm run verify:trinity-train is the end-to-end runtime smoke check for the live {reply} -> {trinity} -> {train} contract. It verifies one synthetic cycle through suggest, record-outcome, export-trace, and train-propose-policy. The check is now bounded, emits step timing, and should fail fast instead of hanging indefinitely. On this machine, the Trinity runtime can also auto-resolve from a misconfigured mistral-cli route to an effective Ollama route, and the smoke output now makes that provider decision explicit.
Current high-level split:
- conversation assembly, transport, safety, and operator UX remain in
{reply} - candidate generation, refinement, evaluation, ranking, and artifact application live in
{trinity} - offline policy learning and eval live in
{train}
Additional docs:
- docs/ARCHITECTURE.md
- docs/CONVERSATION_FOUNDATION_AUDIT.md
- docs/DEPENDENCY_MAP.md
- docs/LOCAL_MACHINE_DEPLOYMENT.md
- docs/HANDOVER.md
- docs/CODING_STANDARDS.md
- CONTRIBUTING.md
Open-source contributions should start with:
Every code change must update the relevant docs when behavior, runtime ownership, setup steps, or verification expectations change.
- Dashboard counts are high but the sidebar is tiny: the current build now uses the unified message-backed conversation index rather than requiring a preexisting contact row. If the UI still shows stale results, reload the app so the
v5conversation cache replaces older cached pages. - Thread history feels incomplete: current behavior intentionally preloads both ends of the thread and loads the middle gap progressively. Scroll through the thread or use the history gap loader to fetch more without freezing the workspace.
Local agent runtime is unavailable.: this now means a normalized local substrate failure, usually Docker/Colima or a sandbox runtime. Check the local runtime, not the drafting code.Reply drafting runtime is unavailable.: check the local{trinity}runtime path, Python 3.12+, and model runtime health.- iMessage ingestion degraded: grant Full Disk Access to the actual runtime host process and confirm
~/Library/Messages/chat.dbis readable. - WhatsApp transport degraded: check
OpenClawand its gateway.
- Track work in
moldovancsaba/replyissues and docs/EXECUTION_BACKLOG.md. - Keep product, runtime, and learning boundaries explicit.
- Run tests and syntax checks before shipping.
- Update the canonical docs when runtime contracts, install steps, or operator-visible behavior change.
Provided "as-is" for local-first operator workflows and localhost ecosystem routing.