LT CLI Reference
Gotchas
lt fullstack initwithout--noConfirmblocks Claude Code forever — The interactive prompts (project name, git init, template selection) wait for stdin input. Claude Code cannot respond to them, and the session hangs on "Unfurling..." with no token consumption. Pass--noConfirm+ all required flags (--name X --frontend nuxt --git false) when calling lt CLI from Claude Code.--api-linkand--frontend-linkcreate SYMLINKS, not copies — Changes to the template checkout (nest-server-starter,nuxt-base-starter), wherever it lives on this machine, immediately affect the linked project. This is a feature for framework development but surprises developers who expect copies. Document it in the project README when using--api-link.lt git resetis DESTRUCTIVE and irreversible — Lives next to the safelt git getin the CLI menu.resetdoesgit reset --hardfollowed by force-pull, destroying ALL local changes without confirmation. Never run it on a branch with unpushed work. Prefergit stash+lt git get.lt server object X --controllergenerates REST, NOT GraphQL — Default is REST. For GraphQL projects, use--resolver. The CLI does not auto-detect from existing project patterns — you must specify explicitly.lt fullstack convert-moderewrites the source tree — Switching betweennpmandvendormode moves framework code in/out ofsrc/core/(API) orapp/core/(App). The operation is reversible but NOT idempotent mid-run — always commit before starting, so a failed conversion can be rolled back viagit reset.--nextis experimental and incompatible withlt server module/object/addProp/test/permissions— Whenlt server create --nextorlt fullstack init --nextis used, the API is cloned fromnest-base(Bun + Prisma 7 + Postgres + Better-Auth) instead ofnest-server-starter. The downstream generators target the classic nest-server layout (Mongoose models, src/server/modules/, etc.) and will not work on a nest-base project. Use it for greenfield prototyping only; for production work prefer the default template.- macOS: a long
$TMPDIRbreaks Nuxt SSR underlt dev up— On macOS,$TMPDIRis a long per-user path (/var/folders/…, often >~49 chars). Nuxt 4.4.7's vite-node builds a Unix domain socket path under it that exceeds the OS 104-character limit → SSR crashes with a 500. Workaround: start with a short tmp dir,TMPDIR=/tmp lt dev up. (Linux$TMPDIR=/tmpis short, so this only bites on macOS.) - macOS: HMR WebSocket port 24678 collides between parallel
lt devprojects — Twolt devprojects running at once both try to bind Vite's HMR WS port 24678.vite.server.hmr.portis ignored by Nuxt 4.4.7, so you cannot reassign it in config. This is non-fatal — SSR recompile still works; only live-HMR pushes on the second project are affected. Reload the page to pick up changes there.
Skill Boundaries
| User Intent | Correct Skill |
|------------|---------------|
| "lt fullstack init" | THIS SKILL |
| "lt git get feature-branch" | THIS SKILL |
| "lt server create my-project" | THIS SKILL |
| "lt server module / object / addProp" | generating-nest-servers |
| "lt server permissions" | generating-nest-servers |
| "Create a NestJS module" | generating-nest-servers |
| "Build a Vue component" | developing-lt-frontend |
| "lt deployment create" | THIS SKILL (see the lt deployment create command) |
| "Deploy to TurboOps / go live / turbo deploy / deployment stage" | deploying-to-turboops |
After lt fullstack init:
- Backend work (projects/api/) →
generating-nest-servers - Frontend work (projects/app/) →
developing-lt-frontend
Commands
lt git get — Checkout/Create Branch
lt git get <branch-name> # alias: lt git g
- Branch exists locally → switches to it
- Branch exists on remote → checks out and tracks
- Neither exists → creates new branch from current
lt git reset — Reset to Remote
lt git reset
Fetches latest from remote, resets current branch to origin/<branch>. Destructive — all local changes lost.
lt fullstack init — Create Fullstack Workspace
# Non-interactive
lt fullstack init --name <Name> --frontend <angular|nuxt> --git <true|false> --noConfirm \
[--git-link <URL>] [--api-link <path>] [--frontend-link <path>] [--next]
| Parameter | Required | Description |
|-----------|----------|-------------|
| --name | Yes | Workspace name (PascalCase) |
| --frontend | Yes | angular or nuxt |
| --git | Yes | Initialize git: true / false |
| --noConfirm | No | Skip confirmation prompts |
| --git-link | No | Git repository URL |
| --api-branch | No | Branch of nest-server-starter |
| --frontend-branch | No | Branch of frontend starter |
| --api-copy / --api-link | No | Local API template (copy / symlink) |
| --frontend-copy / --frontend-link | No | Local frontend template (copy / symlink) |
| --next | No | Experimental — clone nest-base (Bun + Prisma 7 + Postgres + Better-Auth) for the API. Forces apiMode = Rest, frameworkMode = npm, and skips the workspace install (run pnpm install for app and bun install for api manually). Downstream lt server module/object/addProp/test are NOT compatible with the resulting layout. |
Priority: --*-link > --*-copy > --*-branch > default (GitHub clone)
Created structure:
<workspace>/
├── projects/
│ ├── api/ ← nest-server-starter (or nest-base with --next)
│ └── app/ ← nuxt-base-starter (or ng-base-starter)
├── package.json
└── .gitignore
Post-creation:
cd <workspace> && pnpm install
lt dev init # idempotent: ENV patches + register; auto-runs `lt dev install` first if the machine isn't set up yet
lt dev up # Start API + App behind Caddy under https://<slug>.localhost
# With --next: install per subproject, no workspace install
cd <workspace>/projects/app && pnpm install
cd <workspace>/projects/api && bun install
(Falls back to pnpm -r --parallel run start on default ports 3000/3001 if lt dev is not used.)
lt dev — Parallel Project Orchestration (Caddy + HTTPS)
Serves every lt project under stable HTTPS URLs (<slug>.localhost, api.<slug>.localhost) via Caddy so multiple projects can run side by side without colliding on 3000/3001 and without auth cross-wiring. Use this in every lt-monorepo or standalone API/App project.
lt dev install # One-time per machine: bootstraps dedicated LaunchAgent/systemd unit + Caddyfile stub + CA reminder
lt dev uninstall [--purge] # Remove the lt-dev service (--purge also drops Caddyfile + logs)
lt dev init # Once per project (idempotent): ENV patches + register
lt dev up # Start API + App behind Caddy
lt dev down # Stop processes + remove Caddy block (also tears down any isolated test stack)
lt dev test # ISOLATED Playwright E2E: parallel stack + dedicated `<slug>-test` DB, auto-teardown
lt dev test --shard # Shard across 2 isolated stacks (default — stable sweet spot)
lt dev test --shard 3 # Shard across N isolated stacks (each own ports/Caddy/DB `<slug>-test-<i>`)
lt dev test --shard auto # Size N from this machine's CPU + RAM (conservative)
lt dev test down # Tear the isolated test stack(s) down (residue-free)
lt dev status # Show URLs + PIDs + live upstream state for THIS project (incl. any test stack)
lt dev status --all # List every registered project + running state
lt dev doctor # Diagnose Caddy / CA / DNS / port issues
lt dev tunnel [--api] # Foreground Cloudflare Quick Tunnel: public *.trycloudflare.com URL
What each subcommand does:
install— One-time per machine. Verifiescaddyis on PATH (suggestsbrew install caddyif missing), creates~/.lenneTech/Caddyfilestub, writes + bootstraps a dedicated LaunchAgent (macOS,~/Library/LaunchAgents/tech.lenne.lt-dev-caddy.plist) or systemd-user unit (Linux). Waits up to 8s for the Caddy admin endpoint (:2019) to respond, validates the file, and reminds you to runsudo -E HOME="$HOME" caddy trust(the-E HOME="$HOME"is mandatory — without it sudo switches HOME to/var/rootand the CA install silently fails). Does NOT usebrew services start caddy— its plist hardcodes--config /opt/homebrew/etc/Caddyfileand crash-loops against our Caddyfile location. Auto-chains: when run inside an un-initialized lt-dev project, runsinitafterwards (--skip-initto opt out).uninstall— Symmetric counterpart toinstall. Boots out the LaunchAgent / systemd unit, removes the unit file. With--purgealso deletes~/.lenneTech/Caddyfileand caddy logs. Does NOT remove the caddy binary itself (usebrew uninstall caddyif desired).init(aliasmigrate) — Idempotent. Builds the project identity (slug =package.json"name", subdomains from monorepo layout), patches legacy hardcodedport: 3000/port: 3001/ Vite-proxy targets / Playwright URLs to env-aware variants (defaults preserved), persists to~/.lenneTech/projects.json, injects a "Local Development (lt dev)" URL block into allCLAUDE.mdfiles, adds.lt-dev/to.gitignore. Auto-chains: runsinstallfirst when the machine isn't prepared yet (--skip-installto opt out).up— Allocates internal upstream ports (4000+, never 3000/3001), upserts the Caddy block withreverse_proxy 127.0.0.1:<port>+ reloads, exportsPORT,HOST=127.0.0.1/NITRO_HOST=127.0.0.1(pins dev servers to IPv4 so the upstream is unambiguous),BASE_URL,APP_URL,NUXT_API_URL,NUXT_PUBLIC_API_URL,NUXT_PUBLIC_SITE_URL,NUXT_PUBLIC_STORAGE_PREFIX,NUXT_PUBLIC_API_PROXY=false,NSC__MONGOOSE__URI,DATABASE_URL,NODE_EXTRA_CA_CERTS(Caddy root CA so Nuxt SSR fetches trust HTTPS), plus legacy aliasesAPI_URL/SITE_URLfor projects that pre-date theNUXT_*convention. Then spawnspnpm start(api) +pnpm dev(app) detached. Pre-flight checks refuse to start when Caddy is missing, Caddy daemon is down, an existing session is alive, or internal ports are bound. Logs at<root>/.lt-dev/{api,app}.log.down— Sends SIGTERM to the saved process group (negative PID) so children (Vite, Nest watcher, etc.) receive it too. Removes the project's Caddy block + reloads. Also tears down any isolated test stack (lt dev test) for this project.test— ISOLATED E2E. Brings up a SECOND, parallel stack (<slug>-test.localhost/api.<slug>-test.localhost, own ports + Caddy block +.lt-dev/.env.testbridge) on a dedicated DB<slug>-test(separate from the dev<slug>-localand the API-test<slug>-e2e), runs the Playwright suite (global-setup resets that DB once before the first test), then auto-tears-down residue-free. Runs alongside — and never touches — the dev session.--keepleaves it up;lt dev test downstops it;--apiruns the (already isolated) API tests instead;--debug= PWDEBUG+headed;-- <args>forwards to Playwright.--shard Nruns the suite split across N FULLY-isolated stacks in parallel (each own ports + Caddy block + DB<slug>-test-<i>) + N--shard=i/NPlaywright processes — the local CI-parity matrix. A bare--sharddefaults to 2 (the stable sweet spot: N≥3 over-subscribes the perf cores on a typical dev machine → flaky);--shard autosizes N from CPU+RAM (conservative). Local shards share ONE machine (unlike CI's per-shard containers), so the CLI exportsLT_DEV_TEST_SHARDSfor the project's playwright.config to relax timeouts under that load only (CI stays fast).lt dev test downreclaims all shards. Requires the lt CLI version that ships this isolated session.status/status --all— Current project: subdomains → upstream ports, db URI, session PIDs (alive/dead), livelsofupstream state.--all: every registered project with a●/○indicator.doctor— Caddy on PATH, lt-dev LaunchAgent / systemd unit loaded, daemon running, Caddyfile valid, ports 80/443 free or held by Caddy,*.localhostresolves (IPv4 or IPv6 loopback), registry status.tunnel— Foreground Cloudflare Quick Tunnel:cloudflared tunnel --url https://<slug>.localhost --http-host-header <slug>.localhost --no-tls-verify. Prints a public*.trycloudflare.comURL (5-10s) and runs until Ctrl-C. Default exposes the App;--apiswitches the target. Auth cookies on the localhost domain are NOT valid on the tunnel URL — add the tunnel URL to Better-Auth'strustedOriginsfor login flows to succeed. Start a secondlt dev tunnel --apiin parallel for full external usage.
Override the spawn binary via LT_PNPM_BIN (e.g. for bun-based projects via wrapper script).
lt ticket — Parallel ticket dev environments
Work on several tickets/features of ONE project at the same time — each in its
OWN git worktree + its OWN isolated lt dev stack (own URLs, ports, Caddy block,
empty DB) — so several tickets can be browser-tested AND E2E-tested in parallel
without any cross-influence.
lt ticket start DEV-2200 # worktree (branch feat/DEV-2200 from origin/dev) + pnpm install + lt dev up
# → https://shop-2200.localhost / https://api.shop-2200.localhost, DB shop-2200 (empty)
lt ticket start checkout-refactor # no ticket? a free feature name works too → shop-checkout-refactor.localhost
lt ticket start DEV-2200 --as cof # override the short id; --branch / --base override branch / base ref (default origin/dev)
lt ticket list # dashboard: every ticket env + URLs + branch + status + DB (re-view URLs anytime)
lt ticket switch <id> # show the worktree path + open it in $LT_EDITOR (default `code`)
lt ticket test <id> [--shard N] # run the E2E suite in the ticket's isolated stack/DB (delegates to lt dev test)
lt ticket stop <id> [--drop-db] # lt dev down + remove the worktree (branch kept); --drop-db also drops the ticket DBs
- Isolation: ticket
DEV-2200→ short id2200; a free name is used as-is. Every ticket gets<slug>-<id>EVERYWHERE — URLs<slug>-<id>.localhost/api.<slug>-<id>…, dev DB<base>-<id>, test DB<base>-<id>-test[-<shard>], own ports + Caddy block + session. The sibling worktree folder<parent>/<slug>-<id>matches the URL, so you always know which ticket you are in. - Always from fresh
dev:startdoesgit fetch+ branches fromorigin/dev, so every ticket is independent (--base <ref>to start elsewhere). Worktrees share ONE.git— onegit fetchupdates all, creation is instant, teardown is git-tracked (vs. a full clone per ticket: slower, duplicates.git, untracked). - Claude-aware automatically: a gitignored
.lt-dev/ticketmarker tags the worktree → everylt dev *run in it is ticket-aware with NO flags, and the lt-dev hook surfaces the ticket id + URLs each prompt. The git-trackedCLAUDE.mdis never modified per ticket (no git noise). - DB-wiping
global-setup: allow the per-ticket test-DB pattern<base>-<id>-test(-<n>)in the project's allow-list (an allow-list function such asisAllowedDbin the project'stests/global-setup.ts) + local-DB guard — only…-testnames, never a ticket's dev DB.
lt server create — Scaffold New Server
lt server create <name> --noConfirm [--branch <branch>] [--copy <path>] [--link <path>] [--next]
Creates a standalone NestJS project from nest-server-starter. With --next, clones nest-base (Bun + Prisma 7 + Postgres + Better-Auth) instead and skips API-mode / vendor-mode / install / lt.config.json processing. For module/object/property commands, see generating-nest-servers skill — those are NOT compatible with --next projects.
lt deployment create — Wire the Project to TurboOps
lt deployment create --noConfirm
Run from the repo root. Writes .turboops.json = { "project": "<slug>" } at
the repo root — the link between the repo and its TurboOps project (<slug> =
the TurboOps project slug). CI reads this file, so commit it.
This is only the first step of taking an lt fullstack project live. The complete
end-to-end flow — GitLab CI/CD variables (TURBOOPS_PROJECT + the masked
TURBOOPS_TOKEN minted in the TurboOps web UI), creating a multi-service
deployment stage via the TurboOps web UI (never the single-service MCP
bootstrap), DNS-before-Let's-Encrypt, the swarm Mongo URI, and CI-driven
redeploys — is documented in the deploying-to-turboops skill and driven by
the /lt-dev:deployment:setup command. Read that skill before creating a stage;
it documents the two MCP traps that silently produce a broken fullstack deploy.
Best Practices
- Always use
--noConfirmfrom Claude Code to avoid blocking prompts - Run
git statusbeforelt git reset— it's irreversible - Use PascalCase for workspace names
- Use
--api-link/--frontend-linkfor local template development (fastest) - After init:
pnpm install→ start API → start App
Reference Files
| Topic | File | |-------|------| | Command reference & troubleshooting | reference.md | | Real-world examples | examples.md |
External Documentation (Canonical Source)
The authoritative references live in the lenneTech/cli GitHub repository. Fetch via WebFetch when deep context is needed:
| Document | URL | When to fetch |
|----------|-----|---------------|
| LT-ECOSYSTEM-GUIDE | https://raw.githubusercontent.com/lenneTech/cli/main/docs/LT-ECOSYSTEM-GUIDE.md | Full reference for CLI + plugin (architecture, commands, agents, skills, vendor-mode, glossary) |
| VENDOR-MODE-WORKFLOW | https://raw.githubusercontent.com/lenneTech/cli/main/docs/VENDOR-MODE-WORKFLOW.md | Step-by-step guide for npm ↔ vendor conversion, vendor updates, rollback |
| Command Reference | https://raw.githubusercontent.com/lenneTech/cli/main/docs/commands.md | Full CLI command reference with all options |
| Configuration Guide | https://raw.githubusercontent.com/lenneTech/cli/main/docs/lt.config.md | lt.config.json reference |
When to fetch: When user asks about architecture/design decisions, vendor-mode conversion steps, or any CLI/plugin function not covered by this skill's condensed content.
Related Skills
generating-nest-servers—lt server module,lt server object,lt server addProp,lt server permissionsdeveloping-lt-frontend— Nuxt/Vue frontend developmentbuilding-stories-with-tdd— TDD workflow orchestrationdeploying-to-turboops— take an lt fullstack project live on TurboOps via CI/CD (the full flow afterlt deployment create)
Scan to join WeChat group