Documentation

Everything you can do with Forward.

Forward keeps your UI design, backend documentation, architecture, data models and project work together as plain JSON in .forward/, inside your own git repository. You author it from the canvas, VS Code, or an AI agent. This guide walks through every layer and every surface.

Start here

Getting started

Set Forward up in an existing repository, open the canvas, commit the project, and connect your editor and agents.

  1. Install the CLI. Forward needs Node 22 or newer. Install it globally with npm i -g forward-mcp, which adds two commands to your PATH: forward-mcp (the MCP server) and forward (the CLI). Or skip the install and prefix each command with npx -y -p forward-mcp.
  2. Initialize your repository. In the repository root, run forward init. It creates .forward/, the agent wiring (AGENTS.md, CLAUDE.md, .mcp.json, .cursor/mcp.json) and the GitHub workflow. --no-agents and --no-github skip those.
  3. Open the canvas. Run forward serve. It serves the design editor at http://127.0.0.1:4747 (add --open to launch your browser) and writes every edit straight to .forward/.
  4. Commit the project. Add .forward/ and the generated files and commit them with your code. From here on, Forward changes travel through branches and pull requests like any other change.
  5. Connect an agent. Claude Code and Cursor pick up the generated configs; for others see AI agents. Restart the agent session after adding the server.
  6. Install the VS Code extension. Get Forward on the VS Code Marketplace; it finds .forward/ in the open repository on its own (see VS Code extension).
# in the root of your repository (Node 22+)
npm i -g forward-mcp
forward init
forward serve # http://127.0.0.1:4747
git add .forward/ AGENTS.md CLAUDE.md .mcp.json .cursor/ .github/
git commit -m "Add Forward"
Just looking? The live demo opens the canvas on a sample project in your browser, with nothing to install.

What lands in your repository

The whole project is one directory, one file per record, so merges stay clean and pull-request diffs stay readable:

PathHolds
forward.jsonThe project manifest: id, name, format version.
design/<id>.jsonDesign elements, each with its optional apiBinding docs.
history/<elementId>/…Append-only API-doc history, one file per version.
infra/nodes, infra/edges, infra/flowsThe infrastructure graph and narrated flows.
data/entities, data/relationsThe ER data model.
agents/agents, agents/serversAgents and the MCP servers they call.
tasks/<id>.jsonThe task tracker.
checkpoints/<id>.jsonNamed, restorable snapshots of design and infra.
dismissed/<id>.jsonCode drafts someone deleted, so capture doesn't recreate them.
assets/<sha256>.<ext>Image bytes for image fills, named by their hash (PNG, JPEG, WebP, GIF or AVIF, up to 5 MB; location metadata stripped).

The project id is the id in .forward/forward.json. Every tool finds the project by looking for the nearest .forward/ above the current directory (or the repository named by FORWARD_REPO).

Mental model

Core concepts

Forward is built from seven intentionally-separate layers. The design layer is primary and stands on its own; every other layer is optional and either attaches to a design element or links to one by id.

Understanding these seven layers makes the rest of the product obvious: every feature is one of them, and every surface (canvas, VS Code, agent, CI) speaks the same shapes, validated by the same schemas on every read and write.

Seven layers: the design layer is primary; the API binding attaches to an element; infrastructure, entities and tasks are project-scoped and link by iddesign — the primary layerframePay nowPOST /api/checkoutapiBinding · markdown · versionedattachesinfrastructure + flowsproject-scoped graph · narrated hopsentities (ER)tables + crow's-foot relationstaskslink into any layercheckpointsrestorable snapshots of design + infralinks by id (soft)
fig 1 — the design layer stands alone; a binding attaches to an element; everything else is project-scoped and links by id.
LayerWhat it is
DesignThe frames, shapes, text, components and instances a designer draws, with geometry and a parent/child hierarchy. The primary artifact; everything else hangs off it.
API bindingAn optional title + Markdown description attached to a design element. Docs-first and framework-agnostic; an endpoint is never a first-class canvas object.
InfrastructureA project-wide graph of nodes (apps, services, databases, caches, queues) and edges, rendered as an overlay.
FlowsNarrated, ordered hops across the infra graph; a hop can tie to an endpoint. Serializes to a Mermaid sequence diagram.
Entities (ER)A project-wide data model of tables, fields and crow's-foot relations. Serializes to a Mermaid erDiagram.
TasksA tracker of work items that can each link into another layer: an element, a flow or an endpoint.
CheckpointsNamed, restorable snapshots of the whole canvas (design + infra), each with a note and per-layer change counts.

Links between layers are soft references, resolved on read and never enforced as foreign keys. forward validate reports dangling ones as warnings.

