Architecture
flowchart LR
App[Local app] --> Overlay[TypeScript overlay + review modal]
Dashboard[TypeScript dashboard] --> API[Rust HTTP + SSE]
Overlay -->|Bearer token| API
API --> Store[(SQLite tasks, conversations, versions, appearance)]
API --> Queue[Rust worker queue]
Queue --> Git[Rust Git worktree operations]
Git --> Runtime[Rust agent transport library]
Runtime --> Agent[Codex / ACP / custom stdio]
Agent --> Validation[Rust command supervisor]
Validation --> Review[Patch + validation results]
Review -->|Explicit Apply| Checkout[Active working tree]
nudgethis is one executable with embedded, compiled browser assets. No Node bridge or
JavaScript backend remains. Node is used by build scripts and the black-box test harness;
default tests run application fixtures with execution disabled. Agent fixtures are separate opt-in tests.
| Path | Responsibility |
|---|---|
crates/nudgethis/src/main.rs |
CLI, setup, shutdown and disposable Rust demo |
config.rs |
Trusted TOML configuration and registered agents |
server.rs |
Axum loopback HTTP, bounded JSON, auth, origin/Host validation, SSE and assets |
core.rs |
Repository ownership, lifecycle, queue, concurrency, messages and actions |
store.rs |
SQLite, WAL-aware migration backup, tasks/messages/revisions/audit/preferences |
git.rs |
Detached worktrees, safe patch collection, apply checks and cleanup |
workspace.rs |
Missing-Git/no-history onboarding, explicit initialization and guarded branch changes |
versions.rs |
Private-index first/applied commit reviews, exact saves and interruption journal |
github.rs |
Selected-account GitHub CLI/API access, reviewed publishing, proposals and merge gates |
process.rs |
Bounded, cancellable validation/Git subprocesses with process groups/jobs |
appearance.rs |
Appearance schema constraints and uploaded-font limits |
element_context.rs |
Bounded single/group element context, URL sanitization and target validation |
crates/agent-runtime |
Reusable Rust transport library plus protocol-test executable |
packages/overlay |
TypeScript capture, review and shared appearance editor |
packages/server/public |
Dashboard HTML/CSS/TypeScript, embedded at Rust compile time |
packages/contracts |
Strict browser API types, checked against black-box HTTP behavior |
tests |
Node test client invoking real Rust binaries and disposable Git fixtures |
Lifecycle and consistency
draft → pending → analyzing → preparing → working → validating → ready → applying → applied → undoing → undone
Other review states are awaiting_feedback, failed, cancelled, conflict, rejected,
recovery_required. Drafts and preparation are optional stages.
An agent reply without a patch waits for feedback. Follow-ups increment the attempt and reuse
the worktree, except after Apply/Reject/Undo. Retry captures the current workspace, including local edits. The latest requested
attempt must match the stored version before a UI action runs. CLI actions target the latest.
Queue actions serialize through a control mutex. A bounded number of turns run concurrently. Git worktree metadata and application of patches serialize separately. Process cancellation stops the tree before the turn completes. A cancellation token spans agent and validation. The server's stop token cancels active work; SQLite recovers interrupted execution as failed and interrupted Apply/Undo as recovery_required.
SQLite preserves the Node alpha's JSON task rows and additive message/revision tables. Task update, audit insertion and terminal revision write share one transaction. Version 0 databases receive a SQLite backup, including committed WAL data, before the schema transaction. Reopening version 1 does not duplicate messages or backups. Future schema versions are refused. Earlier patch contents remain available; Apply/Reject update their version's status.
The agent receives an allowlisted task envelope and at most 128 KB of recent message text; the shared prompt also caps conversation at 48,000 characters. Full history remains in SQLite. No provider credentials, browser-supplied commands or raw prior process logs enter this envelope.
Agent transports
The queue calls nudgethis-agent-runtime directly as a Rust library. Each turn runs one
configured executable in its isolated worktree. Codex JSONL, the supported ACP v1 subset and
custom JSONL normalize public responses into chat events. See agents.
There is no in-process JavaScript adapter API. Existing adapters can expose the stdio protocol
in any language; their own runtime is independent of NudgeThis.
Appearance
A versioned JSON document stores both palettes, mode, three font roles, base size, radius
and optional base64 WOFF/WOFF2 files. Authenticated updates persist in SQLite and publish
appearance SSE notifications. Reconnecting clients refetch preferences. Clients with an
unsaved preview retain it until Save/Cancel; there is no collaborative merge or optimistic
revision control for themes, so the last saved theme wins.
Semantic CSS variables propagate through the dashboard and NudgeThis Shadow DOM. The host
application's root is never changed by the overlay. Fonts load through FontFace from bytes,
without public unauthenticated font endpoints or external font URLs. Custom themes can choose
any RGB colors; the editor reports several text contrast pairs and does not guarantee an
entire custom theme meets WCAG.
Element selection
The overlay supports single picks, multiple clicks/taps and rectangular area selection.
selection-input.ts handles gestures; multi-selection.ts owns the selected group and
review controls. Rust validates up to 20 unique targets from one page and a 48 KiB context
limit. Drafts, conversations and revisions retain that group. Source hints remain unverified;
changed or ambiguous targets require reselection. See selection controls.
Remaining work
Verified source mapping, screenshots, post-HMR visual checks and broader provider coverage are tracked in the roadmap. Rust HTTP models currently retain the existing JSON schema; generating TypeScript contracts from typed Rust models remains a follow-up, not a runtime dependency on JavaScript.
Discovery, snapshots and route coverage
project.rs reads bounded project metadata for framework/package-manager suggestions and
executable availability. It never executes diagnostic commands. route_review.rs scans
Git-listed source files for route candidates, validates concrete paths and stores explicit
manual desktop/mobile checks through a versioned SQLite preference. The TypeScript
route-review.ts frame uses fixed layout widths and optional visual scaling; it is not a
headless browser or full mobile emulator. Scan and review do not enter the worker queue.
git.rs uses an independent index to snapshot current source and retains local refs outside
branch history. Apply compares affected files with the captured base and records hashes
before/after. Undo refuses mismatches. The store journals mutation state before file changes;
recovery requires inspection instead of guessing whether to replay. Details.
Fresh worktrees run trusted setup commands before agent execution; continued worktrees retain dependencies. Setup and validation have separate result arrays. A source mutation by either command phase blocks review, and an empty validation list is explicitly unchecked.
Explicit local commits
The shared TypeScript Saved versions dialog is used by both browser clients. Rust's
versions module reads applied revision journals and creates a private index from HEAD.
It replays only selected patches and compares the resulting blobs/modes with recorded
applied states before returning a review. Saving validates that same server-held plan,
acquires the real index lock and prepares an index that retains unrelated staged entries.
commit-tree creates the exact reviewed commit (honoring signing); update-ref compares
and swaps the branch against the reviewed parent. A durable saved_versions SQLite record
precedes that ref update. Index installation completes the transaction; interruption
retains evidence and blocks ambiguous retries. No push, reset or agent execution is involved.
See Saved versions for limits and recovery. API tests use deterministic
file patches with execution disabled; Chromium tests exercise dashboard and mobile overlay.
Branches and publishing
Startup probes the folder instead of requiring a first commit. Git-dependent execution waits for a ready workspace; drafts and context remain accessible. The shared TypeScript branch guide polls read-only Git status without optional index writes and consumes local workspace notifications. Branch mutations validate expected HEAD, dirty state, active work and recovery before non-forced checkout. First-commit saves reuse the version journal.
GitHub sessions and ten-minute reviews live only in server memory. The gh CLI obtains an
explicitly chosen account credential and performs bounded REST/GraphQL calls; it never switches
the global active account. Exact HTTPS Git transfers use per-process credentials and clear
tracing/credential helpers, refuse URL rewrites and use one explicit branch refspec.
SQLite stores target metadata, last-checked branch status and publication receipts, not tokens.
Merge gates combine REST checks/status/mergeability with GraphQL review decisions and recheck
reviewed head/base before calling GitHub. Merge never resets local files or branches.
The test-only HTTP transport points at a local API fixture; Git transfers use local bare
repositories. It is not an externally configurable production endpoint. See the guide.