Lens
ways-lens renders a way's state inside your IDE — flow stepper, gates, step progress and document chips, live, without leaving the editor.
A way writes .ways/state.json on every run so it can resume and so
tooling can see what's going on. Lens (ways-lens) is that tooling, in the place you already are:
a panel docked in your editor that renders the current worktree's state — the phase you're in, which
gate is pending, and which document to open next.
It's a pure reader. It never writes state, never runs git, never approves a gate. The flow writes, you commit, Lens shows.
Contact export
feat/003-contact-export
Phase: Implementation
Flow
- ✓Discovery
- ✓PRD
- ✓Plan
- Implementation
- Validation
- Review
- PR → develop
- PR → main
- Done
Progress
- Schema + migration
- Export service
- CSV writer
- REST endpoint
- Tests
- Docs
Gates
- PRD review
- Plan review
- PR → developPR ↗
Documents
A mock, drawn from the real renderer. In your editor the panel inherits your theme's colors, the PR and ticket links are live, and it re-renders on every .ways/ or branch change.
What it renders
For the active worktree's current branch, Lens loads <root>/.ways/state.json and renders:
| Block | What you see |
|---|---|
| Identity | the flow's friendly label, the way + wayVersion running it, the discipline, an isolation badge (branch / worktree / none), the branch and the current phase |
| Flow | the phase stepper — for feature, bug and security the canonical phase order, with the current phase highlighted and lastPhase showing the transition just completed |
| Gates | each gate's status, with PR gates rendering their url as a link |
| Progress | done / total for the state's steps[], plus the per-step status |
| Documents | one chip per documents[] entry, colored by status — click it and the file opens in the editor |
Namespaced analytical flows (architecture/assessment, security/threat-model) are first-class,
not a degraded case: the label is derived, the stepper comes from the state's own phases instead of a
hardcoded sequence, the report doc leads, and an absent steps[] hides the block rather than
rendering an empty one.
The three empty states
A blank panel is a bug, so every non-state outcome says what it is:
- Not initialized — no
.ways/in the workspace; nothing has run a way here. - No item on this branch — a state file exists but its
branchdoesn't match the checked-out branch, so it's stale or inherited from another worktree. Lens shows nothing rather than the wrong item (the standard's identity rule). - Idle — you're on a base branch (
main,develop) or a detached HEAD.
Malformed or unreadable JSON degrades to an empty state too. Lens never crashes on something the
standard permits — unknown fields and ext blocks are ignored, not rejected.
Install
VSCode, Cursor, Kiro, VSCodium
One extension covers VSCode and every VSCode-based fork. It ships as a .vsix on the
ways-lens releases page (tags vscode-v*) —
download it, then:
code --install-extension ways-lens.vsix # or: cursor / kiro / codiumOr in the editor: Extensions → ⋯ → Install from VSIX…
The panel appears in the activity bar. ways-lens: Refresh in the command palette forces a
re-render; you rarely need it, since the panel watches .ways/ and .git/HEAD and re-renders on
focus.
JetBrains and Visual Studio
On the roadmap, in that order: IntelliJ/JetBrains (tool window), then Visual Studio. Both are thin adapters over the same core, so they render exactly what you see above.
Why it stays correct
Three deliberate choices, worth knowing because they're what makes the panel trustworthy:
- The branch comes from
.git/HEAD, following thegitdir:pointer for linked worktrees — not from the editor's git plugin. It works in the setups where that plugin doesn't. - Host filesystem API only, never direct
node:fs— so Remote/SSH and dev containers work unchanged. - One shared core. Parsing, flow logic and the view-model live once in
ways-state-core(pure TypeScript, zero host dependencies); each IDE plugin is a shell around it. Every renderer agrees on what the state means, because there's only one implementation of the meaning.
Source:
incu-tech/ways-lens— the core inpackages/ways-state-core, the plugins underplugins/. It consumes the state contract as-is; the shape itself is defined by the state file standard.