A related, project-scoped Agents layer lets you document the MCP servers and AI agents your project builds or consumes (see AI agents), modelled the same way as the seven above.

On top of the layers sit the timelines: a per-element history of documentation changes and a project event feed built from git log. Together they power the History view, doc diffs and the catch-up digest (see History & checkpoints).

Design layer

The design canvas

A design editor for the interface. Draw it, then let every other layer attach to what you drew.

The canvas is where the design layer lives and where the API, infra, data and task overlays render on top of it. Run it with forward serve, open it inside VS Code with Forward: Open Design Canvas, or browse the read-only copy your GitHub Pages site publishes.

The canvas: toolbar rail, layers tree, a selected element with its endpoint badge, the API drawer, zoom bar and live-sync indicatorforward / canvasLIVE SYNC− 100% + FitLAYERS▾ CheckoutframePay nowtotal-labelCheckoutPay nowAPIAPI DRAWERPOST /api/checkouthistory · v4+3 −1
fig 2 — the canvas shell: toolbar rail, layers tree, a selected element with its API badge, and the drawer.

Element types

Every element you draw is one of six types:

typeWhat it is
frameA container / screen; establishes hierarchy, nest anything inside it.
rectangleA generic box: buttons, cards, inputs.
ellipseA circle / oval, drawn within its bounding box.
textA text label.
componentA reusable master definition.
instanceA placed copy of a component (links back via componentId).

What an element stores

FieldMeaning
id, type, nameIdentity and the element type above.
x, y, width, heightAbsolute geometry in canvas space.
zStacking order among siblings: higher paints on top.
rotationDegrees clockwise about the element's center (default 0).
parentIdThe containing element, or null at the top level; this is the layer tree.
textText content (for text elements).
styleFill, stroke (width/style, per-side), corner radius (uniform or per-corner), font size/weight/family/color.
componentIdFor an instance: the source component's id.
apiBindingThe optional backend documentation attached to this element (see below).
originSet on drafts generated from frontend code (see Designs from code); gone once a draft is adopted.
updatedAtISO-8601 timestamp of the last write, stamped by Forward rather than the client.

Because geometry is absolute and hierarchy is a plain parentId, the layer rail reflects a real tree. Select an element to open its API drawer, inspect its overlays, or view its history.

Toolbar, overlays & view controls

The left rail doesn't hold drawing tools; shapes come from the keyboard or the right-click menu. Instead it toggles the panels and overlays that sit on top of the design:

ToggleOpens
LayersThe design-tree sidebar (the element hierarchy).
DocsEndpoint badges on documented elements + the API drawer.
InfraThe infrastructure graph overlay and its editing drawer.
DataThe entity/ER overlay and its editing drawer.
FlowsThe narrated flows as sequence diagrams (Mermaid), one per flow.
AgentsThe agent / MCP-server wiring diagram.
HistoryThe project timeline panel (see History).
TasksThe task-tracker panel.
ThemeThe view-theme editor: per-user, stored locally, never committed.
PeopleThe read-only list of git contributors (see Access & sync).

A zoom bar (− / + / Fit) sits over the stage, and a live-sync indicator shows the connection to the local server. Changes an agent writes through MCP while the canvas is open show up within a couple of seconds. Right-click anywhere on the canvas for the Add element menu: the same catalog the keyboard shortcuts arm, nested at the point you clicked.

Drawing & keyboard shortcuts

Select is the default mode. Press a tool key, then drag on the canvas to size the new element (single-key shortcuts; they're ignored while you're typing in a field):

KeyAction
VSelect / move.
FDraw a frame.
RDraw a rectangle.
ODraw an ellipse.
TAdd text.
⌘S / Ctrl+SSave a checkpoint (opens the save modal; see Checkpoints).
Delete / BackspaceDelete the selected element.
EscapeDeselect / close the open dialog.
Diagrams (infra, flows, ER) render with Mermaid inside the same view, and the GitHub Pages export renders the very same canvas, read-only.

API binding layer

API documentation

Attach framework-agnostic Markdown docs to any design element, so an endpoint stays tied to the interface it powers and the docs can't drift away from the UI.

An API binding is just a title and a Markdown description. Most elements never get one; the ones that do become the anchor for backend documentation. You can author bindings from the canvas, but the intended home is the VS Code extension and the MCP server, where the backend actually lives.

An API binding: a design element linked to its documentation card — title, markdown body and versionPay nowdesign elementapiBindingPOST /api/checkoutv4{ amount, currency }
fig 3 — a binding: two fields on an element. The Markdown body carries the meaning; every edit becomes a diff.

The binding shape

A binding is deliberately tiny, two fields:

