Skip to content

Latest commit

 

History

History
165 lines (118 loc) · 18.1 KB

README.md

File metadata and controls

165 lines (118 loc) · 18.1 KB

lt-dev Plugin

lenne.Tech Development Skills, Commands and Hooks for Claude Code - Frontend (Nuxt 4), Backend (NestJS), TDD and CLI Tools.

Installation

/plugin marketplace add lenneTech/claude-code
/plugin install lt-dev@lenne-tech

Recommended Plugins

These plugins enhance the experience when working with this plugin:

Plugin Marketplace Purpose Install Command
typescript-lsp claude-plugins-official TypeScript language server for better code intelligence (optional) claude plugin install typescript-lsp@claude-plugins-official
figma claude-plugins-official Required companion for the Figma commands (/lt-dev:frontend:figma-init, /lt-dev:frontend:figma-research, /lt-dev:frontend:figma-to-code) and the --figma=<url> flag of take-ticket / ticket-cycle; everything else works without it claude plugin install figma@claude-plugins-official

Features

  • Backend Development: NestJS with @lenne.tech/nest-server (supports both npm-mode and vendored-mode projects — see below)
  • Frontend Development: Nuxt 4 with Nuxt UI
  • TDD Workflows: Test-Driven Development with story-based implementation
  • Nest-Server Updates: Automated migration guides and stepwise upgrades (auto-delegates to nest-server-core-updater in vendored projects)
  • Fullstack Updates: Synchronize projects with latest starter templates
  • CLI Tools: lenne.Tech CLI integration
  • Git Workflows: Commit messages, MR descriptions, branch rebasing
  • Code Review: Nine review domains in parallel, filtered to proven Critical/High defects in what the diff actually changed, then fixed automatically. Everything below that bar is dropped rather than deferred, so one finished ticket does not leave ten follow-ups behind it — and a review that finds nothing ends clean
  • Runnability Gate: /lt-dev:check runs the project's check script with iterate-until-green auto-fix and mandatory audit-finding fix escalation (also integrated into review + rebase workflows)
  • Linear Integration: Issue management and story creation
  • Docker: Development and production setup generation
  • Package Maintenance: npm dependency management and security audits
  • Frontend Security: OWASP-based security auditing (XSS, CSRF, CSP)
  • Agent Teams: Parallel workflow coordination for complex tasks
  • Plugin Development: Claude Code plugin best practices and validation
  • Framework Contribution: Local pnpm link workflow for modifying @lenne.tech/nest-server / @lenne.tech/nuxt-extensions and validating changes from a starter
  • Dev Server Lifecycle: Enforced run_in_background / pkill contract to prevent orphaned processes across TDD, framework linking, and MCP-driven debugging
  • Alignment before code: A grilling loop that looks facts up in the codebase rather than asking, works every open decision through a brief (current code, planned change, quoted sources, options with their impact, recommendation), implements what the ticket states as written, settles gaps the evidence makes unambiguous, and asks the developer about everything imprecise, contradictory, or unclear — wired into ticket creation, planning, and the implementation flow
  • Parallel sessions: Coordination rules for several sessions working one project or the base repos at once. Linear and Git stay the claim protocol, ListAgents gives the live picture for free, and a cross-session message is spent only where it changes what the other session does next: a warning, a claim, a diagnosis worth handing over, or a question the peer answers cheaply
  • AI-proposed tickets stay distinguishable: anything Claude suggests off its own initiative is searched against the existing backlog first, then filed into Triage with a KI-Vorschlag label and no assignee — so a human decides whether a machine's idea becomes work, and a near-duplicate extends the existing ticket instead of splitting the discussion
  • Linear comments a product owner can actually read: the comment carries the plain-language summary and the complete test steps with links and example data; the technical detail moves into a Linear document attached to the ticket, which a later session reads back via get_document
  • Skills that trigger whatever the budget: the skill listing every session sees is capped at 1% of the context window and shared by all installed plugins. lt-dev keeps its share small (slash-only commands, one-line descriptions for skills only commands load) and gates it in Plugin CI against context-budget.json; skills with distinctive vocabulary are also named by a keyword hook (detect-skill-keywords.sh), so they are found even when their description is dropped from the listing
  • Writing quality: An unslop pass that strips AI tells from tickets, commit bodies, MR descriptions, docs, and customer copy, with a German pattern set (Nominalstil, Floskeln, Füllwörter, Gedankenstrich) on top of the English one

