Annotask serves its local API under /__annotask/ in development.
- CORS is limited to local origins such as
localhost,127.0.0.1, and::1 - mutating requests from non-local origins are rejected
- request bodies are capped at 4 MiB
- screenshots are served from
/__annotask/screenshots/*outside the/apinamespace
HTTP errors use:
{
"error": {
"code": "validation_failed",
"message": "status: Invalid status. Must be one of: pending, in_progress, applied, review, accepted, denied, needs_info, blocked"
}
}Current error codes:
invalid_jsonbody_too_largebody_not_objectvalidation_failedinvalid_transitionforbidden_originorigin_port_mismatch(agent spawn routes only — origin must match the server's own port)not_foundmissing_fieldinvalid_idinvalid_body
Canonical task types:
annotationsection_requeststyle_updatetheme_updatea11y_fixerror_fixperf_fixwireframe_apply— created by the wireframe palette's "Build this route" or by the design-session apply path ("Apply now" / "Implement this wireframe").context.wireframecarries{ route, instances[] }; each instance has ananchor(file,line,position,component,targetTag) and aninsertedpayload (tag,componentName,library,module,props,classes,text_content).context.session(when present) carries{ session_id, entries[] }— the design-session edits and/or wireframe directions. Applied via theWIREFRAME_APPLY.mdcompanion playbook.
There is no dedicated task type for backend-contract work; it surfaces as annotation tasks grounded with data_context and runtime-endpoint evidence.
Statuses:
pendingin_progressappliedreviewaccepteddeniedneeds_infoblocked
Typical lifecycle:
pending -> in_progress -> review -> accepted | denied
\-> needs_info
\-> blocked
applied is also a valid intermediate status.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/status |
health check |
GET |
/__annotask/api/report |
current live change report |
GET |
/__annotask/api/config |
current design-spec-backed config payload |
GET |
/__annotask/api/design-spec |
current design spec |
GET |
/__annotask/api/performance |
latest stored performance snapshot |
POST |
/__annotask/api/performance |
store a performance snapshot |
GET |
/__annotask/api/system-prompt |
composed embedded-agent system prompt (?task_type= adds the matching companion playbook) |
GET |
/__annotask/api/style-guide |
contents of .annotask/STYLE_GUIDE.md (init wizard review step) |
GET |
/__annotask/api/read-file |
read one project file by relative ?path= (traversal-guarded to the project root) |
DELETE |
/__annotask/api/session-reset |
clear the .annotask/.session-reset sentinel after the shell wipes localStorage |
Notes:
reportsupports?mfe=NAMEreportcan includeperformancewhen a snapshot existsstatusreportssessionReset: truewhile the.session-resetsentinel exists on disk
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/tasks |
list tasks |
POST |
/__annotask/api/tasks |
create a task |
GET |
/__annotask/api/tasks/:id |
fetch one task |
PATCH |
/__annotask/api/tasks/:id |
update a task |
DELETE |
/__annotask/api/tasks/:id |
delete a task |
GET /tasks supports ?mfe=NAME.
POST /tasks accepts these user-settable fields:
typedescriptionfilelinecomponentmferouteintentactioncontextviewportcolor_schemeinteraction_historydata_contextscreenshotscreenshot_metavisual
Server-controlled fields such as id, status, createdAt, and updatedAt are generated automatically.
PATCH /tasks/:id currently accepts:
statusdescriptionnotesscreenshotfeedbackintentactioncontextviewportcolor_schemeinteraction_historydata_contextscreenshot_metamfeagent_feedbackblocked_reasonresolution
Transitions are validated server-side.
| Method | Path | Purpose |
|---|---|---|
POST |
/__annotask/api/screenshots |
upload a base64 PNG |
GET |
/__annotask/screenshots/:filename |
fetch a stored screenshot |
Screenshot uploads must be PNG data URLs and are limited to 4 MiB.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/components |
detected component libraries |
GET |
/__annotask/api/component-usage |
project usage index for detected components |
GET |
/__annotask/api/component-examples/:name |
real in-repo usage examples |
GET |
/__annotask/api/workspace |
workspace packages and discovered MFE ids |
workspace omits internal absolute paths and returns workspace-relative package dirs.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/code-context/:taskId |
source excerpt for a task |
GET |
/__annotask/api/source-excerpt |
direct file-and-line excerpt |
Query params:
context_linesdefaults to15, max200source-excerptalso acceptsfileandline
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/data-context/:taskId |
stored or freshly resolved task data context |
GET |
/__annotask/api/data-context/probe |
quick probe for whether data context is worth offering |
GET |
/__annotask/api/data-context/resolve |
resolve file-and-line data context |
GET |
/__annotask/api/data-context/element |
resolve element-focused data context |
GET |
/__annotask/api/data-sources |
project data-source catalog (?include_runtime=true to append the runtime-observed catalog) |
GET |
/__annotask/api/data-source-examples/:name |
in-repo usages for a data source |
GET |
/__annotask/api/data-source-details/:name |
definition-level detail for a data source |
GET |
/__annotask/api/data-source-bindings/:name |
binding graph used for page highlights |
Useful query params:
kindlibrarysearchused_only=true|1limitfilecontext_linesinclude_runtime=true|1(data-sources)
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/runtime-endpoints |
aggregated runtime-observed endpoints (iframe fetch/XHR/beacon calls) |
POST |
/__annotask/api/runtime-endpoints |
ingest iframe network-call observations |
DELETE |
/__annotask/api/runtime-endpoints |
clear the runtime catalog |
Useful query params:
merge_static=true|1— enrich rows with matching static sources and OpenAPI operationsroute=PATH— filter to endpoints observed on a specific iframe routeorphans_only=true|1— only rows with no matching static source (surfaces gaps the static scanner missed)
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/tasks/:id/interaction-history |
per-task pre-task user-trace sidecar (route + ~20 recent actions) |
POST |
/__annotask/api/tasks/:id/interaction-history |
write the sidecar for a task |
GET |
/__annotask/api/tasks/:id/rendered-html |
per-task outerHTML snapshot of the selected element (200 KB cap) |
POST |
/__annotask/api/tasks/:id/rendered-html |
write the sidecar for a task |
Both sidecars are written server-side on task create whenever the shell has them. The in-shell "Embed" toggles only decide whether the payload rides inside the task JSON; when unembedded, agents retrieve from the sidecar endpoint. Rendered-HTML reads include a source field (embedded vs sidecar) and fall back to { rendered: null, not_captured: true } when the task has no selection.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/api-schemas |
discovered schema catalog |
GET |
/__annotask/api/api-operation |
one operation by path |
GET |
/__annotask/api/resolve-endpoint |
best-match operation for a concrete URL |
Schema sources can include:
- OpenAPI
- GraphQL
- tRPC
- JSON Schema
Useful query params:
kinddetail=true|1pathmethodschema_locationurl
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/wireframe |
full multi-route wireframe document, or one route's slice with ?route=PATH |
PUT |
/__annotask/api/wireframe |
replace the whole document (the shell owns the in-memory merge) |
POST |
/__annotask/api/wireframe-snapshots |
upload a canvas block PNG ({id, data}; id-addressed, 4MB cap) |
GET |
/__annotask/wireframe-snapshots/:filename |
serve a canvas snapshot PNG (containment-guarded) |
DELETE |
/__annotask/api/wireframe-snapshots/:filename |
drop a canvas snapshot PNG |
GET PUT DELETE |
/__annotask/api/design-session |
design-session journal (CAS on rev, 409 on stale writes); DELETE discards the journal, session-created placements, and every route's canvas sketch |
POST |
/__annotask/api/design-session/apply |
snapshot the touched files and mint one wireframe_apply task (placements + design-session edits/directions); the embedded agent then writes source |
POST |
/__annotask/api/design-session/undo-batch |
restore the newest apply batch's pre-apply bytes (hash-guarded) |
POST |
/__annotask/api/design-session/detach-file |
diverged-file resolution: keep the disk bytes, drop the file from the session |
GET |
/__annotask/api/design-session/snapshots |
snapshot-engine state (touched files, divergence, apply batches) |
The document persists to .annotask/wireframe.json and is shape-validated ({ version: "1.0", updatedAt, routes[] }) on PUT. Snapshot PNGs live in .annotask/wireframe-snapshots/ (orphans GC'd at boot). The design-session journal persists to .annotask/design-session.json; "Apply now" / "Implement this wireframe" snapshots the touched files first so undo/discard stays byte-exact — the agent writes source, the tool only snapshots and restores.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/agent-configs |
per-persona project directions and provider preferences from .annotask/agents.json |
PATCH |
/__annotask/api/agent-configs/:id |
update one persona's projectDirections, providerId, model, or effort |
| Method | Path | Purpose |
|---|---|---|
POST |
/__annotask/api/agent/spawn |
spawn an allow-listed local CLI (claude / codex / opencode / copilot) and stream stdout/stderr back as SSE |
DELETE |
/__annotask/api/agent/spawn/:runId |
abort a running spawn by run id |
GET |
/__annotask/api/agent/detect |
detect which local CLIs are installed and logged in |
GET |
/__annotask/api/agent/models |
per-provider model catalog for ?cli=ID (?refresh=1 bypasses the 5-min cache) |
The spawn routes enforce a stricter same-port origin check on top of the general localhost gate — a page on a different localhost port cannot spawn CLIs that have credential access (origin_port_mismatch). When ANNOTASK_MAX_PERMISSION is set to plan or default, the server refuses any spawn that exceeds it. The default is no ceiling (bypass).
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/tasks/:id/messages |
full per-task conversation snapshot (optional ?after=<id>) |
POST |
/__annotask/api/tasks/:id/messages |
append a message; broadcasts to subscribers |
GET |
/__annotask/api/tasks/:id/messages/stream |
SSE stream; honours Last-Event-ID for resume |
PATCH |
/__annotask/api/tasks/:id/messages/:msgId |
update a message in place (used to flush a partial assistant turn while it streams) |
Threads persist as append-only JSONL at .annotask/conversations/<taskId>.jsonl.
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/usage |
aggregate token-usage totals, per-scope and per-provider, from .annotask/usage.jsonl |
GET |
/__annotask/api/usage/recent |
most recent usage entries, newest first (?limit=N, default 50, max 500) |
| Method | Path | Purpose |
|---|---|---|
GET |
/__annotask/api/init/state |
current init-runner state |
GET |
/__annotask/api/init/scan-targets |
existence + mtime of the durable scan artifacts (design-spec.json, agents.json) |
POST |
/__annotask/api/init/start |
start an init scan (body can skip individual scanners and pin provider/model/effort) |
POST |
/__annotask/api/init/cancel |
cancel a running scan |
POST |
/__annotask/api/init/skip |
mark the project initialized without committing token data |
POST |
/__annotask/api/init/commit |
commit the reviewed spec (and optionally a style guide) to .annotask/ |
Connect to ws://localhost:<port>/__annotask/ws.
Messages are JSON objects with event, data, and timestamp.
Server-to-client events:
| Event | Payload |
|---|---|
report:updated |
full AnnotaskReport |
report:current |
full AnnotaskReport |
changes:cleared |
null |
tasks:updated |
task list payload |
designspec:updated |
null |
components:updated |
{ scannedAt } — a background component scan landed a fresh catalog |
init:progress |
init-runner step state for the wizard |
runtime-endpoints:updated |
current runtime endpoint catalog |
wireframe:updated |
saved wireframe document (null when invalidated from disk) |
session:updated |
null — broadcast when .annotask/design-session.json changes |
Client-to-server events:
| Event | Payload |
|---|---|
report:updated |
full AnnotaskReport |
changes:cleared |
{} |
get:report |
{} |
POST /__annotask/mcp implements Streamable HTTP MCP over JSON-RPC 2.0.
Current tool surface:
annotask_get_tasksannotask_get_taskannotask_update_taskannotask_create_taskannotask_delete_taskannotask_get_design_specannotask_get_componentsannotask_get_componentannotask_get_screenshotannotask_get_code_contextannotask_get_component_examplesannotask_get_data_contextannotask_get_interaction_historyannotask_get_rendered_htmlannotask_get_data_sourcesannotask_get_runtime_endpointsannotask_get_api_schemasannotask_get_api_operationannotask_resolve_endpointannotask_get_data_source_examplesannotask_get_data_source_detailsannotask_get_source_excerptannotask_get_binding_classificationannotask_get_playbookannotask_get_agent_directionsannotask_conversation_readannotask_conversation_postannotask_conversation_subscribe
Behavior differences from raw HTTP:
- task lists return summaries by default
- the shell-only
visualfield is stripped - older
agent_feedbackentries are trimmed from single-task reads - arguments are validated at the tool boundary
The live report's changes[] union currently includes:
style_updateclass_updatescoped_style_updateexperimentalcomponent_prop_updateexperimentalcomponent_insertcomponent_movelegacy — no longer emitted (the Reposition tool was removed); agents still apply it from older reportscomponent_deleteexperimentalannotationsection_requestlegacy — no longer emitted (sections are wireframe sketch material ridingwireframe_applyadd directions)
The canonical definitions live in src/schema.ts.