FieldMeaning
titleA one-line label, e.g. POST /api/checkout.
descriptionThe full Markdown body: request/response shape, status codes, notes. Anything the reader needs.

That's it. There's no enforced HTTP method or path: you can write GET, POST, PUT, PATCH or DELETE in the title, or document a GraphQL resolver, a gRPC call, a CLI command or a background job the same way. The Markdown carries the meaning.

Why docs-first

  • Framework-agnostic. There's no OpenAPI import or route scanner to keep happy.
  • Tied to the UI. The doc is attached to the element it describes, so it's discoverable from the design.
  • Versioned. Every edit is appended to the element's history as its own file, with a reviewable, git-style diff (see History). Two branches that both document endpoints merge without conflicts.

Who wrote each version is decided by Forward, not the client: your git user.name (or FORWARD_AUTHOR), plus via <agent> when FORWARD_AGENT is set.

Infrastructure & flow layers

Infrastructure & flows

Model your architecture as one project-wide graph, then narrate how a request travels across it.

The infrastructure graph

Add nodes and connect them with edges. Unlike the design layer, the infra graph is project-scoped and isn't attached to any one element; it renders as its own overlay and serializes to a Mermaid component diagram. Each node has a kind that drives its colour and icon:

kindRepresents
frontendWeb / mobile client.
backendAPI server / app service.
databaseSQL / NoSQL store.
cacheRedis, Memcached…
queueKafka, SQS, RabbitMQ…
serviceInternal microservice.
devopsCI/CD, container, IaC, monitoring.
externalThird-party dependency.
actorA person (user, admin) who starts a journey; not a system component.
groupA container box that visually groups other nodes.

A node carries a label, an optional tech tag (e.g. "v15", "Node 20"), a Markdown description, geometry, and a parentId to nest it inside a group. An edge is just from → to node ids with an optional label.

Narrated flows

A flow has a name, a Markdown overview and an ordered list of steps. Each step is a hop from one infra node to another ("place order", "register", "checkout") and can carry an endpointId that ties the arrow to a documented endpoint (turning a generic arrow into "called by POST /auth/verify"). Every step has a call style:

kindMeaningMermaid arrow
syncA request that waits for a response.->>
asyncFire-and-forget / a publish.-)
replyA response back to the caller.-->>

A step can also carry an optional condition, a branch guard like "session valid" or "409 duplicate". Consecutive steps that share one condition render together as a Mermaid alt/else block, so a flow can show conditional paths, not just a straight line.

Flows render as numbered arrows across the graph and serialize to a Mermaid sequenceDiagram you can drop straight into a design doc. Agents get both diagrams as Mermaid from list_infra and list_flows.

A narrated flow: numbered hops across the infrastructure graph — sync request, async publish and a reply — exporting to a Mermaid sequence diagramweb clientfrontendcheckout-apibackendorders-dbdatabaseevents-queuequeue12ties to POST /orders34syncasyncreplyflow: place order → Mermaid sequenceDiagram
fig 4 — a narrated flow over the infra graph: numbered hops, one tied to a documented endpoint.

Entity layer

Data models

Entity-relationship diagrams with tables, fields and crow's-foot cardinality, versioned with the rest of the project.

Define entities (tables with fields) and relations between them. Like infra, the data model is its own project-scoped graph.

An entity-relationship diagram: USER places ORDER, exactly-one to zero-or-many, with primary, unique and foreign keysUSERiduuidPKemailvarcharUKnamevarcharORDERiduuidPKuser_iduuidFKtotalintplacesexactly-one → zero-or-many · identifyingexports to Mermaid erDiagram
fig 5 — two entities and a crow's-foot relation: USER places zero-or-many ORDERs.

Fields & keys

Each entity holds a list of fields, and every field has a name, a free-form type (e.g. "uuid", "varchar", "int"), an optional note, and zero or more key roles:

keyRole
PKPrimary key.
FKForeign key.
UKUnique key.

Relationships (crow's-foot)

A relation is directed (from → to entity), carries a verb label, and has a cardinality at each end:

cardinalityMeaning
zero-or-oneOptional single (|o).
exactly-oneRequired single (||).
zero-or-manyOptional many (}o).
one-or-manyRequired many (}|).

An identifying flag picks the line style: solid when the child can't exist without the parent, dashed otherwise. The whole model serializes to a Mermaid erDiagram, easy to review in a pull request, version alongside code, and keep next to the API docs and architecture it supports.

Task layer

Task management

Track the work next to the system it belongs to. Every task can link to a design element, a flow or an endpoint, for traceability from planning to implementation.

Status, type & priority

Three independent enums classify every task:

FieldValues
statustodo · in_progress · blocked · done
typebug · feature · task · milestone (a zero-duration marker, drawn as a diamond)
prioritylow · medium · high · urgent

