Local API
The server binds to 127.0.0.1:7331 by default. Every /api/ endpoint requires
Authorization: Bearer <local-token>. The token lives in ignored .nudgethis/token.
Browser calls must also use an explicitly allowed loopback Origin.
| Method | Route | Result |
|---|---|---|
| GET | /api/status |
Branch, HEAD, configured agents, executionEnabled, setup/validation commands |
| GET | /api/diagnostics |
Read-only framework, package-manager and executable availability report |
| GET | /api/versions |
Pending applied corrections, local saved-version history and Git author defaults |
| POST | /api/versions/preview |
Review selected corrections without staging or updating the branch |
| POST | /api/versions/save |
Explicitly create the reviewed local commit; never pushes |
| GET | /api/workspace |
Local Git readiness, branch, HEAD, branch choices and dirty counts |
| POST | /api/workspace/initialize |
Explicitly initialize local Git; no upload |
| GET | /api/workspace/initial-files |
Eligible first-version paths and author defaults |
| POST | /api/workspace/initial-preview |
Review selected first-version files |
| POST | /api/workspace/branch |
Guarded create/switch of a local branch |
| GET | /api/github |
Session account, target and cached branch publication status; no network |
| POST | /api/github |
Explicit account, repository, publishing, proposal and merge actions |
| GET | /api/device-preview |
Browser availability, fixed profiles and the last opened device session |
| POST | /api/device-preview |
Explicitly open/configure or close the owned Chromium browser |
| GET | /api/tasks |
Task summaries, newest first |
| POST | /api/tasks |
Create a draft or enqueue; returns 202 |
| GET | /api/tasks/QA-1 |
Context, patch, validation, messages, activity, revision summaries |
| POST | /api/tasks/QA-1/messages |
Send a follow-up; returns 202 |
| GET | /api/tasks/QA-1/revisions/1 |
Historical patch, validation and context snapshot for version 1 |
| POST | /api/tasks/QA-1/draft |
Edit a draft with version checking |
| POST | /api/tasks/QA-1/start |
Queue a saved draft when execution is enabled |
| POST | /api/tasks/QA-1/undo |
Undo an applied patch if affected files are unchanged |
| POST | /api/tasks/QA-1/apply |
Apply a ready patch to the active working tree |
| POST | /api/tasks/QA-1/reject |
Reject and remove the worktree |
| POST | /api/tasks/QA-1/retry |
Discard old worktree and retry from the current workspace |
| POST | /api/tasks/QA-1/cancel |
Cancel pending or active work |
| DELETE | /api/tasks/QA-1 |
Delete an inactive, unapplied task and worktree |
| GET | /api/project-context |
Project instructions, skills and reference documents |
| POST | /api/project-context |
Validate and replace the project context library |
| GET | /api/events |
SSE events including connected, task, appearance, project-context, route-review, versions, workspace and github |
Use Content-Type: application/json for POST, and {} for actions. A task body (optional agent selects a configured ID):
{
"agent": "codex",
"request": "Align the button right on desktop and full width on mobile.",
"context": {
"url": "http://localhost:5173/team",
"tagName": "button",
"selector": "[data-testid=add-teammate]",
"text": "Add teammate",
"viewport": { "width": 1440, "height": 900 },
"boundingBox": { "x": 24, "y": 200, "width": 160, "height": 40 }
}
}
URLs are stripped of credentials, query strings and fragments. Extra fields are
ignored; the server does not accept executable commands or a repository root from task bodies.
Optional references are safe relative file hints, not an allowlist or file-reading request.
Task creation and draft edits accept up to 128 KiB; other task action payloads are
limited to 32 KiB. A conflict or invalid lifecycle action returns 409.
For a group, provide context.elements, a flat array of 1–20 element context objects
with the same fields as the single-target example. Every member needs a unique nonempty
selector, tag name and HTTP(S) URL. All sanitized URLs must identify the same page.
The returned top-level context mirrors the first member for compatibility; elements
contains the entire group, including that first member. Single-target requests remain valid.
The server strips credentials, queries and fragments from every URL, bounds each field,
rejects nested groups and limits the complete normalized context to 48 KiB. Source hints
remain unverified. Draft edits, task details and historical revisions preserve the group.
SSE uses fetch with the authorization header, rather than putting a token in
an EventSource URL. Reconnect clients should refetch /api/tasks; SSE is an update
notification stream, not a durable event log.
Conversations
Send { "content": "Keep the alignment, but round the corners." } to the messages
endpoint. Content must contain 1–8000 characters. The server assigns the user
role; clients cannot inject assistant messages. A running turn or unresolved
conflict returns 409 without storing the attempted message.
Actions and messages also accept attempt, the version displayed by the client.
The in-page modal and dashboard send this value so a stale review cannot apply or
discard a newer version. A mismatch returns 409. CLI commands without this field
act on the latest version by task ID.
Agent replies cause a task SSE notification immediately, even before execution
finishes. Refetch the full task to read messages. A reply without any patch enters
awaiting_feedback and can accept another message. Existing tasks from the first
alpha retain their original request and latest available patch during migration;
earlier replies that were never stored cannot be reconstructed.
Each historical revision includes its attempt number, status, diff, files, validation results, base commit/branch and timestamp. Historical revisions are read-only. There is no endpoint that applies an obsolete revision.
Selection controls
GET /api/selection-controls returns saved controls, or null before the first save.
POST a complete version-1 preference with the current revision, pointer (button and
modifiers), keyboard (code and modifiers, or null) and optional additiveModifier.
The extra modifier accepts control, alt, shift, meta or null to disable it;
older preferences that omit it use Shift in the client. Pointer and keyboard behavior
remain unchanged when their existing modifiers already contain this key. Successful
saves increment the revision and broadcast selection-controls; stale saves return 409.
See selection controls for gestures and group limits.
Project context
GET /api/project-context returns { "version": 1, "revision": 0, "items": [] }
for a new repository. Save the complete library with its last-read revision:
{
"version": 1,
"revision": 0,
"items": [{
"id": "project-rules",
"kind": "instruction",
"title": "Project rules",
"content": "Use the project's existing spacing and color tokens.",
"source": "",
"default": true
}]
}
Kinds are instruction, skill and document. IDs are unique lowercase identifiers,
starting with a letter, using letters/digits/underscores/hyphens, up to 64 characters.
The server assigns item revision and updatedAt; unchanged items retain them.
A stale library revision returns 409 without overwriting another window's save.
Saving publishes a project-context SSE event containing only the library revision.
Limits: 32 items, 16 KiB of UTF-8 text per item, title 120 characters, source label 180
characters, serialized library 128 KiB, serialized task snapshot 48 KiB. The save route
accepts HTTP bodies up to 256 KiB before normalization. Defaults must fit the snapshot
budget. source is only a label, never a filesystem path to read or a URL to fetch.
Creation accepts optional contextIds: ["project-rules"]; omission selects defaults,
while [] selects nothing. On follow-up, omitted IDs retain the exact previous
snapshot; explicit IDs resolve the latest saved library. Missing IDs return 400 and an
oversized selection returns 413 before storing a task or advancing its conversation.
Retry retains the previous snapshot even if library items have since been deleted.
Full tasks and historical revisions contain projectContext with version,
libraryRevision, capturedAt and complete selected items. Legacy revisions may
have no snapshot. List/SSE task summaries and revision summaries omit attachment text;
fetch the individual task or revision to inspect it. Client-supplied snapshots are ignored.
The common agent prompt distinguishes user-selected instructions/skills from reference material. This is a prompt boundary, not an execution sandbox or a guarantee of provider compliance. Importing a skill's text does not install tools, scripts or referenced assets.
My Style
GET /api/my-style returns {version:1,revision,profiles,activeId,dismissed,suggestions,guides}.
Suggestions and Markdown guides are computed locally. POST /api/my-style accepts the
last-read revision, action, and fields below (64 KiB body limit):
| action | Fields |
|---|---|
save |
profile: ID beginning style-, name, direction, matching branch, tokens, rules, notes |
import |
profile with a new ID; imported evidence is discarded |
publish |
profileId; refresh its generated Project context instruction |
activate |
profileId; publish and use for new changes by default |
deactivate |
Clear the default style; retain profiles and context history |
delete |
profileId; remove the profile and generated context item |
accept |
profileId, suggestionId, explicit scope; recheck current applied evidence |
dismiss |
suggestionId |
reset-dismissed |
Show dismissed patterns again |
Scope is global, buttons, inputs, headings, or surfaces. Server-generated profile
versions and rule evidence cannot be forged by imports. Stale revision/evidence returns 409;
invalid preferences return 400. Profile and Project context changes commit atomically and
emit my-style and, when changed, project-context revision events. Open/reload the editor
to fetch current values; open unsaved drafts are not overwritten by events.
Applying a profile is a UI flow: publish it, then create an ordinary frontend draft/request
with its my-<profileId> in contextIds. The API does not directly execute a style operation.
See My Style for the builder, evidence boundaries, export format and limits.
Agent registry
GET /api/status includes agents: configured IDs, display labels, transport names
and current integration capabilities (automatic, streaming, resume, images).
Executable paths and arguments are not returned. These are configured integrations,
not proof that a provider is installed or authenticated.
Task creation accepts an optional agent ID. An unknown ID returns 400 before a
task is stored. Omission uses defaultAgent. The choice is persisted on the task
and retained by follow-ups. The browser cannot provide commands or switch the
provider of an existing conversation. Runtime protocol versions are independent of
this temporary HTTP API; see agents.
Appearance and shutdown
GET /api/appearance returns the saved appearance document or null for defaults.
POST /api/appearance validates and saves a version-1 theme, then broadcasts appearance
with that document. Both require the same token/Origin checks as task APIs. Appearance
payloads have a separate 2 MiB limit; uploaded WOFF/WOFF2 data totals at most 1 MiB.
See appearance schema. No uploaded-font URL is exposed without authentication.
Clients refetch preferences after reconnecting. The last save wins; unsaved local previews
are not broadcast. No account-level or cross-repository synchronization is provided.
POST /api/shutdown with {} stops the server and cancels active agents. The Rust CLI's
stop command uses it. GET /api/status additionally reports runtime: "rust".
Drafts and execution control
Creation accepts kind (frontend, backend, tests, documentation, general),
draft: true and up to 32 references. Element context is optional. Requests are limited
to 8000 characters. Drafts do not snapshot source, create worktrees or execute anything.
POST /api/tasks/QA-1/draft accepts the same fields plus attempt; it records the previous
version and increments the draft attempt. POST /start captures the current workspace.
Execution-disabled servers return 403 for execution, start, follow-up and retry requests.
validationStatus is not_run, not_configured, running, passed or failed.
setupChecks records preparation separately. An empty check list never implies a pass.
Applied tasks include an undo before/after record; older tasks may not have one.
Interrupted Apply/Undo becomes recovery_required. See recovery.
Route review
GET /api/route-review returns {version:1,revision:0,origin:"",routes:[],...} initially.
POST accepts the last-read revision and one operation:
| action | Fields |
|---|---|
scan |
origin: exact configured loopback origin; starts a fresh checklist |
add |
path: concrete URL path without query or fragment |
resolve |
id, path: map a route candidate to a real URL |
remove |
id: exclude a route from coverage |
review |
id, viewport (desktop/mobile), status (pending/reviewed/blocked), width, optional note |
Review notes are limited to 2000 characters; blocked records require a reason. Reviewed
records require a concrete path and a width of 320–480 px for mobile or 1024–2560 px for
desktop. The server records time and method: manual-browser-review. It validates record
shape and width, not the truth of a human review. Stale revisions return 409. The selected
origin is never fetched by Rust; the browser loads the preview. Coverage semantics.
To confirm an emulated device view, send method: "device" and the current sessionId
with the review request. The server verifies the live browser session, matching URL and
Desktop/Mobile category, and completed document load. It obtains width/settings from its
owned session, allowing landscape and tablet widths. It records method: "manual-device-emulation"
and a device evidence object. Client-supplied evidence is ignored. This verifies the
browser context; the user still judges page correctness. Old sessions and redirected or
closed tabs return 409. Requests with no method or method: "embedded" retain layout-only
manual review behavior for existing clients.
Device preview
GET reports available, browser, profiles and nullable session. It never starts a
browser. doctor/diagnostics also include metadata-only deviceBrowser availability.
POST accepts either { "action": "close" } or:
{
"action": "open",
"origin": "http://localhost:3000",
"path": "/settings",
"profile": "phone",
"orientation": "portrait"
}
Profiles are phone-small, phone, phone-large, tablet and desktop. Orientation is
portrait or landscape; desktop is always landscape. The origin must be an explicitly
allowed loopback origin and the path must be concrete without query/fragment. The body
limit is 4 KiB. Only one owned browser session exists per repository server; opening again
updates its tab and generates a fresh session ID. The API accepts no executable, arbitrary
browser arguments, script, CDP command, external debugging endpoint or user profile.
These endpoints remain available with agent execution disabled. Opening explicitly launches a browser, never an agent or project command. Close and graceful server shutdown stop the owned process and clean its temporary profile. See device browser.
Saved Git versions
GET /api/versions returns {repository: {branch, head}, pending, history, identity}.
Pending entries contain id, attempt, request, files and validationStatus.
History contains versions created here with status (saving, saved, failed),
commit, branch, message, identity, at, changes, files and an optional error.
Internal tree/index hashes are not returned in history. GET task details includes
savedVersion for completed saves and versionSavePending for interrupted/in-progress saves.
Send {"changes":[{"id":"QA-1","attempt":1}]} to /api/versions/preview.
The result contains a random id, current repository, selected change summaries,
files, combined diff, suggestedMessage, identity and expiresInSeconds: 600.
The server retains the reviewed plan. A client cannot submit its own tree or file contents.
To confirm, send this to /api/versions/save:
{
"previewId": "the-returned-review-id",
"message": "Improve checkout spacing",
"identity": {"name": "Your name", "email": "your-private-email@users.noreply.github.com"}
}
The response is a saved-version record. Reusing its preview ID returns the same successful
commit. Invalid author/message fields return 400; stale reviews, incomplete selections,
active hooks and other Git conflicts return 409. Preview and save may take longer than
ordinary requests, particularly with configured signing. UI requests allow 150 seconds.
versions SSE events carry {changed:true} and prompt a fresh GET. These endpoints are
available in execution-disabled mode and never invoke an agent or push a branch.
Local workspace and GitHub
GET /api/workspace returns id, kind, ready, branch, head, branches,
defaultBranch, defaultSource, dirty: {staged, unstaged, untracked}, operation and
rootHint. Kinds are missing_git, no_repository, unavailable, nested_folder,
unborn, detached and ready. Counts are porcelain status entries, not lines. Status
polling disables optional Git index writes. /api/status includes this workspace plus
executionConfigured; effective executionEnabled also requires a ready workspace.
Initialize with {"confirm":true,"branch":"main"} (4 KiB limit). First-file discovery
returns {files, excluded, identity, repository}; review selected paths with
{"files":[".gitignore","src/app.ts"]} (64 KiB limit). The resulting plan uses
/api/versions/save and has initial: true, with an empty parent and changes list.
For branch changes send {"action":"create","name":"improve-checkout", "expected":{"branch":"main","head":"current-sha"},"carryChanges":false}.
switch instead selects an existing local branch; the body limit is 4 KiB. Successful
mutations emit workspace events with {changed:true}. External Git changes are polled
by clients and do not generate a server event on their own.
GitHub actions use POST /api/github with a 16 KiB body limit:
action |
Required fields / behavior |
|---|---|
connect |
username, method: "cli" or "token"; token method also needs token. Validates the selected identity. |
disconnect |
Clears the session credential and in-memory reviews. |
target |
repository: "owner/name"; verifies write access and records the selected repository. |
create |
account, name, Boolean private, confirm: true; explicitly creates an empty personal repository. |
refresh |
Reads remote branch/PR state and stores {branch, head, checkedAt, proposal}. |
preview |
Returns a server-held publication plan with id, account/target/visibility, branch/head/remoteHead, commits, files, diff, dirty counts and default-branch notice. |
publish |
previewId; checks the reviewed destination and pushes exactly that SHA without force. |
propose |
account, targetId, private, base, branch, head, title, body; requires the current version to be published. Reuses an existing open PR. |
merge-preview |
number; returns target/proposal, head/baseHead, diff, checks/status/reviewDecision and canMerge. Already merged returns {merged:true, proposal}. |
merge |
number, previewId, method: "merge", "squash" or "rebase"; rereads rules/checks/versions and uses an allowed repository method. |
GET /api/github returns {available, account, target, suggestedTarget, last} without
fetching remote state. Tokens are never returned or persisted. Target metadata includes
id, fullName, private, defaultBranch, url and allowed merge methods. Ten-minute
reviews are scoped to the current server session. github events contain only
{changed:true}; consumers refetch status. GitHub operations use bounded process/network
timeouts; browser requests allow five minutes. These endpoints work with agent execution
disabled. See Branch & publish for review limits and recovery.
Project library and managed previews
All endpoints below require the same local token, Host and Origin validation as task APIs.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/starter |
Local library, curated templates and prerequisite presence |
| POST | /api/starter/diagnose |
Goal/audience/data/accounts/payments/budget answers; deterministic recommendation |
| POST | /api/starter/plan |
answers, name, optional parent and template; review a new directory and file list |
| POST | /api/starter/create |
previewId, confirm: true; create the reviewed project |
| POST | /api/starter/import |
Absolute path, confirm: true; add a local project |
| POST | /api/starter/open |
Library id; return an owned workspace's authenticated dashboard URL |
| POST | /api/starter/close |
Library id; close the owned workspace and previews |
| POST | /api/starter/remove |
id, confirm: true; close and remove membership, preserving project files |
| POST | /api/starter/pick-folder |
Open the optional native folder chooser; return a path or cancellation |
| GET | /api/preview |
Recipe, prerequisites and installation/preview state |
| POST | /api/preview/review |
action: install, start or restart; inspect fixed command and project script |
| POST | /api/preview |
previewId, confirm: true; execute a current reviewed operation; or action: stop |
Project plans and command reviews expire after ten minutes. The server retains their actual contents; clients cannot replace them during confirmation. Project-command reviews include a configuration fingerprint and reject changes before execution. Returned workspace/preview URLs contain local tokens in fragments; treat them as private credentials. The endpoints never accept arbitrary shell commands, template URLs or browser executable arguments. See project starters for execution modes and supported preview stacks.