Included

  • Skills - Auto-detected contextual expertise (includes cleaning-up-disk-space for auditing and freeing disk space through deterministic scripts, maintaining-ai-models for keeping a project's LLM models available and measured, with a scheduled CI check, grilling-decisions for settling open decisions before implementation, running-check-script for runnability validation, managing-dev-servers for dev-server lifecycle rules, contributing-to-lt-framework for pnpm link workflows, coordinating-peer-sessions for parallel sessions on one project, writing-linear-comments and filing-ai-proposed-tickets for what reaches a Linear ticket and in what shape, and unslop for cutting AI tells out of every text that reaches a human)
  • Agents - Autonomous task execution
  • Commands - User-triggered actions via /lt-dev:<name>; the ones other commands invoke stay model-invocable, every other one runs only by slash and stays out of the skill listing
  • Hook scripts on SessionStart, SubagentStart, PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, StopFailure and SessionEnd - Automated project detection and validation
  • Helper Scripts - Plugin-local shell helpers under plugins/lt-dev/scripts/ (e.g. discover-check-scripts.sh for monorepo-aware check discovery, peer-ledger.sh for cross-session claims and diagnoses, change-provenance.sh for attributing changes this session did not write, repo-expert.sh for whether a live session works in the repository a change belongs to and the handover is the user's question, find-vault-logins.sh for the 1Password test accounts of a deployed stage, returned as login name plus private link and never as a secret, chrome-devtools-mcp-launcher.sh as Chrome MCP wrapper, context-budget.sh for what the plugin adds to every session, ai-models.mjs for the AI model check: provider catalog, announced shutdowns, capability probes and benchmark summaries, runnable in CI without Claude)
  • MCP servers - Chrome DevTools, Linear and Nuxt UI (Figma via the official figma plugin as a companion)

Chrome DevTools MCP — Canary auto-detection

The chrome-devtools MCP server is launched via scripts/chrome-devtools-mcp-launcher.sh. On macOS the launcher checks for Google Chrome Canary in /Applications/, ~/Applications/, and via mdfind on the bundle identifier com.google.Chrome.canary. If Canary is present, it appends --channel=canary so the automated browser shows up with the yellow Canary icon in the window switcher and is clearly distinguishable from the developer's daily-driver Chrome. Without Canary (or on non-macOS systems) it starts stable Chrome with no extra flags. A globally installed chrome-devtools-mcp is used only when it is at the pinned version; any other version, or none, starts the pin through npx.

Override the auto-detection with the CHROME_MCP_CHANNEL environment variable:

CHROME_MCP_CHANNEL=stable claude   # force stable even if Canary is installed
CHROME_MCP_CHANNEL=canary claude   # force canary (only useful for testing the flag)

Parallel sessions on one project

Claude Code sessions can list and message each other (v2.1.224+, on by default). The plugin uses that sparingly and in a fixed order.

Cheapest channel first. Linear stays the claim protocol for tickets and Git for branches, because both are free to read and stay true after a session ends. ListAgents adds who is alive right now. Only what none of those carry goes over a message, since a delivered message costs the receiving session a full prompt in the middle of its work.

Seven occasions justify one. Three protect a peer from doing the wrong thing (LANDED, CLAIM, CONFLICT), two save it work (SOLVED, READY), one asks it for something it answers cheaply (ASK), and one asks who wrote a change and what they were solving (ORIGIN). Progress reports, "I am finished", and anything readable in the repo are not on the list. The coordinating-peer-sessions skill holds the protocol; take-ticket, ticket-cycle, review, git:ship, dev-submit, debug, running-check-script, contributing-to-lt-framework, maintaining-lt-stack, rebasing-branches, and validating-changes-in-browser each apply it at the point where parallel work actually collides or actually helps.

A diff says what changed, never why. That gap is invisible while the session reading the diff is the session that wrote it, and three routine situations open it: base-repo work stays uncommitted by house rule, /clear drops a session's own memory while its files live on, and two sessions occasionally share a checkout. scripts/change-provenance.sh separates what this process wrote from what it found and names the live sessions that could explain the difference, so review, git:ship, dev-submit, debug, and rebasing-branches ask one targeted question instead of reviewing, committing, or resolving somebody else's work in progress as if it were their own. Reviewer sub-agents cannot reach a peer, so the orchestrator resolves it once and passes the answer down in every prompt.

What has to outlive a session gets written down. Messages are not history: a session starting later never learns what was sent before it existed, and a claim dies with the session that made it. scripts/peer-ledger.sh persists the two cases where that loss is expensive — open claims on cross-cutting work, and diagnoses worth keeping — per repository under ~/.claude/lt-dev/peer-ledger/, never inside a project. A claim is bound to its session's process, so a crashed session's claim reads as stale and free to take instead of blocking the topic forever.

/lt-dev:peers answers it on demand. Live sessions, open claims, recorded diagnoses, and any foreign uncommitted changes in one read-only report. It sends nothing.

A SessionStart hook says when it matters. detect-peer-sessions.sh reports how many other sessions are live and how many of them sit in this repository, so coordination is a question only when there is something to coordinate with.

Coordination is settled between sessions; decisions go to you. Who takes which ticket, who fixes a shared finding, and who waits for whom are resolved session-to-session without a prompt. Scope, priority, risk, anything destructive, anything a permission prompt would cover, and a contested claim that one exchange did not settle always reach the user.

/lt-dev:briefing says what is left for you. It re-checks every open thread of the session against its source (git, pipelines, releases, tickets, peer sessions, asking a peer only what only it knows), finishes what Claude can still do on its own, and then lists in plain words the decisions that are yours and the tasks only you can do, each with a step-by-step guide and complete links. It also runs when you just ask "Was ist noch offen?".

One setup caveat. With crossSessionInbound unset, Claude Code decides per message from both sessions' permission modes and delivers only when the two match (both bypassing prompts, or both prompting). Mixed in either direction means an approval dialog that expires after dialogExpiry, five minutes by default — which is exactly how coordination fails on unattended sessions. Setting crossSessionInbound: "accept" in user settings (or via /config → "Messages from your other sessions") removes the classification and is the fix; matching permission modes is the workaround when the default has to stay.

Unattended processing with /loop

/loop /lt-dev:ticket-cycle --autopilot --project=<Linear project> --team=<Linear team>

--autopilot runs the whole ticket cycle without a single question, so /loop (without an interval, self-paced) works a project ticket by ticket while nobody is at the screen. Starting it is your standing approval for its defaults: the decision round settles every open point by its recommendation and posts the decisions comment, the run reviews, walks the browser, attaches the test package to the ticket as a document, auto-merges after a green pipeline and verifies the dev deploy. Tickets of other repositories are skipped; a Blocked ticket is taken once its blockers are Done, or merged into the base branch as Git shows.

What no default can settle is parked: the work is pushed to its branch, the ticket gets a comment with the question and Claude's recommendation, goes to Blocked and is assigned to you. A problem of the environment (expired access, a dirty base branch, Docker or an MCP server down, or the same cause twice in a row) halts the loop instead of parking ticket after ticket. Each run ends with an AUTOPILOT-RESULT: line; AUTOPILOT: NOTHING-LEFT and AUTOPILOT: HALT <reason> end the loop. The full list of questions and their defaults is in commands/ticket-cycle.md → "Autopilot". The autopilot never publishes content, never promotes dev into a higher branch, never sets a ticket to Done, and never bypasses a hook or gate.

Framework consumption modes (nest-server)

lenne.Tech API projects can consume @lenne.tech/nest-server in one of two modes:

  • npm mode (classic): @lenne.tech/nest-server is installed as a dependency. Framework source lives in node_modules/@lenne.tech/nest-server/. Imports use the bare specifier from '@lenne.tech/nest-server'. Updated via /lt-dev:backend:update-nest-server → nest-server-updater agent.
  • vendored mode: the framework's core/ directory is copied directly into the project at <api-root>/src/core/ and managed as first-class project code. There is NO @lenne.tech/nest-server npm dependency. Imports use relative paths (from '../../../core'). Local patches are allowed and logged in <api-root>/src/core/VENDOR.md. Updated via /lt-dev:backend:update-nest-server-core → nest-server-core-updater agent; local changes are proposed back upstream via /lt-dev:backend:contribute-nest-server-core → nest-server-core-contributor agent.

Detection: test -f <api-root>/src/core/VENDOR.md → vendored, else npm. The detect-nest-server hook, the nest-server-updater agent, and the nest-server-core-vendoring skill all perform this check automatically and branch accordingly. All skills and agents that reference framework files (generating-nest-servers, building-stories-with-tdd, backend-dev, etc.) carry a preamble listing both path conventions.

Linear conventions

New tickets are created in Open — always, unless the user explicitly asks for another status. This is not cosmetic: the auto-pick pool of /lt-dev:take-ticket and /lt-dev:ticket-cycle is Open ∪ Fix needed and deliberately excludes Backlog (what the team consciously deferred must not be picked up automatically). A ticket filed in Backlog is therefore invisible to the whole cycle until someone moves it by hand.

This applies everywhere a ticket is created — the guided /lt-dev:create-* commands, follow-ups spun off during take-ticket / ticket-cycle / review, and ad-hoc tickets created directly via the Linear MCP.

Two deliberate exceptions:

  • A ticket Claude proposes on its own initiative goes to Triage, not Open, with a KI-Vorschlag label and no assignee. Open means somebody committed to the work; a machine's suggestion has not been decided yet, and Triage is where that decision happens. Where the team has no Triage state, such a ticket falls back to Open — still never Backlog. The rules, including the duplicate search that runs first, live in the filing-ai-proposed-tickets skill.
  • A follow-up that can only be worked after the current change is merged is not created at all until that merge has landed (see the dependency gate in take-ticket STEP 9a) — precisely because an Open ticket is immediately pickable by a parallel session.

In a project that spans several repositories, every ticket names its repository in its description: **Repo:** \/`, or Repo: — (Inhalt)plus the labelInhaltfor content work without a merge request. A ticket without the line is worked in the repository of the session that picks it.take-ticketreads the line before it cuts a branch, offers the ticket to a live session in the named repository, and implements it there itself when none takes it, after the user has moved the session there with/cd`.

Further Reading

The comprehensive guide for the full lenne.Tech fullstack ecosystem — covering both the lt CLI and this lt-dev plugin — is maintained in the CLI repository:

  • LT-ECOSYSTEM-GUIDE — Full reference: architecture, CLI commands, plugin commands, agents, skills, vendor-mode workflows, decision matrix, glossary
  • VENDOR-MODE-WORKFLOW — Step-by-step guide: npm → vendor conversion, update workflows, vendor → npm rollback, troubleshooting

Both documents reference each other and are kept in sync with CLI releases.

For lenne.Tech team members

Authorized lenne.Tech team members have access to additional internal plugins via a private, unlisted marketplace (separate from the public lenne-tech marketplace). Access and setup are covered in internal onboarding — ask your team lead if you don't have it yet.

License

MIT - lenne.tech GmbH