Last updated July 24, 2026
Intents
Reading a system and changing it happen on the same board. An intent is how you change it: a work item you author on the board and a developer implements in the repo. You describe a change anchored to real board elements, release it, and it flows into a coding session through Cdx Code. When the code comes back, the board updates itself around it — and architectural decisions stop being screenshots in Slack.
Intents live on app boards: the hub leads with them, and the Intents panel on the canvas holds the full queue.
Where intents come from
The main path. An analysis or a /monitor run lands findings on the board; you review them and create an intent from the ones that deserve action. Select several findings at once and each becomes its own intent — one work item per finding, so nothing gets bundled into a vague umbrella task. Each one carries its origin finding — so a production signal traces all the way to the commit that fixed it. See Insights.
The board-edit path surprises people once, in a good way: on a governed board your structural edit stays right where you made it — the element remains on the canvas as an uncommitted staged change (an Added / Removing / Modified badge, like a git working tree) and files an intent in the Intents panel, waiting to be implemented in the repo. It neither vanishes nor silently commits.
Reading the board
Intents don't just live in a panel — they show up on the canvas, on the elements they're about. On an app board the badge language answers two different questions at a glance:
- Where did this element come from? Elements generated from code carry the source-binding indicator; hand-authored elements simply lack it. This is the is — what exists today.
- What's wanted on it? A count chip appears on any element with active intents, colored by their dominant status. Click it for the element's dossier: every intent anchored here, with a + Add intent entry to author another. Proposed and staged changes also restyle the element — a green Added badge on a newly staged element (node or edge), a dashed amber border for a proposed modification, dashed red (dimmed) for a proposed removal. A proposed connection that isn't drawn yet shows as a dashed ghost edge between the two nodes. This is the ought — what's proposed.
Plugin-proposed intents carry a small plug marker on the chip, so system-filed work reads as distinct — but it behaves exactly like any other intent everywhere else.
Visual context
An intent can carry more than words: the actual screen it's about, marked up. When a developer runs /inspect against the running app and pushes the result, each captured page is stored on its ui.page as a page capture — a clean screenshot plus a map of the interactive elements on it. From the intent editor you annotate that capture directly:
- Pick a component. Hover the screenshot and the highlight snaps to the smallest element under your cursor — a button inside a card, not the whole card — down to the page's internal components, not just the page itself. Click to attach it, and the platform resolves that component to the source file it renders from, so the anchor points a developer at real code.
- Draw an annotation. Drag a box over any region and add a note — "this spacing is wrong", "make this a dropdown". The box and its note ride along with the intent.
- Components panel. The capture's render tree is listed beside the image, so you can see every internal component the page is built from and pick from the list instead of the pixels.
The developer sees all of it on the other side: /intents surfaces the intent's visual context — the annotated screenshot, the picked components, and the files they map to — so "make this cleaner" arrives with the picture attached.
Page captures come from a developer running /inspect and choosing to push — the platform never screenshots your app itself. A ui.page with no captures yet simply shows nothing to annotate; capture it once from a coding session and it's there for every future intent on that page.
The lifecycle
| Status | What it means |
|---|---|
| Unreleased | You're still shaping it — name, summary, and instructions stay editable right in the editor. Invisible to developers. |
| Open | You hit Release — the intent is locked and visible to /intents pulls. |
| Assigned | Handed to specific people. |
| In progress | A developer claimed it — single-winner, so two sessions can't duplicate work. |
| Needs clarification | A developer bounced it back: the code no longer matches what the intent describes. It leaves the pullable queue until you revise and re-open it — or reject it. |
| Implemented | The developer resolved it as done, with a note and usually a commit or PR link. |
| Rejected | Declined with a reason. |
| Resolved | Closed another way — overtaken by events, or handled outside this queue. |
Needs clarification is the one status that moves backwards, and it's deliberate: a developer who finds the board's picture stale shouldn't guess, and shouldn't silently implement the wrong thing. Bounced intents reappear on your hub as work waiting on your decision.
The gate that matters is unreleased → open. Until you release an intent, it's a sketch; the moment you release it, it's a commitment developers will pick up. The hub's intents card surfaces exactly this — N await your approval — with the Release action inline.
Trust, then verify
Two badges tell you how much to believe an intent's status:
- Verified — the developer claimed implemented, and a later
/syncpush matched the structural change the intent proposed. The board proved that one; it isn't self-reporting. The developer sees it too: their/syncprints which intents the push just verified. - Stale — the board moved underneath a waiting intent (the anchored elements changed since you wrote it). Re-review before anyone implements against an outdated picture.
Verified only applies to intents that propose a change to the board's structure — a node added, an edge redrawn, an element removed. That's what a sync can match code against. An intent whose payload is Instructions — most hand-written ones, and every intent created from a spec requirement — gives a sync nothing to compare, so it closes on the implementer's resolution note. Know which kind you're reading before you treat a green status as proof.
Two things happen without you lifting a finger:
- Auto-satisfied — if a sync shows an open intent's proposed change already holds in code (someone did it directly), the intent retires itself as verified instead of lingering in the queue.
- Conflicts held back — if two open intents propose different changes to the same element, both are withheld from
/intentspulls and flagged, so a developer never implements one half of a contested change. Resolve it on the board first.
Working the queue
The Intents panel groups the queue by status. On a root board's command center you see every app's counts in one place, plus an All layers scope inside the panel for the whole board tree.
From either place you can:
- Release an unreleased intent, or reject it
- Assign open intents to specific developers
- Open it in the editor — a click on any row opens the intent in the dock: the instructions, the proposed changes, and the resolution note when it comes back. Until you release it, the name, summary, and instructions are yours to refine right there.
An intent's context is never a dead end. Every anchor is a link: click it and you land on the thing itself — the node on its board's canvas, the table on its aspects screen — even when it lives on another board in the tree. Below the anchors, a small context map draws the intent's scope: the elements in their real board styling, grouped by board, connections included. Reading an intent and seeing what it touches are the same act.
The developer side
Developers don't visit the portal to pick up work. In their coding session, /intents pulls the open queue for the bound repo, claims an item, implements it against the instructions, verifies with the project's own checks, and resolves — and the resolution flows back to your board. If the repo has moved out from under an intent, they bounce it back as Needs clarification rather than guess. The full flow lives in the plugins guide.
The loop closes on its own: /monitor finds a production signal → you create an intent from it → a developer implements → /sync pushes the changed code back onto the board → the next /monitor run shows the signal gone.
What's next
Specs
The step upstream — requirements that become intents in this queue and close against it.
App Boards & the Hub
Where intents live — the front page of a board connected to a repo.
ContextDX Plugins
The developer half: /intents, /inspect, /build, /monitor, /sync.
Insights
The findings you'll turn into intents.

