Reference
CLI reference
Every command, flag, default and exit code of the desde command line tool, as the argument parser actually reads them.
The Editor is a command line tool that boots your prototype's own Vite dev server, injects the bridge, and serves an editing workspace on localhost. This page documents its argument parser exactly: the flags it accepts, what each one defaults to, and which exit code you get when it refuses.
If you have not run it before, start with the Editor quickstart. This page assumes the tool is already installed.
Running it#
Desde is not published to npm, so there is no globally installed desde binary. You run the entry script from a monorepo checkout:
node editor-cli/bin/desde.mjs ../my-prototypeThe package declares two binary names. Neither is on your PATH today; both are reachable by path from the checkout.
| Binary name | Script | What it is |
|---|---|---|
desde |
editor-cli/bin/desde.mjs |
The editor itself. Everything on this page. |
desde-mcp |
editor-cli/bin/desde-mcp.mjs |
A stdio MCP server that exposes the Editor's tools to a separate claude CLI session. Takes no flags of its own. |
Both scripts re-run themselves once with the TypeScript loader attached, then load the real entry point. That is why they need editor-cli/node_modules to exist, and why the first line of output can take a moment.
Invocation forms#
| You type | What happens |
|---|---|
desde <repo-path> |
Boots the editor against that repository. |
desde clone <url> [dest] |
Clones the repository, then boots the editor on the fresh checkout. |
desde (no arguments) |
Starts the launcher (a project picker page). See below. |
desde -h |
Prints the built-in help and exits 0. |
<repo-path> may be relative or absolute. Relative paths resolve against the directory you were in when you ran the command.
Running with no arguments starts a server#
This is the one behaviour the built-in help does not mention. Running desde with no repository path does not print usage and exit. It starts a second kind of server (the launcher) on port 4321 and opens your browser at it.
The launcher is a project picker: recent projects, a native "open a local folder" dialog, and "clone from GitHub". Choosing a project spawns a normal desde <path> process on a free port and redirects your browser there. The launcher process stays alive so you can open more projects from the same tab.
Note To see usage text, pass
-hexplicitly. A bare run gives you a web page, not a usage message.
Three flags you give the launcher are forwarded verbatim to every editor it spawns, so a launched project runs the same assets you asked for: --ui-bundle-root, --bridge-bundle, and --vite-port. --shell-port is not forwarded: it sets the launcher's own port, and each spawned editor gets a free port.
Boot options#
| Flag | Argument | Default | Effect |
|---|---|---|---|
-h, --help |
N/A | N/A | Print the help text and exit 0. |
--no-open |
N/A | off | Do not try to open a browser. Applies to the launcher too. |
--shell-port <n> |
number | 4321 |
Port for the editor workspace. |
--vite-port <n> |
number | 5173 |
Port for your prototype's Vite dev server, or for the attach-mode proxy. |
--attach <url> |
url | none | Attach to a dev server you already started (its origin, e.g. http://localhost:3000), instead of booting one. Needed for a framework Editor has no in-process host for, or one turned off via hosts config. Checks that your own config wires the Desde source stamper, and refuses with the exact block to paste if it does not (exit 5). |
--host-mode <mode> |
auto | in-process | attach |
auto |
What happens when in-process boot cannot be trusted. auto shuts the broken host down and points you at attach mode (exit 4). in-process refuses loudly instead (exit 6). attach requires --attach <url>. |
--host <id> |
id | detected automatically | Name the dev-server host instead of detecting it: vite, react-router, astro, nuxt, next, or attach. Needed when a prototype looks like two frameworks at once (exit 7 lists them). Does not skip the host's own seam checks. |
--doctor |
N/A | off | Print what Editor detected, which host would run, the seams that host stands on, and what it could stamp, then exit without booting anything. Exits 0 even when the report says the project is unsupported or ambiguous; exits 1 only if the report itself could not be produced. |
--skip-stamp-verify |
N/A | off | Serve anyway when stamping verification concludes the stamper is not running. Edits will be refused; this is a diagnostic override, not a fix. |
--bridge-bundle <path> |
path | <checkout>/dist/bridge-bundle.js |
Where to read the bridge bundle from. |
--ui-bundle-root <path> |
path | editor-cli/ui-src/dist |
Where to read the built editor interface from. |
--branch <name> |
string | N/A | Branch to check out. Only used by clone. See below. |
Both default paths are resolved relative to the CLI's own source file, not to your prototype and not to your current directory. They point back into the Desde checkout.
There is no flag for the bind address. Both servers always bind to 127.0.0.1. The --host <id> flag below names the dev-server framework, not a network interface.
When booting an editor, a port that is already in use is silently swapped for a free port chosen by the operating system. Read the URLs off the terminal rather than assuming 4321 and 5173.
The launcher does not do this. If 4321 is taken (usually by an editor you already have running), the launcher fails to start rather than moving. Give it another port with --shell-port.
--branch is accepted while booting, and ignored#
The parser accepts --branch in every invocation form, but only the clone path reads it. Running:
node editor-cli/bin/desde.mjs ../my-prototype --branch redesigndoes not switch branches. It boots on whatever branch is currently checked out, with no warning that the flag did nothing. Switch branches with git switch before you start, or from the branch menu in the workspace once it is running. See branch mode.
There is no --force#
Some refusal messages read as though an override exists. It does not. --force is not a flag the parser knows, and passing it exits with code 2 and the message Unknown option: --force. A framework refusal is final: the Editor cannot map a click back to a line of source in a framework it has no source-tagging plugin for. See limits.
The clone subcommand#
node editor-cli/bin/desde.mjs clone https://github.com/you/my-prototypeclone is only recognised as the very first argument. Anywhere else it is treated as a repository path.
| Positional | Required | Default |
|---|---|---|
<url> |
yes | N/A |
[dest] |
no | the repository name, derived from the URL |
Behaviour worth knowing:
- It uses your own git credentials. SSH agent, or your HTTPS credential helper, whatever
git clonealready uses in your shell. There is no sign-in step and no brokered token. - It will not clone over an existing directory. If the destination exists, the command fails rather than merging into it.
- Interactive credential prompts are disabled. The clone runs with
GIT_TERMINAL_PROMPT=0, so a private repository your credential helper cannot answer for fails fast instead of hanging. --branch <name>is passed through togit clone --branch.- The destination resolves against your launch directory, not the editor's working directory, so a relative
destlands where you expect.
On success it prints the destination and then boots the editor on it, exactly as if you had passed that path directly. Boot flags such as --shell-port work in the same command.
node editor-cli/bin/desde.mjs clone https://github.com/you/proto ./proto --branch main --no-openExit codes#
| Code | Meaning |
|---|---|
0 |
Normal exit. In practice only -h, or a --doctor report (even one that says the project is unsupported or ambiguous), since a booted editor runs until you stop it. |
1 |
The clone failed, the editor failed to start for a reason other than framework support (missing bridge bundle, missing interface bundle, Vite config error, not a git repository, or a merge / rebase / cherry-pick / revert / bisect left in progress; those are refused as unsafe to edit over), or --doctor itself could not produce a report. |
2 |
Bad arguments. Failures inside argument parsing itself, an unknown --flag, an unexpected extra positional argument, an invalid --host-mode value, or an invalid --host id, print the help text before exiting. A clone with no URL, a non-numeric --shell-port / --vite-port, an empty --attach, or a contradictory pairing of --host-mode / --host / --attach exit the same way without printing it. |
3 |
Framework refusal. The repository is not a shape the Editor supports. |
4 |
Attach mode is required, and no --attach <url> (successfully) covers it. Two different paths land here: the repository needs a dev server Editor cannot supervise in-process at all, or has that host turned off via hosts config; or --host-mode auto (the default) found the in-process host either failed to boot or booted without proof it stamps source, and routed you to attach mode instead of failing outright. The message ends with the two commands to run. |
5 |
Only reachable via --attach <url>. Attach mode could not confirm your own dev server's config wires the Desde source stamper. Prints the exact config block to paste and the restart command to run before retrying. |
6 |
The same underlying failure as the second path in exit 4 (the in-process host failed to boot, or booted without proof it stamps source), except --host-mode in-process was passed explicitly, so Editor refuses loudly instead of silently routing you to attach mode. |
7 |
Two frameworks both look like the owner of this repository's dev server, each corroborated by its own config file on disk. Pass --host <id> naming the one you want; the message lists both candidates. |
130 |
You pressed Ctrl-C. |
143 |
The process received SIGTERM. |
Exit code 3 exists so a wrapping tool can tell "this repo is unsupported" apart from "the editor crashed" and react differently.
What triggers exit 3#
The check reads your prototype's package.json. Any of these refusals exits 3:
| Reason | Condition |
|---|---|
no-package-json |
No package.json at the path you gave. |
malformed-package-json |
It exists but does not parse. |
missing-framework |
Neither a vue nor a react dependency in dependencies, devDependencies or peerDependencies. Svelte, SvelteKit and Angular projects are refused here. |
wrong-vue-major |
vue pins a major other than 3. Vue 2 is not supported. |
missing-vite and no-vite-config no longer exist. They refused a repository for lacking
a Vite dependency or a root vite.config, which described what the Editor's own boot path
needed rather than anything wrong with the code. Which dev server to start is now a separate
decision made after this gate: Nuxt, React Router and Next.js are started for you, and a
project that fits none of the built-in hosts is offered
attach mode rather than turned away.
If both vue and react are present, Vue wins. A version range the parser cannot resolve to a single major (latest, workspace:*, ^2 || ^3) is treated as ambiguous and produces a warning rather than a refusal.
Argument parsing details#
Small behaviours that are easier to read here than to discover:
- Flags may come before or after the repository path. The parser walks the whole argument list.
- Exactly one positional argument is allowed in boot mode. A second one exits 2 with
Unexpected positional argument. Quote paths that contain spaces. - Value-taking flags consume the next argument unconditionally.
--shell-port --no-openreads--no-openas the port value, which is not a number. In boot mode that exits 2 with--shell-port and --vite-port must be numbers; when no repository path was given, the launcher ignores the unusable value and uses 4321. -hanywhere prints help, but only if the rest of the arguments parse. An unknown flag in the same command exits 2 first.- Anything starting with
--that is not in the table above is an error. Single-dash flags other than-hare not special-cased and are read as a positional argument.
What a successful boot prints#
▸ Vite running at http://127.0.0.1:5173
▸ Editor UI ready at http://127.0.0.1:4321
▸ Bridge version 2026-09-01a-callsite-edit-target
▸ Orchestrator: SDK (CLAUDE.md loaded natively)
▸ Smoke check passed (bridge tag + data-desde-src present in served output)Lines that appear only when they apply: the linked project slug, warnings from project-config or framework detection, the names of any configured read roots, and a smoke-check warning if the bridge tag or the data-desde-src source stamps were missing from the served output. The last block is a one-time setup hint for wiring the MCP server into a claude CLI session.
Use the exact host and port printed. The editor's API rejects requests whose Origin header is not exactly the printed origin, so opening http://localhost:4321 when http://127.0.0.1:4321 was printed loads the page but makes every action fail with a 403.
Stopping it#
Ctrl-C. The process shuts the Vite server and the HTTP server down, then exits 130. A second Ctrl-C while cleanup is running exits immediately.
Configuration#
Flags cover ports and asset paths. Everything else (chat behaviour, read roots, design systems, Figma, web access) lives in two JSON files in your prototype. See Editor configuration.