Quiote for VS Code
Route explorer, triad navigation, and live introspection for apps built on the
Quiote PHP framework.
Available on the VS Code Marketplace.
Core navigation, route exploration, diagnostics, and scaffolding all work
end-to-end, but some polish (hover previews, telemetry-informed defaults) is
still ahead. See Known limitations for what's missing
today.
Features
- Triad navigation — jump between an Action, its View, and its Template
(
Modules/{Module}/Actions/{Action}Action.php ↔ Views/{Action}{View}View.php
↔ Templates/{Action}{View}.{php,tal,xsl,twig}, matching whichever
renderer the app configures per output type — PHPTAL, XSLT, and Twig
templates are recognized alongside plain PHP). Available via:
- right-click → Quiote: Go to Related in the editor (or the default
keybinding
Alt+O), while a triad file is open
- CodeLens links at the top of any triad file (needs
editor.codeLens: true,
VS Code's default)
- right-click an Action node in the Route Explorer → Open View / Open
Template / Describe Action — Open View/Open Template prefer real,
per-output-type paths from live introspection (Artifact/Console/Probe,
whichever answers) over convention-guessing, and prompt with a picker
when a view renders more than one output type's template (e.g.
html
via PHPTAL alongside xml via plain PHP)
- a status-bar breadcrumb showing
Module · Action · Role for the active file
$(list-tree) Quiote status bar item — always visible (not gated on
having a triad file open); click it for a QuickPick of every Quiote command
(List Routes, Refresh, Validate Config, the four scaffolding commands, Go
to Related). This — plus the Command Palette (Quiote: ...) — is the
answer to "how do I do anything with this extension."
- Route Explorer — a
Quiote activity-bar view listing every route the app
knows about, grouped Module → Action → Route. Backed by a four-rung
introspection ladder (fastest first) that degrades gracefully:
- Artifact — reads
cache/introspection/app.json straight off
disk, zero PHP spawn. Written by the framework's own routes:compile
command — no assistant needed, just a Quiote app.
- Probe — the quiote-mcp-assistant's
probe.php, batched via its overview/diagnostics capabilities (one
app bootstrap for routes+modules+triads+diagnostics together). Auto-detected
if the target app has it installed via
composer require --dev quioteframework/quiote-mcp-assistant (searched
from the app dir upward, since vendor/ isn't always a direct child of
the app dir); override with quiote.probePath otherwise.
- Console — the app's own
vendor/bin/quiote routes:compile --json
(framework-only, no assistant needed — this also refreshes the Artifact
as a side effect).
- Static — a filesystem convention scan (no PHP invoked at all), used
for instant paint and as the last-resort fallback.
- Problems panel diagnostics — route/triad problems (
MISSING_VIEW,
SHADOWED_CONFIG, duplicate routes, ...) plus config validation where the
Probe rung is available, via Quiote: Validate Config or automatically on
save.
- Scaffolding —
Quiote: New Module / New Action / New Plugin /
New DB Connection, each a dry-run preview → confirm → write flow that
never overwrites an existing file. Needs the Probe rung. New Action
resolves the target app's real configured renderer for the html
format and writes a minimal, engine-correct starter template in whichever
syntax that renderer actually uses — PHPTAL, Twig, XSLT, or plain PHP —
rather than assuming PHP. Only a renderer with no starter to offer (a
fully custom, app-registered one) is skipped, reported back in the
confirm dialog/completion message with the extension to author by hand.
- Tasks —
routes:list, cache:warmup, and about show up under
Tasks: Run Task as quiote tasks (needs the Console rung —
vendor/bin/quiote found). No problem matcher is attached: these commands'
diagnostics render as Symfony Console's boxed, colored text, not a
reliable regex target — use Quiote: Validate Config (or the automatic
Problems-panel refresh) for structured diagnostics instead.
- Cassette Explorer — a
Cassettes activity-bar view listing recorded
replay (VCR-style record/replay) cassettes, backed by the target app's
own cassette:list/cassette:show --json (needs the Console rung —
vendor/bin/quiote). Clicking a cassette opens a tabbed, Postman-style
detail view (Overview, Request, Session/User, Effects, Response,
Exception, Log) with a per-body "Load full body" action for anything the
console excerpted. The view's Quiote: Select Cassette Environment title-bar
action (backed by env:list --json) picks which environment's cassettes
are listed — e.g. an object-store-backed replay plugin partitions
recordings by environment, so cassettes recorded in staging won't show
up while development is selected. Defaults to whatever the target app's
own .env/$QUIOTE_ENV resolves to. Quiote: Analyze Cassette with Copilot builds a prompt
from the cassette and opens it in Copilot Chat — referencing the app's own
MCP server (mcp:serve, auto-registered to Copilot Chat when the target
app has McpPlugin active) when available, or embedding the cassette JSON
directly otherwise. Pre-fills the prompt for review by default; see
quiote.copilot.autoSendPrompt to send immediately instead.
- File decorations — Action/View/Template files get an
A/V/T badge in
the explorer.
- Snippets — PHP (action/view/config), XML (settings/route), and YAML
(settings/module) snippets for common Quiote authoring patterns.
Requirements
- VS Code
^1.101.0 (the Cassette Explorer's Copilot integration needs the
stable Language Model/MCP-provider APIs; everything else works on older
VS Code too, but the extension declares one floor).
- A workspace containing a Quiote app, detected via
.quiote.json (an
{"app_dir": "..."} marker, resolved relative to the marker file) or a
Config/settings.{php,yaml,yml,xml} file.
- PHP on
PATH (or configured via quiote.phpPath) if you want the
Artifact/Console/Probe rungs — the extension works without PHP at all via
the Static rung, just with less detail (no route paths/methods).
quioteframework/quiote-mcp-assistant as a dev dependency of the target
app (composer require --dev quioteframework/quiote-mcp-assistant) — this
is required for the Probe rung, which in turn is required for
scaffolding (New Module/New Action/New Plugin/New DB Connection)
and config-validation diagnostics. Without it, everything else still works
at the Artifact/Console/Static rungs, but those commands report "needs the
assistant."
phpstan/phpstan as a dev dependency of the target app (with
vendor/bin/phpstan present) if you want to enable
quiote.phpstan.enable, which cross-checks Action/View execute*()
declared return types against what they actually return. Off by default;
see Configuration.
Installing it
From the Marketplace (recommended)
Search for Quiote in the Extensions view (Ctrl/Cmd+Shift+X), or install
directly:
code --install-extension jakamo.quiote-vscode
From source (for developing the extension itself)
Option A — Run it from source (fastest, for trying it out or developing)
- Clone this repo and install dependencies:
git clone <this-repo-url>
cd quiote-vscode
npm install
- Open the folder in VS Code.
- Press F5 (or Run → Start Debugging). This launches an Extension
Development Host window — a second VS Code instance with the extension
loaded. Open a Quiote app folder in that window to try it.
Changes to src/ are picked up after re-running npm run compile (or
npm run watch in a terminal) and reloading the dev host window
(Cmd/Ctrl+R inside it, or Developer: Reload Window from the command palette).
Option B — Install a packaged .vsix into your everyday VS Code
This installs it into your real VS Code, not just a throwaway dev host:
npm install
npx @vscode/vsce package
This produces quiote-vscode-<version>.vsix in the project root. Then either:
Reload VS Code (or just restart it) afterwards. To update after pulling new
changes, repackage and reinstall the same way — VS Code overwrites the
previous version.
To remove it: Extensions view → find "Quiote" → Uninstall.
Configuration
| Setting |
Default |
Description |
quiote.phpPath |
"php" |
PHP executable used for the Console/Probe rungs. |
quiote.appDir |
"" (auto-detect) |
Quiote app root, relative to the workspace. |
quiote.probePath |
"" (auto-detect) |
Path to the assistant's probe.php. Auto-detects a composer require --dev-installed assistant first. |
quiote.introspection.mode |
"auto" |
Pin a rung (auto|artifact|probe|console|static) for debugging. |
quiote.introspection.timeoutMs |
20000 |
Timeout for probe/console spawns — generous by default since a large app's first cold-cache bootstrap can take a while. On timeout you're prompted to keep waiting 30s more rather than failing immediately. |
quiote.diagnostics.enable |
true |
Enable the Problems-panel integration. |
quiote.diagnostics.requireReturnType |
true |
Warn when an Action's/View's execute*() has no declared return type. |
quiote.cache.regenerateOnSave |
true |
Re-query routes/diagnostics in the background when watched files change. |
quiote.phpstan.enable |
false |
Cross-check declared vs. actual execute*() return types via PHPStan. Needs vendor/bin/phpstan in the target app (see Requirements) — off by default, and turning it on prompts for consent before creating phpstan-return-type.neon if it doesn't exist yet. |
quiote.phpstan.configPath |
"" (auto-detect) |
Path to the isolated PHPStan return-type config. Auto-detected next to vendor/bin/phpstan. |
quiote.phpstan.timeoutMs |
60000 |
Timeout for PHPStan return-type check invocations. |
quiote.copilot.autoSendPrompt |
false |
Submit the Analyze Cassette with Copilot prompt immediately instead of only inserting it into the Chat input for review. |
Commands
| Command |
Works today? |
Quiote: Go to Related |
Yes |
Quiote: Refresh Routes |
Yes |
Quiote: Warm Introspection Cache |
Yes (currently an alias for refresh) |
Quiote: List Routes |
Yes |
Quiote: Describe Action |
Yes (from a Route Explorer action node) |
Quiote: Open View / Open Template |
Yes (from a Route Explorer route node) |
Quiote: New Module / New Action / New Plugin / New DB Connection |
Yes — needs the Probe rung (assistant installed). Dry-run preview → confirm → write; never overwrites an existing file. |
Quiote: Validate Config |
Yes — works at the Artifact/Console/Probe rungs (route/triad diagnostics); config-validation diagnostics specifically need the Probe rung. Populates the Problems panel. |
Quiote: List Registered Plugins / Refresh Registered Plugins |
Yes — needs the Console rung (plugins:list --json, includes declaration source) or the Probe rung (assistant installed, no source); neither requires the other. |
Quiote: List Middleware / Refresh Middleware |
Yes — needs the Console rung (middleware:list --json). No probe/assistant equivalent exists. |
Quiote: Refresh Cassettes |
Yes — needs the Console rung. |
Quiote: Select Cassette Environment |
Yes — needs the Console rung. Lists environments via env:list --json (can come back empty if no EnvironmentSourceInterface is registered); also offers a free-text entry and resetting to the project default. |
Quiote: Show Cassette |
Yes — from a Cassette Explorer node, or a Command Palette picker. Needs the Console rung. |
Quiote: Analyze Cassette with Copilot |
Yes — from a Cassette Explorer node, or a Command Palette picker. Needs the Console rung and an active GitHub Copilot session. |
Development
npm run compile # typecheck + bundle
npm run lint
npm run test-unit # pure-logic tests, no VS Code needed
npm run test-integration # runs in a real headless VS Code instance
npm test # both
Known limitations
quiote.cache.regenerateOnSave invalidates unconditionally on any matching
save rather than rehashing the artifact's dependency manifest to check
real staleness — cheaper, and the next live rung recomputes anyway.
- Scaffolding needs the Probe rung (the assistant installed via Composer) —
Console/Static/Artifact have no equivalent, so these commands show "needs
the assistant" without it. Config-validation diagnostics specifically are
also Probe-only; route/triad diagnostics work at every rung down to Console.
- Route Explorer targets the first detected Quiote app in a multi-root
workspace.
- Template-extension detection without a live rung (CodeLens, Go to Related,
file decorations, and the Alt+O index all work purely off disk, no PHP
round-trip) only recognizes the framework's four built-in renderer
extensions (
.php, .tal, .xsl, .twig) — an app-registered custom
renderer with a different extension won't be picked up there. Any rung
with a live introspection artifact (Artifact/Console/Probe) instead
reports the app's real configured extension per output type, no
guessing involved.
- No hover previews yet, and no telemetry to inform future defaults — both
are planned but not implemented in
0.1.0.
| |