{"id":"2d966dff-e548-4419-a0cc-a6c4ebd8acef","slug":"dsasante1-forward","kind":"mcp","name":"forward","summary":"Keep UI design and backend docs in sync, inside your git repo. A design canvas, API/infra/data-model docs, and an MCP server + CLI so AI agents document as they build.","owner":"dsasante1","repoUrl":"https://github.com/dsasante1/forward","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-05-31T18:04:06.000Z","addedAt":"2026-11-01T01:48:14.027Z","logoUrl":"https://avatars.githubusercontent.com/u/114578080?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["design-media","developer-tools","files-documents"],"tags":["ai-agents","api-documentation","design-tools","developer-tools","git","mermaid","vscode-extension"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-11-01T02:47:26.656Z","sample":false,"url":"https://conduits.dev/tools/dsasante1-forward","language":"TypeScript","transports":["stdio"],"install":{"npm":"forward-mcp"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Forward\n\nKeep **UI design and backend documentation in sync**, inside your repository.\n\nDesigners draw UI on a visual canvas. Backend developers, and the AI agents working with them,\nattach API docs, infrastructure, data-model and flow documentation to those design elements. A\nhistory timeline and a catch-up digest show frontend developers exactly which endpoints to\nintegrate, change or remove.\n\n- **Lives in git.** The whole project is plain JSON in `.forward/`, one file per record. It is\n  versioned, reviewed and merged with the code it describes. No server and no account are needed.\n- **AI-agent first.** Claude Code, Codex, Cursor, Copilot or any MCP client gets 42 tools with full\n  parity with the canvas. Agents without MCP use the same tools through the `forward` CLI.\n- **GitHub native.** One workflow validates `.forward/` on pull requests, posts a catch-up digest\n  as a PR comment, and publishes a read-only canvas to GitHub Pages.\n- **Open source** under the [Apache 2.0 license](LICENSE).\n\n## Quick start\n\nRun this in the root of your repository. Node 22 or newer is required.\n\n```bash\nnpx -y -p forward-mcp forward init     # creates .forward/, agent configs and the GitHub workflow\nnpx -y -p forward-mcp forward serve    # opens the canvas editor on .forward/ at http://127.0.0.1:4747\ngit add .forward AGENTS.md CLAUDE.md .mcp.json .cursor .github && git commit -m \"Add Forward\"\n```\n\n`forward serve` writes straight to `.forward/`. An agent editing through MCP at the same time\nshows up on the canvas within a couple of seconds, and the History view reads your git log.\n\n## AI agents\n\n`forward init` (or `forward agents` later) writes the agent wiring into your repository:\n\n| File | For |\n|---|---|\n| `AGENTS.md` | Instructions every agent reads: when and how to document endpoints, infra and schema |\n| `CLAUDE.md` | Imports `AGENTS.md` for Claude Code |\n| `.mcp.json` | Registers the `forward` MCP server for Claude Code |\n| `.cursor/mcp.json` | Registers it for Cursor |\n| `.vscode/mcp.json` | Registers it for VS Code / Copilot (`forward agents --vscode`) |\n\nCodex reads `AGENTS.md`. Register the server in `~/.codex/config.toml`:\n\n```toml\n[mcp_servers.forward]\ncommand = \"npx\"\nargs = [\"-y\", \"forward-mcp\"]\nenv = { FORWARD_AGENT = \"codex\" }\n```\n\nAny other MCP client runs `npx -y forward-mcp` over stdio from the repository root. No\nconfiguration is needed: the server finds the nearest `.forward/` and works on those files.\n\n**Without MCP**, the CLI calls the very same tool code in-process:\n\n```bash\nforward tools                                   # list all 42 tools\nforward tools write_documentation               # one tool's arguments\nforward find_element --query \"login button\"\nforward write_documentation --element-id el_123 --title \"POST /login\" --description \"Body: email, password\"\nforward call write_infra_node '{\"kind\":\"cache\",\"label\":\"Redis\"}'\nforward diff origin/main                        # what this branch changed, as Markdown\n```\n\nGood first calls for an agent are `project_info`, `find_element`, `write_documentation`,\n`validate_project` and `get_changes_since_ref`. Writes are stamped with your git `user.name`, plus\n`via <agent>` when `FORWARD_AGENT` is set.\n\n## Images\n\nDrop or paste an image onto the canvas (or right-click → **Image…**) and it becomes a rectangle\nwith an **image fill**; any rectangle, ellipse or frame can take one from the inspector or the\nright-click menu, clipped to its corners. The inspector sets the fit (cover, contain, fill) and alt\ntext. Agents use `set_element_image` with a file path.\n\nThe bytes are stored once in `.forward/assets/`, named by their SHA-256, and the element only holds\nthat name, so checkpoints, history and the PR digest never copy them, the same image used twice is\none file, and two branches adding it don't conflict. PNG, JPEG, WebP, GIF and AVIF are accepted up\nto 5 MB (SVG is refused: it can carry script). The canvas downscales to 4096 px and re-encodes,\nand the store strips EXIF/XMP from every JPEG and PNG, so a photo's GPS position never reaches git.\n`forward init` marks `assets/` binary in `.forward/.gitattributes`; teams with many large images\ncan add `git lfs track \".forward/assets/**\"`.\n\nRemoving an image or deleting its element keeps the file (undo and checkpoints may need it).\n`forward assets` lists what's stored, `forward assets prune` deletes what no element or checkpoint\nuses, and `forward validate` warns about missing or unused images and fails on a file whose bytes\ndon't match its name. `forward capture --images` fetches the page's `<img>`s into drafts instead\nof grey placeholders.\n\n## Designs from frontend code\n\nIdeally the frontend is built from the design. When a screen was built first, Forward can draw it\nfor you: it renders the running app, reads back what the browser actually painted (position, size,\ncolours, borders, corners, fonts, text, stacking) and turns it into canvas elements: one frame per\nroute, a box for everything that paints, text for every run of text. Wrappers that paint nothing are\ndropped, so the layer tree stays readable. React dev builds also report which component rendered\neach node, so repeated components become a component plus instances.\n\n```bash\nforward capture --browsers                                  # which browsers it can use here\nforward capture http://localhost:5173 / /login /settings --dry-run\nforward capture http://localhost:5173 / /login /settings\nforward capture http://localhost:5173 /account --auth state.json --viewport 390x844\nforward capture http://localhost:5173 / --browser edge      # or chrome, brave, chromium, vivaldi, opera, a path\n```\n\nLive capture uses the browser you already have. Any Chromium-based browser works: Chrome, Edge,\nBrave, Chromium, Vivaldi or Opera. Nothing is installed or downloaded. The browser runs headless\nwith a fresh, temporary profile (it never sees your own cookies, logins or extensions). It's\ncontrolled over a pipe, so nothing listens on the network, and it's closed and its profile deleted\nwhen the capture ends. If the project has Playwright, that is used first; `--browser` picks one\nexplicitly and `FORWARD_BROWSER` sets the default.\n\nNo Playwright and no Chromium browser (a server, a container, some CI)? `forward capture` then runs\nits companion package, `forward-capture`, at the same version\n(`npx -y forward-capture@<version>`). It brings Playwright and downloads Playwright's headless\nChromium once, about 100 MB, into Playwright's shared cache; `npx -y forward-capture install`\nfetches it ahead of time. `FORWARD_NO_DOWNLOAD=1` forbids both downloads. `forward-mcp` itself\nstays free of dependencies.\n\nFirefox and Safari can't be driven this way. In those (or any browser), `forward capture --script`\nprints a snippet to paste into the DevTools console. It downloads `forward-snapshot.json`, which\n`forward capture --from forward-snapshot.json` imports. Agents call the same thing as\n`import_design_from_code`.\n\nGenerated elements are **drafts**, marked \"from code\" on the canvas:\n\n- Re-running a capture updates drafts in place, and API docs attached to a draft are kept. An\n  element keeps its identity by its `data-testid`, `id`, the JSX line that rendered it (React dev\n  builds) or its `aria-label`. Failing those, by its position under the nearest element that has\n  one. When the page around a draft changes (a banner inserted above, say), drafts are re-matched by\n  type, name or text, size and what they contain, as long as the match is unambiguous. API docs\n  never move on a guess: if a documented draft can't be matched for certain, it stays where it was\n  (stale, docs intact) and the capture reports it. Test ids on repeated or generic elements make\n  identity certain.\n- A draft someone has edited (moved, restyled, renamed) is never overwritten. The import reports\n  it as a conflict.\n- **Adopt draft** (inspector or right-click menu) turns a draft into an ordinary design element\n  that imports never touch again.\n- Deleting a draft remembers it in `.forward/dismissed/`, so the next capture doesn't bring it\n  back. `--restore` brings deleted drafts back.\n- Drafts the code no longer renders are reported as stale. `--prune` removes them, but never one\n  that is documented, edited, adopted, or holds something that stays. Pruning also forgets deleted\n  drafts the code no longer renders.\n- `--anchors` adds `// @adc <id>` markers above each component's declaration in your JS/TS source,\n  so `resolve_anchors` links code to design. It edits source files, so it is off by default; every\n  capture says how many anchors it would add.\n- Adopting a draft isn't listed as a design change in the PR digest. The digest reports it on its\n  own \"Adopted from code\" line instead.\n- A capture records what the page shows, so run it against development or seed data, not real\n  customer data. Password fields are always masked.\n\n## GitHub\n\n`forward init` adds [`.github/workflows/forward.yml`](apps/mcp/src/cli/scaffold.ts), which uses\nthis repository's [composite action](action.yml):\n\n- **On pull requests** it runs `forward validate`, annotating schema errors inline. It then posts\n  one comment, updated on every push, listing new, changed and removed endpoints with doc diffs and\n  a per-layer summary of everything else.\n- **On the default branch** it builds a static, read-only canvas with `forward export` and deploys\n  it to GitHub Pages. Turn Pages on with *Source: GitHub Actions*.\n\nTeams that want an AI to write the docs on every pull request can add the bring-your-own-AI\npipeline in [apps/docs-ci](apps/docs-ci). Its repo-mode template commits the generated `.forward/`\nchanges back to the PR branch.\n\n## How it works\n\n```\n  designers              backend devs                 AI agents                 GitHub\n      │                       │                           │                        │\n [ canvas ]        [ VS Code extension ]        [ MCP server · CLI ]      [ Action · Pages ]\n      │                       │                           │                        │\n      └───────────────────────┴──────── forward-core/api ─┴────────────────────────┘\n                                             │\n                               .forward/ files in your git repo\n```\n\nEvery surface speaks one REST contract, `forward-core/api`. A router in `forward-core/repo`\nserves that contract from the files in `.forward/`: in-process for the MCP server, CLI, extension\nand CI, and over a local HTTP server that `forward serve` runs for the canvas. There is no central\nserver, database or account. Git is the sync, the history and the access control.\n\n### The `.forward/` directory\n\n| Path | Holds |\n|---|---|\n| `forward.json` | Project manifest: id, name, format version |\n| `design/<id>.json` | Design elements, each with its optional `apiBinding` docs |\n| `history/<elementId>/<ts>-<n>.json` | Append-only API-doc history, one file per version |\n| `infra/nodes`, `infra/edges`, `infra/flows` | Infrastructure graph and narrated flows |\n| `data/entities`, `data/relations` | ER data model |\n| `agents/agents`, `agents/servers` | Agents and the MCP servers they call |\n| `tasks/<id>.json` | Task tracker |\n| `checkpoints/<id>.json` | Named, restorable snapshots of design and infra |\n| `dismissed/<id>.json` | Code drafts someone deleted, so capture doesn't recreate them |\n| `assets/<sha256>.<ext>` | Image bytes for image fills, named by their hash |\n\nOne file per record keeps merges clean and PR diffs readable. History entries are separate files,\nso two branches that both document endpoints merge without conflicts. The project activity feed is\nbuilt from `git log`, so commit messages show up in the History timeline. `forward validate` checks\nschemas, ids and cross-layer links.\n\n## Seven data layers, one contract\n\nThe data model is deliberately layered. The **design** is the primary artefact and exists on its own;\neverything else is optional and attaches (or links) to it. All shapes live once in\n[packages/shared](packages/shared) (`forward-core`) as Zod schemas + TypeScript types, so every surface\nstays in sync.\n\n| Layer | What it is | Attaches to |\n|---|---|---|\n| **Design** | `DesignElement`s a designer draws — frames, rectangles, ellipses, text, components/instances — with absolute geometry, `parentId` hierarchy and style | — (stands alone) |\n| **API binding** | An *optional* `{ title, description }` doc note a backend dev attaches to a design element. Docs-first and framework-agnostic (REST, GraphQL, gRPC, a job…) — an endpoint is never a first-class canvas object | one design element |\n| **Infrastructure** | A project-scoped graph of `InfraNode`s + `InfraEdge`s (frontend, backend, db, cache, queue, service, devops, external, group), rendered as an overlay | project |\n| **Flows** | Narrated `InfraFlow`s — ordered hops over the infra nodes — that serialize to a Mermaid `sequenceDiagram` and can tie a hop to an endpoint | infra graph |\n| **Entities (ER/UML)** | A project-scoped data model of `Entity` tables + crow's-foot `EntityRelation`s, serialized to a Mermaid `erDiagram` | project |\n| **Tasks** | A work tracker (`Task`: status/priority/type, assignees, start/due dates, `dependsOn`, activity feed) that *optionally links* into a design element / flow / endpoint, with a timeline (Gantt) view | project (soft links) |\n| **Checkpoints** | Named, restorable snapshots of the whole canvas (design + infra) — a deliberate save with a note | project |\n\nOn top of these sits the **History timeline**: a per-element append-only API-doc history\n(`version_timeline`) plus a unified project event feed, rendered as a git-graph with expandable\n\"git-diff for API docs\" and a **catch-up digest** (\"since this baseline, here's what to integrate /\nmodify / remove\") for a returning frontend dev.\n\n## Monorepo layout\n\nnpm workspaces (Node >= 22.12 to develop; `.nvmrc` pins 22).\n\n| Path | Package | What it is |\n|---|---|---|\n| [packages/shared](packages/shared) | `forward-core` | The contract: Zod schemas + types, timeline/diff/infra/entity helpers, the `api-rest` client (`forward-core/api`) and the repo-mode store, router and git helpers (`forward-core/repo`) |\n| [apps/mcp](apps/mcp) | `forward-mcp` | The agent surface: the MCP server (`forward-mcp`) and the `forward` CLI (init, serve, validate, diff, export, capture, agents, every tool). Also builds the companion `forward-capture` (live capture with Playwright) |\n| [apps/canvas](apps/canvas) | `forward-canvas` | The design editor, shipped standalone with the CLI (`host/`) and embedded in the VS Code extension |\n| [apps/extension](apps/extension) | `forward-vscode` | VS Code extension. Works on the workspace's `.forward/` automatically |\n| [apps/docs-ci](apps/docs-ci) | `forward-docs-ci` | Bring-your-own-AI CI step that applies an agent-written plan to a project |\n| [apps/site](apps/site) | `forward-site` | The website: landing page, docs and a live read-only demo, deployed on Vercel |\n\n## Development\n\n```bash\nnpm install && npm run build    # build packages/shared first, then every app\nnpm test                        # all Vitest suites\nnpm run typecheck\nnpm run dev:host -w apps/canvas # hack on the standalone canvas host with Vite\nnode apps/mcp/dist/cli.js serve # run your local build of the CLI against a repo with .forward/\nnpm run dev -w apps/site        # the website (landing page + docs) with Vite\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow, conventions and governance, and\n[CHANGELOG.md](CHANGELOG.md) for what changed in each release.\n\n## Publishing\n\nReleases are tags. `mcp-v*` publishes `forward-mcp` to npm with trusted publishing, so no npm token\nis stored anywhere. `v*` publishes the VS Code extension. Both re-run the full verification first,\nand `forward-mcp` is smoke-tested as the installed tarball. See [docs/releasing.md](docs/releasing.md),\nincluding the one-time manual first publish.\n\n```bash\nnpm version 0.3.0 -w apps/mcp --no-git-tag-version   # land it through a PR, then:\ngit tag mcp-v0.3.0 && git push origin mcp-v0.3.0\n```\n\n## License\n\nApache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).\n"}