managing-dev-servers
Managing Dev Servers
Local development servers (npm run dev, nuxt dev, nest start, pnpm build --watch, pnpm test:watch, etc.) are long-running processes. If they are started uncontrolled in the background, Claude Code cannot reliably reclaim them, the session blocks on "Unfurling..." without consuming tokens, and the user must press ESC to continue.
Apply these rules whenever you start any such process — regardless of whether you are inside a TDD cycle, a framework-linking session, a manual validation run, or an MCP-driven debugging flow.
Decision tree — what to run before any dev server
The plugin's detect-lt-dev hook injects a context block on every prompt in the main session and at the start of every lt-dev agent. Use that block as your switch:
- "Active lt-dev project" with
session: yes— Project registered AND running. Use the URLs from the block. Do nothing extra; for browser tests / API calls use the URLs as-is. - "Active lt-dev project" with
session: no— Project registered, not running. For the Playwright/E2E suite runlt dev test(isolated parallel stack on a dedicated<slug>-testDB — never touches dev data, auto-teardown). For manual browser tests, Chrome DevTools MCP, or API probes, runlt dev upfirst. The "lt-dev ticket worktree … stack not up yet" block is this case for an isolated per-ticket stack: runlt dev upin that worktree. - "lt-Stack project detected — not yet migrated" — The repo uses
@lenne.tech/*packages but has no registry entry. When it has the layoutlt devserves (aprojects/api/orprojects/app/directory, or at the rootsrc/config.env.tsornest-cli.json(API) ornuxt.config.ts(app)), runlt dev init(idempotent, safe — patches legacy ports, registers, updates CLAUDE.md), thenlt dev up; do not startpnpm dev/pnpm startas a workaround. Without that layout (a library, the lt CLI, a plugin repo) the block is a misdetection, andlt dev initwould stop with "No lt project detected at this path": continue as case 4. - No block — A project
lt devdoes not serve. Use the classicrun_in_background: true+pkillpattern documented below. Exception: in a subagent that is not an lt-dev agent (general-purpose, Explore, another plugin's agent) the block never arrives, so its absence proves nothing. There, check yourself what the hook checks: the case 3 layout plus lt evidence (anlt.config.json, an@lenne.tech/*dependency inpackage.jsonorprojects/api|app/package.json, or a root package named@lenne.tech/*or after an lt starter); a plain Nuxt or NestJS app without it stays on the classic pattern. With both, runlt dev status: a registered project prints its URLs (and "nolt dev upsession active" when it is down, then continue as case 2), while "Not registered" means case 3.
If lt dev up later complains that Caddy is missing or the daemon is not running, run lt dev install first. One-time per machine: