ways

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.

Flow & State
FeatureWorktreePROJ-412

Contact export

incu/dev v1.2.0·development

feat/003-contact-export

Phase: Implementation

Flow

  1. Discovery
  2. PRD
  3. Plan
  4. Implementation
  5. Validation
  6. Review
  7. PR → develop
  8. PR → main
  9. Done

Progress

Steps2 / 6
  • 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:

BlockWhat you see
Identitythe flow's friendly label, the way + wayVersion running it, the discipline, an isolation badge (branch / worktree / none), the branch and the current phase
Flowthe phase stepper — for feature, bug and security the canonical phase order, with the current phase highlighted and lastPhase showing the transition just completed
Gateseach gate's status, with PR gates rendering their url as a link
Progressdone / total for the state's steps[], plus the per-step status
Documentsone 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 branch doesn'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 / codium

Or 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 the gitdir: 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 in packages/ways-state-core, the plugins under plugins/. It consumes the state contract as-is; the shape itself is defined by the state file standard.

On this page