Editor setup
Everything below is optional: Saffron runs fine from the CLI alone, but completion from your own step vocabulary is what keeps wording (and token spend) under control.
VS Code
Full experience: the Saffron extension, on the VS Code Marketplace: search "Saffron" in the Extensions view, or
code --install-extension ChathurangaJayasinghe.saffron-vscode
You get .saffron syntax highlighting (first-class StepSet), Ctrl/Cmd+click
on {env:VAR} tokens to open the variable in .env (or .env.example), step
completion with ●/●/○ status badges, StepSet completion,
go-to-definition on invocations, hover cards, and diagnostics
(unknown/duplicate set names, near-duplicate wording warnings).
Run from the editor. Right-click a .saffron file or a folder of them
(Explorer or editor) and pick Saffron: Run, Run (replay only, no
AI), Run (headed browser) or Re-record; the play button in the
editor title runs the open file. Commands run as a VS Code task in the
workspace folder that owns the file, using that folder's own saffron-ai
install (npx otherwise). Arguments reach the process directly, so a file
name is never read as shell syntax. The Command Palette adds Run all feature files, Open
latest report and Accept all pending proposals.
The Saffron side panel. The Saffron icon in the activity bar opens
two views. Feature files lists every .saffron file with its
scenarios as children (click one to jump to it), inline Run and
Replay-only buttons per file, checkboxes with Run selected, and Run
all. Run options and status holds the replay-only and headed toggles,
which apply to every run started from the extension, the last run's
totals with the report one click away, and the proposals pending review
with Accept all. It refreshes as files, reports and proposals change.
Four more sections read saffron status --json: Tags (tick and Run
tagged), Proposals (tick, hover for the narrative, proof-replay
verdict and cost, then Accept selected, Reject selected or Accept
all; click one to open its scenario), Health and config
(vocabulary counts, divergent steps, duplicate wordings proven by
identical recordings, the effective config with one click to the file,
recent pass rates) and Orphaned recordings (caches and proposals whose
scenario no longer exists, with the reason; click one to open it, or use
the title action to run saffron prune --yes after a confirmation).
Saffron: Open dashboard shows the run report in an editor tab,
refreshed after each run.
No-extension fallback (two commands):
// settings.json: Gherkin highlighting for .saffron
{ "files.associations": { "*.saffron": "feature" } }
npx saffron steps --snippets # native completion from your vocabulary
Re-run --snippets after recording sessions to keep completions fresh.
JetBrains (IntelliJ IDEA, WebStorm, PyCharm, Rider, incl. Community)
The Saffron plugin (JetBrains Marketplace; source at
https://github.com/s-chathuranga-j/saffron-jetbrains-plugin) makes this a one-click install, like the Cucumber
plugin: it registers the .saffron file type with highlighting from the
bundled grammar, and wires saffron lsp through the free LSP4IJ plugin, when it is
installed, for *.saffron and *.feature: completion badges, StepSet
go-to-definition, hover, diagnostics. The only prerequisite is
saffron-ai in the project (npm i -D saffron-ai); the plugin runs the
project-local binary and shows a hint if the package is missing.
Running from the IDE. Three ways, all landing in the Run tool window:
- Run configurations: Run/Debug Configurations →
+→ Saffron.runtakes files or folders, tags, and replay-only / headed / re-record switches plus extra arguments;reportopens the latest report;acceptpromotes every pending proposal. Tick Store as project file to share a configuration through.run/. - Right-click → Run on a
.saffronfile (project view or editor) or a folder holding them. The configuration it creates stays in the run widget for re-runs. - The Saffron tool window (right side, in projects with a
saffron.config.json), six tabs. Files: every feature file with its scenario count, search, tick files and Run Selected, Run All, Open Report, Accept All Proposals, the last run's totals and the number of proposals pending review; double-click opens a file. Proposals: tick proposals, read the narrative, proof-replay verdict and cost, then Accept Selected, Reject Selected or Accept All. Tags: tick tags and Run Tagged. Health: vocabulary counts, divergent steps, duplicate wordings proven by identical recordings, the effective config with one click to the file. Orphans: caches and pending proposals whose scenario no longer exists, grouped and explained; double-click opens one, Remove All runssaffron prune --yesafter a confirmation. Dashboard: the run report embedded in the IDE, reloaded after each run. The tabs readsaffron status --json.
Runs use the login shell's environment, so Node from nvm or Homebrew is found even when the IDE was started from the Dock.
Install it from Settings → Plugins → Marketplace (search "Saffron"), or from the listing; install the free LSP4IJ plugin too for completion, go-to-definition and diagnostics. It is optional, so Saffron also installs on IDE builds LSP4IJ has not reached yet.
Manual setup (any JetBrains IDE, no plugin): two separate pieces, the LSP gives you intelligence, a TextMate bundle gives you colors:
- Syntax highlighting: Settings → Editor → TextMate Bundles →
+and pick the bundle shipped inside the package:node_modules/saffron-ai/textmate/saffron. - Completion, diagnostics, hover, go-to-definition, install the
free LSP4IJ plugin (Red Hat), then Settings → Languages &
Frameworks → Language Servers →
+: commandnpx saffron lsp, working directory = your project root, file patterns*.saffronand*.feature. (On IntelliJ Ultimate 2023.2+ the native LSP API also works.)
npx saffron lsp is not something you run by hand, it is a stdio
language server the IDE launches. Run it in a terminal and it prints
exactly these instructions (with the bundle's absolute path).
You get the same completion badges, StepSet go-to-definition, hover,
and diagnostics as VS Code: served by saffron lsp, which is backed
by Saffron's real parser.
Neovim
vim.api.nvim_create_autocmd("FileType", {
pattern = { "cucumber" },
callback = function()
vim.lsp.start({ name = "saffron", cmd = { "npx", "saffron", "lsp" } })
end,
})
vim.filetype.add({ extension = { saffron = "cucumber" } })
AI assistants (any editor)
Assistants can't read completion popups: serve them the vocabulary over MCP so generated feature files reuse your exact wordings:
claude mcp add saffron -- npx saffron mcp # Claude Code
Cursor/Copilot/JetBrains AI Assistant: add an MCP server with command
npx saffron mcp in their respective MCP settings. Three tools are
exposed: search_steps, list_step_sets and project_status (the same
overview as saffron status --json: what is cached, pending review,
tagged, and the vocabulary health). And for whole files from prose:
npx saffron author requirements.txt.
Claude Code: the Saffron plugin
Claude Code users get the language server, the MCP server and the skill in one install, from the public marketplace repo:
/plugin marketplace add s-chathuranga-j/saffron-claude-plugin
/plugin install saffron@saffron
With the plugin, Claude sees diagnostics for .saffron and .feature
files after every edit (unknown or duplicate StepSet names, a missing
StepSet keyword, near-duplicate wordings) and can jump to StepSet
definitions and {env:VAR} variables, the way an IDE does. The MCP
tools and the skill are the same ones saffron init installs per
project, so run npx saffron init --no-mcp there to avoid registering
the server twice. The plugin pins the saffron-ai version it was built
from and starts it through npx.
AI agents: the bundled skill
The npm package ships an Agent Skill,
skills/saffron/SKILL.md plus reference sheets, that teaches any
skill-aware agent (Claude Code, Codex, Cursor, Copilot, Gemini CLI, …)
how to write Saffron tests well: reuse the recorded vocabulary before
inventing wordings, keep Then steps as the sacred verdict, {env:VAR}
for secrets, StepSet syntax, network waits, page furniture, and the
run → review → accept workflow. Install it into your project with:
npx saffron init # .claude/skills + .agents/skills (default)
npx saffron init --agents claude,agents,copilot,cursor
init also registers the saffron mcp server in each host's
project-scoped config: .mcp.json (Claude Code), .cursor/mcp.json,
.vscode/mcp.json (Copilot/VS Code): merged into whatever servers are
already there, so assistants get search_steps, list_step_sets and
project_status with no
manual setup (Codex has no project-level file; init prints the
one-liner). And it appends a short managed block to AGENTS.md
(created if absent) and to CLAUDE.md when one exists, pointers that
tell agents to load the skill and never hand-edit caches. Everything is
idempotent; re-run after npm update saffron-ai to refresh the copy.
--no-instructions / --no-scaffold / --no-mcp narrow it. Projects using
npx skills-npm discover the skill from node_modules automatically.