Skip to content
Development
Command

/init

Initialize LETS in current project - creates .lets/ structure, config, statusline, beads; offers user-scope global-rules install when the plugin is user-scoped

From plugin
lets-workflow
1726 skills15 agents26 commands
> /plugin marketplace add restarter/lets-workflow
> /plugin install lets@lets-workflow

Command definition

init.md
description: Initialize LETS in current project - creates .lets/ structure, config, statusline, beads; offers user-scope global-rules install when the plugin is user-scoped

Project Initialization

Per-project LETS setup. Bridges to `lets init --json` (Go binary) for all filesystem mutation. Slash command captures user prefs via AskUserQuestion, exec's the binary, parses JSON stdout, renders to user.

> **IMPORTANT:** If the spec below invokes any deferred tool (e.g. `AskUserQuestion`), you MUST load and call it as specified. Never skip the call, never substitute a default answer of your own — the tool invocation is part of the contract. This is critical.

> **MANDATORY:** Execute every Step's bash block **literally as written**. Do not substitute output from earlier `ls`/`cat`/`bd show` in this conversation — `.env` and other dotfiles are invisible to plain `ls`. The `test -f` / `test -d` checks below ARE the contract for branching first-time-vs-re-run paths; shortcutting them produces wrong branches.

Step 1: Pre-checks

command -v lets >/dev/null 2>&1 || { echo "NO_LETS_BINARY"; exit 0; }
LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || echo "NOT_GIT_REPO"
if [ -n "$LETS_PROJECT_ROOT" ]; then
  test -f "$LETS_PROJECT_ROOT/.lets/.env" && echo "ENV_EXISTS" || echo "ENV_ABSENT"
  test -d "$LETS_PROJECT_ROOT/.beads" && echo "BEADS_EXISTS" || echo "BEADS_ABSENT"
fi

Branch on output:

  • `NO_LETS_BINARY` → tell user "`lets` binary not found on `$PATH`. Install it — `! curl -fsSL https://raw.githubusercontent.com/restarter/lets-workflow/main/scripts/install.sh | bash` (the leading `!` runs it in this session; or the same command without `!` in a terminal). See the README → Quick Start." NO LETS box. STOP.
  • `NOT_GIT_REPO` → ask user via AskUserQuestion (Step 1a below). If user picks "Init git" → run `git init`, recompute LETS_PROJECT_ROOT, ENV_ABSENT/BEADS_ABSENT (both will be absent for fresh repo). If "Cancel" → stop, NO LETS box.
  • `ENV_ABSENT` → first-time path (Step 2). Use `BEADS_ABSENT`/`BEADS_EXISTS` to decide whether to ask about beads init in Step 2c-bis.
  • `ENV_EXISTS` → re-run path (Step 3). Don't re-ask about beads — `lets init` self-heals (StepSkip if already inited; StepWarn if bd not on PATH).

1a. Git init prompt (only if NOT_GIT_REPO)

AskUserQuestion( questions=[{ question: "This directory is not a git repository. Initialize git here?", header: "Git init", options: [ { label: "Init git", description: "Run `git init` here, then continue with this init flow (LETS workflow assumes git)" }, { label: "Cancel", description: "Stop. Run `git init` manually first or cd to a git repo." } ], multiSelect: false }] )

If "Init git":

git init -q
LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)

Then proceed with first-time path (ENV_ABSENT, BEADS_ABSENT both true for fresh repo).

If "Cancel" → STOP. NO LETS box.

1b. Plugin install scope check

PLUGINS_FILE="$HOME/.claude/plugins/installed_plugins.json"
SCOPE=""
if [ -f "$PLUGINS_FILE" ] && command -v python3 >/dev/null 2>&1; then
  SCOPE=$(python3 -c "
import json, sys
try:
    d = json.load(open('$PLUGINS_FILE'))
    entries = d.get('plugins', {}).get('lets@lets-workflow', [])
    print(entries[0].get('scope', '') if entries else '')
except Exception:
    pass
" 2>/dev/null)
fi
echo "SCOPE=${SCOPE:-unknown}"

Branch on `$SCOPE`. When the plugin is found (`project` / `user` / `local`) **lead** with the **auto-update recommendation** - this is the single biggest update-UX win, so present it prominently (not as a footnote): > ✅ **Do this once - it removes the manual plugin update forever:** `/plugin` → **Marketplaces** → `lets-workflow` → **Enable auto-update**. The plugin then tracks every LETS release on its own, so ongoing updates collapse to a single `/lets:update` loop (run it, do the one thing it says, re-run until `✓ Everything on vX.Y.Z`) - no `/plugin marketplace update` step to remember. (Claude Code has no setting the `lets` binary can flip - this is a one-time UI action only you can do.)

Additionally:

  • `project` → just the auto-update recommendation. Best case.
  • `user` → the auto-update recommendation **plus** the global-rules check:
  test -f "$HOME/.claude/rules/lets-rules.md" && echo "GLOBAL_RULES_PRESENT" || echo "GLOBAL_RULES_ABSENT"
  • `GLOBAL_RULES_PRESENT` → one line: "ℹ️ User-scope install detected — global rules active (`~/.claude/rules/lets-rules.md`); `/lets:update` keeps them current." Continue.
  • `GLOBAL_RULES_ABSENT` → offer the install (AskUserQuestion, header `User scope`):
  • "Install global rules (Recommended)" - description: "Writes ~/.claude/rules + ~/.lets/.env defaults; every project gets LETS rules without per-project init"
  • "Project-only" - description: "Skip global install; this project gets its own rules copy below"

If installed → run, then render its `steps[]` like Step 2e renders project steps:

    lets init --user --json --plugin-root="${CLAUDE_PLUGIN_ROOT}" --language="{LANGUAGE}"

(`{LANGUAGE}` is an orchestrator placeholder — substitute the English language name BEFORE running. If no language is bound yet (Step 2a hasn't run), ask Step 2a's language question first. NEVER leave a bash variable here: `$LANG` is the POSIX locale env var (`en_US.UTF-8`) and bash would expand it, silently poisoning `~/.lets/.env` in every future session. Add `--launcher={LAUNCHER}` only if the user customized the launcher this session.)

  • One-line note stays for teams: "For team adoption, project scope is still preferable (`/plugin install` → 'all collaborators')."
  • `local` → just the auto-update recommendation. User picked the scope deliberately, so no scope-change notice.
  • `unknown` (empty / file missing / dev `--plugin-dir` mode) → no notice at all.

These are informational, not blockers. Continue with Step 2/3 regardless.

Step 2: F

Read more
@restarter
Ships withlets-workflow

A development workflow plugin for Claude Code Stop babysitting your AI. Start shipping with it.

1725 skills15 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
17
Star history of restarter/lets-workflow on GitHub, a chart by star-history.com

Other commands on lets-workflow.

backlog

backlog

Command

Backlog review and cleanup - multi-agent backlog review, quick no-agent pulse (--fast), or interactive triage cleanup

end

end

Command

End a work session - a settlement pass that reconciles uncommitted / unpushed work + session context into git, the tracker, and a…

execute

execute

Command

Execute implementation plan from /lets:plan - inline in native plan mode, or delegated to named implementer subagents you review…

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command