What a task carries

FieldMeaning
key, titleA short human key (e.g. FWD-12) and the title.
descriptionFree-form Markdown detail.
labelsFree-form label names (e.g. "backend").
assignees, reporterThe people doing the work (contributor names from list_members), and who filed it, stamped from your git identity.
startDateOptional planned start, an ISO date (2026-11-02). Without it the timeline starts the task on the day it was filed.
dueDateAn ISO date (2026-11-06); for a milestone, its target date. A free-form label is rejected. Tasks filed before this rule keep their old label until it's changed, and forward validate warns about them.
dependsOnIds of tasks that should finish before this one starts (finish-to-start).
elementIdOptional link to the design element the task concerns.
flowIdOptional link to the narrated flow it implements.
endpointIdOptional link to the element whose apiBinding defines the endpoint.
activityChronological feed of comments and events (oldest first).
createdAt, updatedAtTimestamps stamped by Forward.
All three layer links are independent and optional, and they're soft references: a task may briefly point at a deleted element, and Forward tolerates that rather than blocking you. forward validate flags it as a warning.

Views

Work the list in the canvas's Tasks panel. Because tasks link into the other layers, you always know which design, flow or endpoint a piece of work maps to. Agents use create_task, update_task and comment_task on the same tracker.

Switch the panel to Timeline for a Gantt chart: each task is a bar from its start date to its due date, grouped by status and filled by progress; milestones are diamonds; and dependencies are connectors, drawn red when a task starts before something it depends on is due. The exported read-only site shows the same timeline. get_task_timeline returns the schedule as a Mermaid gantt chart with its warnings, and the PR digest lists tasks whose dates moved. forward validate warns about dependency cycles, and about assignees who aren't on the contributor roster.

Timelines & snapshots

History & checkpoints

The project remembers everything: every documentation edit is a reviewable diff, the activity feed is your git log, and you can snapshot and restore the whole canvas.

The History timeline

Two timelines drive it: an append-only, per-element history of API documentation (one file per version under .forward/history/), and a project event feed built from git log plus your uncommitted changes, so commit messages show up in it. Forward flattens them into one chronological stream, lays it out as a git-graph, and colours each event by the layer it came from:

domainSource
designDesign-element changes.
apiAPI binding (documentation) changes.
infraInfrastructure node/edge changes.
flowNarrated flow changes.
agentAgent / MCP-server changes.

Each event records its action (created, modified or deleted) plus the author, timestamp and a one-line detail, so you can see who changed what, when, across every layer.

The History view: a git-graph of events coloured by layer, next to a doc diff card with added and removed lines and a breaking-change flagapi · POST /orders modifiedkwame · 2h agoinfra · events-queue addedagent · 5h agodesign · Pay now createdama · 1d agoflow · flow "place order" editedkwame · 2d agoPOST /orders+3 −1++−+⚠ breaking change
fig 6 — the History git-graph, coloured by layer, beside a doc diff with a breaking-change flag.

Doc diffs

Each edit to an API binding is a git-style diff: a title change plus a line-level Markdown diff between two versions. Expand any revision to review exactly what moved: added rows are green, removed rows red, and a +a −r badge summarizes the change on the collapsed card. A diff can also be flagged breaking, which surfaces a warning callout so consumers know clients may need changes. Even a deleted endpoint stays labelled, because each history entry keeps a snapshot of the endpoint as it was written.

Catch-up digest

Pick a baseline (the last day, week, month, or all time) and Forward collapses the event stream into a digest of what's to integrate, to modify and to remove: the fast way for a frontend dev to catch up on backend changes. The canvas timeline and get_catchup_digest show the same digest.

To compare against a git ref instead, run forward diff origin/main (any branch, tag or commit). It lists new, changed and removed endpoints with doc diffs, plus a per-layer summary of everything else, as Markdown or JSON. Agents call the same comparison as get_changes_since_ref, and the GitHub Action posts it on every pull request.

Checkpoints

A checkpoint is a deliberate, whole-canvas save: a title, a Markdown note, and a frozen copy of the design + infra graph you can restore later. Create one from the canvas with the Save button or ⌘S / Ctrl+S. Each is tagged milestone, checkpoint or wip, and its card shows per-layer change counts (e.g. DESIGN +8 API +3). Checkpoints are files too (.forward/checkpoints/), so they're committed and shared like everything else.

A restore rewinds the design + infra graph only. Your per-user view settings (theme, grid) aren't touched, and git still holds every earlier state if you need to go further back.

Design layer · from code

Designs from code

Ideally the frontend is built from the design. When a screen was built first, Forward can draw it for you from the running app.

forward capture renders your running frontend, reads back what the browser actually painted (position, size, colours, borders, corners, fonts, text, stacking) and turns it into canvas elements: one frame per route, a box for everything that paints, text for every run of text. Wrappers that paint nothing are dropped, so the layer tree stays readable. React dev builds also report which component rendered each node, so repeated components become a component plus instances.

forward capture --browsers # which browsers it can use here
forward capture http://localhost:5173 / /login /settings --dry-run
forward capture http://localhost:5173 / /login /settings
forward capture http://localhost:5173 /settings --auth state.json --viewport 390x844
forward capture http://localhost:5173 / --browser edge

Which browser it uses

EngineWhen
The project's PlaywrightUsed first when the project has Playwright installed.
An installed Chromium browserChrome, Edge, Brave, Chromium, Vivaldi or Opera. Nothing is installed or downloaded. It runs headless with a fresh, temporary profile (never your own cookies, logins or extensions), is controlled over a pipe so nothing listens on the network, and is closed with its profile deleted when the capture ends.
The forward-capture companionOnly when there is no Playwright and no Chromium browser (a server, a container, some CI). It runs npx -y forward-capture@<version> at the CLI's exact version and downloads Playwright's headless Chromium once (about 100 MB); npx -y forward-capture install fetches it ahead of time.
Any browser, by handFirefox and Safari can't be driven this way. forward capture --script prints a snippet to paste into the DevTools console; it downloads forward-snapshot.json, which forward capture --from forward-snapshot.json imports.

--browser picks one explicitly (a name or a path), FORWARD_BROWSER sets the default, and FORWARD_NO_DOWNLOAD=1 forbids both downloads. Agents call the same capture as import_design_from_code.

Drafts, and what a re-capture never does

  • Drafts. Generated elements are marked from code on the canvas. Re-running a capture updates them in place, and API docs attached to a draft are kept.
  • Stable identity. An element keeps its identity by its data-testid, id, the JSX line that rendered it (React dev builds) or its aria-label; failing those, by its position under the nearest element that has one. When the page around a draft shifts, drafts are re-matched by type, name or text, size and contents, as long as the match is unambiguous.
  • Docs never move on a guess. If a documented draft can't be matched for certain, it stays where it was (stale, docs intact) and the capture reports it. Test ids on repeated or generic elements make identity certain.
  • Edits win. A draft someone has moved, restyled or renamed is never overwritten; the import reports it as a conflict. Adopt draft (inspector or right-click menu) turns a draft into an ordinary element that imports never touch again.
  • Deletions stick. Deleting a draft remembers it in .forward/dismissed/, so the next capture doesn't bring it back; --restore does.
  • Stale drafts. Drafts the code no longer renders are reported as stale. --prune removes them, but never one that is documented, edited, adopted, or holds something that stays.
  • Anchors, opt-in. --anchors adds // @adc <id> markers above each component's declaration in your JS/TS source, so resolve_anchors links code to design. It edits source files, so it is off by default.
Use development data. A capture records what the page shows, so run it against development or seed data, not real customer data. Password fields are always masked. --auth state.json loads a saved browser state for pages behind a login.

Surface · editor

VS Code extension

Document the backend where the backend lives. Attach Markdown docs to design elements without leaving your editor.

  1. Install the extension. Get Forward from the VS Code Marketplace and open your repository.
  2. Initialize, if needed. If the repository has no .forward/ yet, run Forward: Initialize Project in This Repository, or forward init in a terminal (which also writes agent configs and the GitHub workflow).
  3. Document. Use the Forward commands to document an endpoint on an element, edit infra, flows and agents, and file, schedule or update tasks, all from the editor. What forward validate would flag in CI shows in the Problems panel as you work. Insert Anchor at Cursor drops an @adc comment (pick the element by name) so the code↔element link lives in the source: the same anchor CI and MCP agents resolve.
The VS Code extension: the command palette filtered to Forward commands, an @adc anchor comment in the source, and the status bar showing the repository's projectcheckout.ts — forward-shop// @adc el_7f3arouter.post("/api/checkout", async (req, res) => {const order = await createOrder(req.body);res.status(201).json(order);});> forwardForward: Document API on Design ElementForward: Catch Up on Endpoint ChangesForward: Create TaskForward · shop · .forward/TypeScript
fig 7 — Forward in VS Code: the command palette filtered to Forward commands, a deterministic @adc anchor in the source, and the status bar.
Nothing to configure. The extension works on the open repository's .forward/ in-process. There is no server URL or project picker, and access is whatever your git host grants.

Everything you write is a file change in .forward/. Commit it with the code it describes, and the canvas, your teammates and any agent read the same files. Open Design Canvas shows the design with your API docs and diagrams overlaid, right inside VS Code, and its Timeline opens the endpoint git-graph and catch-up digest.

Surface · AI agents

AI agents (MCP server)

Give any AI assistant full parity with the canvas and the extension: 49 tools over the same .forward/ files, over MCP or from the shell.

The forward-mcp server exposes 49 tools so an agent can create and maintain every artifact (documentation, architecture, data models, tasks, even the design) exactly as a human contributor does. It runs over stdio from the repository root and finds the nearest .forward/; there is nothing else to configure. The full list is in the reference.

Connect it

forward init (or forward agents later) writes the wiring into your repository:

FileFor
AGENTS.mdInstructions every agent reads: when and how to document endpoints, infra and schema.
CLAUDE.mdImports AGENTS.md for Claude Code.
.mcp.jsonRegisters the Forward MCP server for Claude Code.
.cursor/mcp.jsonRegisters it for Cursor.
.vscode/mcp.jsonRegisters it for VS Code / Copilot (forward agents --vscode).

To register by hand with Claude Code, run this from the repository root (the extension's Forward: Set Up MCP for AI Agents copies the same line):

claude mcp add forward -- npx -y forward-mcp

Codex reads AGENTS.md; register the server in ~/.codex/config.toml:

[mcp_servers.forward]
command = "npx"
args = ["-y", "forward-mcp"]
env = { FORWARD_AGENT = "codex" }

Any other MCP client runs npx -y forward-mcp over stdio. Set FORWARD_REPO only when the client doesn't start the server inside the repository, and FORWARD_AGENT to tag writes with the agent's name.

After registering, restart your agent session. A session that was already running won't load the Forward tools until it reconnects. That's MCP-client behaviour, not a Forward setting.

Without MCP: the same tools from the shell

The CLI calls the very same tool code in-process, so a script or an agent without MCP gets identical behaviour:

forward tools # list all 49 tools
forward tools write_documentation # one tool's arguments
forward call write_infra_node '{"kind":"cache","label":"Redis"}'
forward call get_changes_since_ref '{"ref":"origin/main"}'

Any tool also runs as a command of its own, with its arguments as flags; forward tools <tool> lists them.

Finding the right element

Good first calls are project_info, find_element, write_documentation, validate_project and get_changes_since_ref. There are two ways to answer "which design element does this code belong to?":

  • Fuzzy: find_element. Ranks elements against a feature description. No setup, but confirm with the user when the score is low or two candidates are close.
  • Deterministic: resolve_anchors. Resolves @adc <elementId> markers in your source to their elements, and flags anchors whose id doesn't exist, catching typos and stale links.
The MCP surface: an AI agent calls the forward-mcp server's tools over stdio; the server reads and writes the .forward/ files in the repositoryAI agentClaude Code · any MCP clientforward-mcp49 tools · stdioFORWARD_AGENT=claudeFORWARD_REPO (optional).forward/files in your repotool callsread / write# the agent documents what it just built find_element("pay now button") → el_7f3a (fuzzy match)write_documentation(el_7f3a, "POST /api/checkout", …)update_task(FWD-12, "done") → file changes, committed with the code
fig 8 — an agent working through forward-mcp: fuzzy element resolution, then documenting and closing out the task it implemented.

Document the agents your project uses

Beyond connecting an agent, Forward has an Agents layer for documenting the AI surface your project builds or consumes, its own project-scoped graph like infrastructure. You can model:

NodeWhat it captures
MCP serverA label, transport (stdio · http · sse), origin (built by your project vs consumed third-party), and the list of tools it exposes.
MCP toolA name + Markdown description; an optional endpointId ties the tool to the documented endpoint it wraps.
AgentA label, the model it runs on, a diffable systemPrompt, and the ids of the MCP servers it's wired to.

An agent's system prompt versions and diffs in the History timeline like an API binding, so your agent definitions get the same reviewable history as the rest of the project.

Git-native

Access & sync

There is no central server and no database. Git is the sync, the history and the access control.

Every surface speaks one REST contract. Forward serves it from the files in .forward/: in-process for the MCP server, CLI, VS Code extension and CI, and over a small local HTTP server that forward serve runs for the canvas.

Three surfaces — the canvas, VS Code and an AI agent — all read and write the same .forward/ files in the repository, and git carries them to the rest of the teamcanvaslocal server · 127.0.0.1VS Codeextension · in-processAI agentMCP · CLI · 49 tools.forward/ in your repoone file per record · validated by one schemagit commit · pull request · merge: the team stays in sync
fig 9 — every surface reads and writes the same .forward/ files; git carries them to the rest of the team.

Who can change the project

  • Push access is edit access. Whoever can push to the repository can change the project, and branch protection and required reviews apply to .forward/ like any other path.
  • The roster comes from git. The canvas's People view and list_members list everyone who has committed to .forward/, with .mailmap applied. To assign work to someone before their first commit, declare them with add_person (a file in .forward/people/); it grants no access. A shallow clone sees only part of the history, and says so.
  • Authorship is stamped, not claimed. An author a client sends is ignored. Your git user.name decides who wrote it (FORWARD_AUTHOR overrides, and FORWARD_AGENT appends via <agent>).

How changes travel

Edits land as file changes in your working tree. Everyone on the same checkout (you on the canvas, an agent over MCP, the VS Code extension) sees them straight away; everyone else gets them through commits, pull requests and merges, exactly like code. One file per record and separate history files keep those merges clean, and git checkout -- .forward/ is the undo.

The local canvas server

forward serve keeps no user list, so it defends itself instead:

  • It binds to loopback (127.0.0.1) by default.
  • Every API call must carry a random per-session key that only the served page knows, so another site can't drive it.
  • It rejects unexpected Host headers, which defeats DNS rebinding.
--host 0.0.0.0 (or ::) exposes the canvas on your network and turns off the Host check. Anyone who can reach the port can open the page and edit the project, and so can any website you visit while it runs (DNS rebinding). Keep the default unless you need it, and stop the server when you're done.

Fit it to your process

GitHub Action & CI

Validate the project on every pull request, post a catch-up digest for reviewers, publish a read-only canvas to GitHub Pages, and optionally let your own AI write the docs.

The Forward workflow

forward init (or forward github later) writes .github/workflows/forward.yml, which uses Forward's composite action:

  • On pull requests it runs forward validate, annotating schema errors inline, then posts one comment, updated on every push, listing new, changed and removed endpoints with doc diffs and a per-layer summary of everything else.
  • On the default branch it builds a static, read-only canvas with forward export and deploys it to GitHub Pages. Turn Pages on with Source: GitHub Actions.

Action inputs

InputMeaning
pathRepository root that contains .forward/ (defaults to the checked-out repository).
validateRun forward validate and fail on schema errors (default true).
strictAlso fail on warnings: dangling cross-layer links, assignees who haven't committed to .forward/, task due dates that aren't ISO dates, dependency cycles (default false).
commentOn pull requests, post or update one comment with the catch-up digest (default true).
baseGit ref to diff against; defaults to the pull request's base commit.
exportDirectory to write the static canvas into, for GitHub Pages; empty skips it.
cli-versionforward-mcp version to run from npm; empty builds the CLI from the action's own source.
github-tokenUsed to post the PR comment (defaults to the workflow's token).

The digest's Markdown path is exposed as the digest output and also written to the job summary, so fork pull requests (which get a read-only token) still see it.

Let your own AI write the docs

The bring-your-own-AI pipeline, forward-docs, keeps API docs, ER, infrastructure, flows and agents in sync with the code on every pull request, without locking you into any particular AI:

  1. Your AI writes a plan. Any provider reads the diff plus the FORWARD_DOCS.md instructions and writes forward-docs.json. It never edits .forward/ itself.
  2. forward-docs apply writes it. Deterministic, no AI: it fills in geometry and timestamps, re-validates every object against the schema, and writes nothing if the plan is malformed. Re-runs update in place via @adc anchors and stable ids.
  3. The result is committed back to the PR. Reviewed and merged with the code; git is the undo.
# .github/workflows/forward-docs.yml (from the template)
- uses: dsasante1/forward/apps/docs-ci@docs-ci-v2
  # inputs: commit, commit-message (see the template)

The template runs on pull requests from the same repository; your AI step needs your provider's key as a repository secret. A pull request's diff is untrusted input, so give the agent the narrowest tools that work (file read/write rather than a shell). An agent that has the Forward MCP server connected can skip the JSON plan and edit through its tools instead.

Tip: tie a checkpoint to each release. It's a restorable snapshot of the whole canvas, and with forward diff <release-tag> the release tag itself becomes a natural "since last release" baseline.

Reference

CLI & settings

Quick lookup for the CLI commands, environment variables, VS Code commands and the MCP tools.

CLI commands

CommandWhat it does
forward init Create .forward/ here, plus agent configs and the GitHub workflow. Flags: --name, --id, --no-agents, --no-github.
forward serve Open the canvas editor on .forward/. Flags: --port 4747, --host 127.0.0.1, --open.
forward validate Check every file (CI runs this); exits 1 on errors, or on warnings too with --strict. Flags: --format text|json|github, --strict.
forward diff <git-ref>What changed since a ref: the catch-up digest for a PR. Flags: --format markdown|json, --out <file>.
forward export Build a read-only static site for GitHub Pages (images the design uses go to images/). Flags: --out _site, --no-history.
forward assets [prune]List the images in .forward/assets/ and whether anything uses them, or delete the unused ones. Flags: --dry-run, --json.
forward capture <url> [route …]Generate design drafts from a running frontend. Flags: --browser, --viewport 1440x900, --auth state.json, --prune, --restore, --anchors, --images, --no-components, --dry-run.
forward capture --browsersList the browsers live capture can use on this device.
forward capture --scriptPrint a DevTools snippet that captures the page in any browser (--route /path).
forward capture --from <snapshot.json>Import snapshots saved by that snippet (with --prune, --restore, --anchors, --dry-run).
forward agents Write AGENTS.md / CLAUDE.md and MCP configs (all by default). Flags: --claude, --cursor, --vscode, --agents-md.
forward github Write .github/workflows/forward.yml.
forward mcp Serve the agent tools over MCP stdio (same as forward-mcp).
forward tools [<tool>]List the agent tools, or one tool's arguments (--json).
forward call <tool> ['<json>' | -]Run an agent tool from the shell (same code as MCP). Each tool also runs directly as a command, with its arguments as flags; forward <tool> --help shows them.
forward call --batch <file | ->Run many tool calls in one process: a JSON array or JSON Lines of {"tool", "args", "as"} steps, where "$name.id" in an argument is an earlier step's result.

Environment variables

VariablePurpose
FORWARD_REPOUse this repository instead of searching up from the working directory.
FORWARD_AUTHORName stamped on writes (default: git user.name, then your OS login name).
FORWARD_AGENTAgent name added to the author, e.g. Ada via claude.
FORWARD_BROWSERDefault browser for live capture: a name (chrome, edge, brave, chromium, vivaldi, opera) or a path.
FORWARD_NO_DOWNLOADSet to 1 to forbid fetching the forward-capture companion and Playwright's Chromium.
FORWARD_CAPTURE_BINPath to a specific forward-capture companion to run, e.g. for air-gapped setups.

VS Code commands

CommandWhat it does
forward.initRepoInitialize a Forward project in this repository.
forward.setupMcpCopy the claude mcp add … line that connects an AI agent.
forward.openCanvasOpen the design canvas.
forward.connectEndpointDocument an API on a design element.
forward.insertAnchorInsert an @adc anchor at the cursor; pick an element by name, no id to transcribe.
forward.removeDocumentationRemove API documentation from an element.
forward.showHistoryShow an endpoint's documentation history.
forward.catchUpCatch up on endpoint changes since a baseline.
forward.addInfraNodeAdd an infrastructure node.
forward.linkInfraNodesLink two infrastructure nodes with an edge.
forward.removeInfraNodeRemove an infrastructure node.
forward.addFlowAdd a narrated flow (sequence diagram).
forward.addFlowStepAdd a step to a flow.
forward.removeFlowRemove a flow.
forward.addMcpServerAdd an MCP server to the Agents layer.
forward.removeMcpServerRemove an MCP server.
forward.addAgentAdd an agent to the Agents layer.
forward.removeAgentRemove an agent.
forward.createTaskCreate a task, with optional start and due dates, dependencies and an element link.
forward.updateTaskStatusUpdate a task's status.
forward.updateTaskChange a task's dates, dependencies, priority or type.
forward.showTaskTimelineOpen the canvas on the task timeline (Gantt).
forward.validateCheck .forward/ as forward validate does; problems show in the Problems panel and update as files change.

The one setting, forward.openCanvasOnStartup, opens the design canvas when VS Code starts (only in a folder with a .forward/ project).

MCP tools

The 49 tools the Forward MCP server exposes to an agent, by area. forward tools <tool> shows any one's arguments.

AreaTools
Project project_info validate_project get_changes_since_ref list_members add_person remove_person
Design list_design_elements find_element resolve_anchors create_design create_element update_element delete_element import_design_from_code set_element_image list_images
API docs get_documentation write_documentation remove_documentation get_history get_catchup_digest
Infrastructure list_infra write_infra_node connect_infra remove_infra_node
Flows list_flows write_flow add_flow_step remove_flow
Data models list_entities write_entity relate_entities remove_entity
Agents layer list_agents write_mcp_server write_agent remove_mcp_server remove_agent
Tasks list_tasks get_task get_task_timeline create_task update_task comment_task delete_task
Checkpoints list_checkpoints create_checkpoint restore_checkpoint delete_checkpoint
Ready to start? Run npx -y -p forward-mcp forward init in your repository root, or explore the live demo first. The source is on GitHub under the Apache 2.0 license.