@lumpcode/cli 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,244 @@
1
+ # Example lumps
2
+
3
+ Seven common shapes for a lump, each a complete, drop-in `.lumpcode/lumps/<name>/config.json` (or `config.js`). Mix and match: a campaign can use `contextMatchFn` for discovery and a multi-step `steps` workflow; a ticket queue can include `setupFn` to install deps before the agent runs; a sweep can add `branchFn` to follow your team’s naming convention.
4
+
5
+ Deep references: [concepts.md](./concepts.md), [lump-config.md](./lump-config.md), [advanced-config.md](./advanced-config.md), [types.md](./types.md).
6
+
7
+ ---
8
+
9
+ ## 0. Smoke test — one context, minimal prompt
10
+
11
+ *When to use:* right after `lumpcode lump-create` to confirm login, remotes, agent command, and marker commits before you invest in a real campaign.
12
+
13
+ Uses a single fixed path every repo already has (`README.md`). Adjust `FILE` if your project root has no `README.md`.
14
+
15
+ `.lumpcode/lumps/smokeTest/config.json`:
16
+
17
+ ```json
18
+ {
19
+ "contextListJson": {
20
+ "FILE": "README.md"
21
+ },
22
+ "prompt": {
23
+ "promptTemplate": "Reply with exactly one line: smoke OK for @{FILE}. Do not edit any file.",
24
+ "command": "claude"
25
+ }
26
+ }
27
+ ```
28
+
29
+ (`baseBranch` defaults to `projectBaseBranch` from `.lumpcode/local.json`; add it on a lump only to override.)
30
+
31
+ Run once: `lumpcode run smokeTest`, then `git log --remotes --grep '^LUMP:' --oneline` and `lumpcode lump-status --lumpName smokeTest`.
32
+
33
+ ## 1. Framework migration campaign — React → Vue, one component per branch
34
+
35
+ *When to use:* large UI migration with one reviewable PR per component.
36
+
37
+ A classic refactoring lump: discover every component folder, do a multi-step migration, ship one PR per component.
38
+
39
+ ```json
40
+ {
41
+ "command": "claude",
42
+ "contextListJson": {
43
+ "FOLDER": "src/components/{COMPONENT_NAME}/",
44
+ "TYPES": "src/components/{COMPONENT_NAME}/{COMPONENT_NAME}.types.ts",
45
+ "TEST": "src/components/{COMPONENT_NAME}/{COMPONENT_NAME}.test.ts",
46
+ "COMPONENT": "src/components/{COMPONENT_NAME}/$upperFirst{COMPONENT_NAME}.tsx"
47
+ },
48
+ "steps": [
49
+ "Read @{COMPONENT}, @{TYPES}, and @{TEST}. Produce a short migration plan and save it to src/components_vue/{COMPONENT_NAME}/migration-plan.md (no source changes yet).",
50
+ "Following the plan at src/components_vue/{COMPONENT_NAME}/migration-plan.md, port @{COMPONENT} to a Vue 3 <script setup> component at src/components_vue/{COMPONENT_NAME}/{COMPONENT_NAME}.vue. Keep behavior identical.",
51
+ "Port @{TEST} to Vitest + @vue/test-utils, saved to src/components_vue/{COMPONENT_NAME}/{COMPONENT_NAME}.test.ts. Run the tests and fix anything that breaks."
52
+ ]
53
+ }
54
+ ```
55
+
56
+ Lumpcode commits each context as `LUMP: reactToVue - <ComponentName>` on `lump/reactToVue/<ComponentName>` and pushes. Already-migrated components are skipped automatically on subsequent runs.
57
+
58
+ ## 2. Feature ticket queue — strict dependency order
59
+
60
+ *When to use:* ordered backlog where later work must wait until earlier tickets are merged to the base branch.
61
+
62
+ Treat a JSON ticket file as the source of truth and let `dependsOnContexts` enforce order. Subsequent tickets only become eligible once their dependency’s commit is on `origin/<projectBaseBranch>` (i.e. merged).
63
+
64
+ `.lumpcode/lumps/userProfile/config.json`:
65
+
66
+ ```json
67
+ {
68
+ "command": "claude",
69
+ "getContextListFn": "./tickets.js",
70
+ "numberOfContextsPerBranch": 1,
71
+ "prompt": {
72
+ "promptTemplate": "Implement ticket {TICKET_ID}: {TITLE}\n\nAcceptance criteria:\n{ACCEPTANCE}\n\nLikely files:\n{FILE_HINT}"
73
+ }
74
+ }
75
+ ```
76
+
77
+ `.lumpcode/lumps/userProfile/tickets.js`:
78
+
79
+ ```js
80
+ export default function getContextListFn() {
81
+ return [
82
+ {
83
+ name: "01-schema",
84
+ variables: {
85
+ TICKET_ID: "PROF-1",
86
+ TITLE: "Add `user_profile` table + Prisma model",
87
+ ACCEPTANCE: "- migration runs cleanly\n- model has bio, avatarUrl, createdAt",
88
+ FILE_HINT: "prisma/schema.prisma, migrations/",
89
+ },
90
+ options: { priority: 1 },
91
+ },
92
+ {
93
+ name: "02-api",
94
+ variables: {
95
+ TICKET_ID: "PROF-2",
96
+ TITLE: "Expose GET/PATCH /me/profile",
97
+ ACCEPTANCE: "- zod-validated body\n- returns 401 when unauth",
98
+ FILE_HINT: "apps/api/src/routes/profile.ts",
99
+ },
100
+ options: { priority: 2, dependsOnContexts: ["01-schema"] },
101
+ },
102
+ {
103
+ name: "03-ui",
104
+ variables: {
105
+ TICKET_ID: "PROF-3",
106
+ TITLE: "Profile edit page in the web app",
107
+ ACCEPTANCE: "- form validates on submit\n- toast on success",
108
+ FILE_HINT: "apps/web/src/pages/profile.tsx",
109
+ },
110
+ options: { priority: 3, dependsOnContexts: ["02-api"] },
111
+ },
112
+ ];
113
+ }
114
+ ```
115
+
116
+ Pair this with `lumpcode start`: each tick the daemon picks up the next eligible ticket (skipping those whose dependency is still `toDo` or `branchPushed`), opens a PR, and stops until you merge.
117
+
118
+ ## 3. Test coverage sweep — add a test next to every untested module
119
+
120
+ *When to use:* repo-wide test gaps where simple path patterns are not enough—encode skip logic in code.
121
+
122
+ Use `contextMatchFn` so the matcher itself decides what to skip. Each call receives `codeBasePath` (the current entry) and `codeBasePaths` (the full scanned list) when you need repo-wide context.
123
+
124
+ `.lumpcode/lumps/addTests/config.json`:
125
+
126
+ ```json
127
+ {
128
+ "command": "claude",
129
+ "contextMatchFn": "./match.js",
130
+ "maximumNumberOfConcurrentBranches": 5,
131
+ "prompt": {
132
+ "promptTemplate": "Write a thorough Vitest suite for the module at @{SOURCE}. Save it next to it as a `.test.ts` file. Aim for branch coverage on exported functions."
133
+ }
134
+ }
135
+ ```
136
+
137
+ `.lumpcode/lumps/addTests/match.js`:
138
+
139
+ ```js
140
+ import fs from 'node:fs';
141
+ export default function match({ codeBasePath }) {
142
+ const { isDir, path } = codeBasePath;
143
+ if (isDir) return null;
144
+ if (!path.endsWith('.ts') || path.endsWith('.test.ts') || path.endsWith('.d.ts')) return null;
145
+ if (!path.startsWith('src/')) return null;
146
+ const testPath = path.replace(/\.ts$/, '.test.ts');
147
+ if (fs.existsSync(testPath)) return null;
148
+ return {
149
+ contextName: path.replaceAll('/', '_').replace(/\.ts$/, ''),
150
+ filePathVariableName: 'SOURCE',
151
+ };
152
+ }
153
+ ```
154
+
155
+ `maximumNumberOfConcurrentBranches: 5` keeps no more than five test PRs in flight; the daemon waits for review before queuing more.
156
+
157
+ ## 4. Codemod-style API sweep — replace a deprecated import everywhere it appears
158
+
159
+ *When to use:* many small mechanical edits across files; optionally batch several files per branch.
160
+
161
+ Each file that imports `lodash` becomes one context. Lumpcode handles the branch-per-file housekeeping.
162
+
163
+ `.lumpcode/lumps/lodashToEs/config.json`:
164
+
165
+ ```json
166
+ {
167
+ "command": "claude",
168
+ "contextMatchFn": "./match.js",
169
+ "numberOfContextsPerBranch": 10,
170
+ "prompt": {
171
+ "promptTemplate": "Rewrite @{FILE} to remove `lodash`. Replace usages with native ES equivalents (Array methods, Object.fromEntries, structuredClone, etc.). Keep behavior identical and update the imports."
172
+ }
173
+ }
174
+ ```
175
+
176
+ `.lumpcode/lumps/lodashToEs/match.js`:
177
+
178
+ ```js
179
+ import fs from 'node:fs';
180
+ export default function match({ codeBasePath }) {
181
+ const { isDir, path } = codeBasePath;
182
+ if (isDir || !/\.(ts|tsx|js|jsx)$/.test(path)) return null;
183
+ const src = fs.readFileSync(path, 'utf8');
184
+ if (!/from ['"]lodash/.test(src)) return null;
185
+ return { contextName: path.replaceAll('/', '_'), filePathVariableName: 'FILE' };
186
+ }
187
+ ```
188
+
189
+ `numberOfContextsPerBranch: 10` groups ten files per PR so reviewers don’t drown in tiny diffs.
190
+
191
+ ## 5. Documentation generation — one README per package
192
+
193
+ *When to use:* monorepos where each package should get consistent README content from `package.json` and entrypoints.
194
+
195
+ Run over `packages/*/` and produce or refresh each package README from real source.
196
+
197
+ ```json
198
+ {
199
+ "command": "claude",
200
+ "contextListJson": {
201
+ "PKG_FOLDER": "packages/{PKG}/",
202
+ "PKG_JSON": "packages/{PKG}/package.json",
203
+ "PKG_ENTRY": "packages/{PKG}/src/index.ts"
204
+ },
205
+ "steps": [
206
+ "Read @{PKG_JSON} and @{PKG_ENTRY} (and other relevant files in @{PKG_FOLDER}). Write or rewrite packages/{PKG}/README.md covering: install, quick example, top exports, and links to deeper docs. Keep it under 200 lines."
207
+ ]
208
+ }
209
+ ```
210
+
211
+ ## 6. Conditional follow-up — only do step B if step A says so
212
+
213
+ *When to use:* optional second agent pass based on the first answer (saves cost when no follow-up is needed).
214
+
215
+ Mix a static prompt with a function-form prompt item to short-circuit work when nothing is needed. Requires a JS config so the function can be inline.
216
+
217
+ `.lumpcode/lumps/maybeBumpDeps/config.js`:
218
+
219
+ ```js
220
+ export default {
221
+ command: 'claude',
222
+ contextListJson: { PKG_JSON: 'packages/{PKG}/package.json' },
223
+ steps: [
224
+ {
225
+ promptTemplate:
226
+ "Inspect @{PKG_JSON}. If any direct dependency is more than two majors behind latest, reply exactly NEEDS_BUMP. Otherwise reply OK.",
227
+ postCommandExecFn: ({ commandResult, contextRunState }) => {
228
+ contextRunState.needsBump = commandResult.includes('NEEDS_BUMP');
229
+ },
230
+ },
231
+ ({ contextRunState }) =>
232
+ contextRunState.needsBump
233
+ ? [
234
+ {
235
+ promptTemplate:
236
+ "Bump outdated direct dependencies in @{PKG_JSON} to their latest minor (no majors). Run the package's tests and fix obvious breakage.",
237
+ },
238
+ ]
239
+ : [],
240
+ ],
241
+ };
242
+ ```
243
+
244
+ The second item is a **function** that returns either a one-step array or an empty one—Lumpcode skips the upgrade prompt entirely when the analysis says it isn’t needed, so you don’t pay for an agent run per package that’s already current.
@@ -0,0 +1,222 @@
1
+ # Getting started with the Lumpcode CLI
2
+
3
+ Follow this guide in order to get started with your first `lumpcode run`. Links at each step point to more detail if you want it.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ Install and prepare the following:
10
+
11
+ 1. **Lumpcode account** — Create one at [lumpcode.com](https://lumpcode.com); you’ll use it to log in.
12
+ 2. **Lumpcode CLI** on your `PATH` — Installers vary by OS (Homebrew `brew install lumpcode`, curl one-liners, Windows downloads, or `npm install -g @lumpcode/cli` on Node 22+). The npm install uses a native binary when available for your platform and otherwise runs with Node automatically. For installation details: [README.md § Install](../README.md#install).
13
+ 3. **Git** repository with **`origin`** reachable for fetch/push. The **`projectBaseBranch`** you'll declare in `.lumpcode/local.json` (typically `main`) must **already exist on `origin`** (e.g. `origin/main`): Lumpcode pulls it during pre-flight and reads it via `origin/<projectBaseBranch>` for status.
14
+ 4. **CLI coding agent** installed and runnable. Lumpcode invokes the **`command`** you set in lump config by resolving a command module in this order: `.lumpcode/commands/<name>.js` (project), then `~/.lumpcode/commands/<name>.js` (global override), then shipped presets at `~/.lumpcode/commands/presets/<name>.js`. Built-in preset names **`cursor`** and **`copilot`** work out of the box when `cursor-agent` or `copilot` is on `PATH`; other agents (e.g. **`claude`**, **`aider`**) need a custom module until more presets ship.
15
+
16
+ ---
17
+
18
+ ## Terms you need for this tutorial
19
+
20
+ | Term | Meaning |
21
+ |------|---------|
22
+ | **Project** | A folder with git that contains both `.git/` and `.lumpcode/` (the CLI adds `.lumpcode/` once you initialize). |
23
+ | **Lump** | One automated coding campaign living under `.lumpcode/lumps/<lumpName>/` (context discovery + prompt + agent command). |
24
+ | **Context** | One unit of work inside a lump (e.g. one file or one component). Each context has a **name** and **variables** filled into your prompt. |
25
+ | **Marker commit** | The commit subject for one context is always **`LUMP: <lumpName> - <contextName>`** on the remote. Lumpcode uses that to know what is already done. |
26
+ | **Resumable** | Re-running `lumpcode run` or a daemon tick skips contexts that already have a matching marker on the remote. |
27
+
28
+ More details, diagrams and context status values (`toDo`, `branchPushed`, `finished`): [concepts.md](./concepts.md).
29
+
30
+ ---
31
+
32
+ ## Step 0: Open a git project
33
+
34
+ ```bash
35
+ cd /path/to/your/repo
36
+ git status # remotes should be set up and accessible
37
+ ```
38
+
39
+ You only need **`.git/`** here. The next steps create **`.lumpcode/`** in this same directory. After that, this folder is your **Lumpcode project root**.
40
+
41
+ ---
42
+
43
+ ## Step 1: Log in
44
+
45
+ ```bash
46
+ lumpcode login
47
+ ```
48
+
49
+ Use your Lumpcode email and password when prompted. The CLI saves the session to `~/.lumpcode/auth.json` and skips prompting if you are already logged in. For non-interactive use and flags, see [commands.md § `lumpcode login`](./commands.md#ref-cmd-login).
50
+
51
+ ---
52
+
53
+ ## Step 2: Initialize the Lumpcode project
54
+
55
+ From the repository root:
56
+
57
+ ```bash
58
+ lumpcode project-setup
59
+ ```
60
+
61
+ This creates:
62
+
63
+ ```text
64
+ .lumpcode/
65
+ ├── project.json # project name and optional project-wide settings (commit this)
66
+ ├── local.json # per-machine mode + projectBaseBranch (gitignored)
67
+ ├── lumps/ # one folder per lump
68
+ └── commands/ # optional custom agent command modules (.js)
69
+ ```
70
+
71
+ **`project.json`** stores **`projectName`**: letters, digits, `_`, and `-` only. If you omit **`--projectName`**, `project-setup` infers a name from **`origin`** or the directory basename and normalizes it to those rules. That same value is used for daemon files and for `~/.lumpcode/project-copies/<projectName>/` when `local.json.mode` is `shared`—Lumpcode does not rename or “slug” it at runtime.
72
+
73
+ **`local.json`** is per machine and gitignored. The default is:
74
+
75
+ ```json
76
+ {
77
+ "mode": "shared",
78
+ "projectBaseBranch": "main"
79
+ }
80
+ ```
81
+
82
+ Keep `shared` on your workstation (Lumpcode never touches your checkout — it runs in a separate copy). Edit it to `"dedicated"` on a server / daemon machine that you don't develop on. Full reference: [local-config.md](./local-config.md).
83
+
84
+ Optional flags:
85
+
86
+ - `--projectPath <dir>` — Initialize another directory (default: current working directory).
87
+ - `--projectName <name>` — Stored verbatim; must already satisfy the character rules (see [project-config.md](./project-config.md#projectname-rules)).
88
+ - `--mode <shared|dedicated>` — Initial `local.json.mode` (default `shared`).
89
+ - `--projectBaseBranch <branch>` — Initial `local.json.projectBaseBranch` (default `main`).
90
+
91
+ Extra fields (`maximumNumberOfConcurrentBranches`, …): [project-config.md](./project-config.md).
92
+
93
+ ---
94
+
95
+ ## Step 3: Create a lump
96
+
97
+ ```bash
98
+ lumpcode lump-create myFirstLump
99
+ ```
100
+
101
+ By default this writes **`.lumpcode/lumps/myFirstLump/config.json`** with a small starter config. For **`config.js`** instead:
102
+
103
+ ```bash
104
+ lumpcode lump-create myFirstLump --config js
105
+ ```
106
+
107
+ `lump-create` gives you one path template plus `@{FILE}` in the prompt; Step 4 is where you reshape that for your campaign.
108
+
109
+ ---
110
+
111
+ ## Step 4: Define contexts
112
+
113
+ `contextListJson` maps variable names to path **templates** (e.g. `{NAME}`, `{COMPONENT_NAME}`). Lumpcode scans the repo and keeps only combinations where **every** template resolves to a real path; each map **key** is a **`{VAR}`** in `promptTemplate`, or **`@{VAR}`** with a leading `@` for agents that treat `@path` as file context. Substitution rules: [lump-config.md § Prompt template syntax](./lump-config.md#prompt-template-syntax).
114
+
115
+ **Why two examples:** Lumpcode excels at **the same shaped change** across many files—first a **minimal** stub (one `{NAME}` pattern under `src/`, one generic improvement prompt); then a **repeat-per-component** pattern: hypothetical **React** `.tsx` files laid out **one folder per component**, where every discovered context runs the **same migration ask** (**Vue 3 `<script setup>`**). The stacks are illustrative only so you see multi-path contexts and **`$upperFirst{…}`**; replace paths, prompts, and `command` with your real migration or refactor.
116
+
117
+ Minimal stub (`lump-create` defaults look like this—adjust `FILE`/prompt):
118
+
119
+ ```json
120
+ {
121
+ "$schema": "https://lumpcode.com/schemas/lumpConfig.schema.json",
122
+ "contextListJson": {
123
+ "FILE": "src/{NAME}.ts"
124
+ },
125
+ "prompt": {
126
+ "promptTemplate": "Improve the code at @{FILE}.",
127
+ "command": "claude"
128
+ }
129
+ }
130
+ ```
131
+
132
+ Repeat-per-component variant (multiple paths must exist per context—the prompt is identical in spirit every time Lumpcode discovers the next matched folder/file set):
133
+
134
+ ```json
135
+ {
136
+ "contextListJson": {
137
+ "FOLDER": "src/components/{COMPONENT_NAME}/",
138
+ "COMPONENT": "src/components/{COMPONENT_NAME}/$upperFirst{COMPONENT_NAME}.tsx"
139
+ },
140
+ "prompt": {
141
+ "promptTemplate": "Migrate the component at @{COMPONENT} (folder @{FOLDER}) to Vue 3 <script setup>.",
142
+ "command": "claude"
143
+ }
144
+ }
145
+ ```
146
+
147
+ The base branch comes from `.lumpcode/local.json.projectBaseBranch`. Add a per-lump `"baseBranch": "release/2.0"` only if this campaign needs to branch off something else.
148
+
149
+ Transforms (e.g. `$upperFirst{…}`) and **`contextOptionsFn`** for `priority` / `dependsOnContexts`: [lump-config.md § contextListJson](./lump-config.md#contextlistjson). Fully custom sourcing: **`getContextListFn`** / **`contextMatchFn`** ([lump-config.md](./lump-config.md), [advanced-config.md](./advanced-config.md)).
150
+
151
+ ---
152
+
153
+ ## Step 5: Run once
154
+
155
+ ```bash
156
+ lumpcode run myFirstLump
157
+ ```
158
+
159
+ In one tick, Lumpcode first runs **pre-flight** (pulls `projectBaseBranch` from `local.json` in the resolved workspace), then picks the next context(s); prepares the work branch `lump/myFirstLump/…`; runs your agent; commits with the **`LUMP: myFirstLump - <contextName>`** marker (see Terms above); pushes to **`origin`**; refreshes **`contextStatusRecord.json`**; and finally switches the workspace back to `projectBaseBranch`.
160
+
161
+ **Workspace:** `local.json.mode` decides where the run happens — `shared` uses **`~/.lumpcode/project-copies/<projectName>/`** (a copy of your repo); `dedicated` uses **this checkout** in place (destructive reset). [concepts.md § Pre-flight and modes](./concepts.md#pre-flight-and-modes) · [local-config.md](./local-config.md)
162
+
163
+ **Sanity checks:**
164
+
165
+ ```bash
166
+ git fetch origin
167
+ git log --remotes --grep '^LUMP:' --oneline
168
+ lumpcode lump-status --lumpName myFirstLump
169
+ ```
170
+
171
+ Do **not** confuse **`lump-status`** (context rows from git) with **`daemon-status`** (scheduler process)—[commands.md](./commands.md#three-commands-that-mention-status).
172
+
173
+ ---
174
+
175
+ ## Step 6: Run continuously (optional)
176
+
177
+ From the same repository root:
178
+
179
+ ```bash
180
+ lumpcode start
181
+ ```
182
+
183
+ By default **`start`** launches a **detached** background process on a cron schedule (**every 5 minutes**), loops **every lump** under `.lumpcode/lumps/` that has a loadable **`config.json`** or **`config.js`**, and **skips** lumps marked **`"disabled": true`** in their config.
184
+
185
+ | If you… | Prefer |
186
+ |---------|--------|
187
+ | Want **one lump**, **one batch**, then return to the shell | **`lumpcode run myFirstLump`** |
188
+ | Leave a machine running and tick **all lumps** on a timer | **`lumpcode start`** |
189
+
190
+ **Common flags:** `lumpcode start --foreground` (block in this terminal instead of detaching). `lumpcode start --cronSetup '*/10 * * * *'` changes the schedule. **`lumpcode daemon-status`** shows PID and log paths; **`lumpcode daemon-log`** tails the log (follows live by default; **`--noFollow`** to print and exit); **`lumpcode stop`** / **`lumpcode restart`** control the daemon. Metadata files live under **`~/.lumpcode/daemons/`** (PID, log, `cronSetup` in meta JSON).
191
+
192
+ Trade-offs and **`maximumNumberOfConcurrentBranches`**: [concepts.md § When to use run vs start](./concepts.md#when-to-use-run-vs-start-daemon).
193
+
194
+ ---
195
+
196
+ ## Where your work lives
197
+
198
+ | Artifact | Location |
199
+ |----------|----------|
200
+ | Lump configs | `.lumpcode/lumps/<lumpName>/` |
201
+ | Per-machine mode + projectBaseBranch | `.lumpcode/local.json` (gitignored) |
202
+ | Context status cache | `.lumpcode/lumps/<lumpName>/contextStatusRecord.json` |
203
+ | Prompt run history (optional, `keepHistory: true`) | `.lumpcode/lumps/<lumpName>/history/<contextName>.json` (gitignored) |
204
+ | Default work branch names | `lump/<lumpName>/<context…>` (local + `origin`) |
205
+ | Isolated repo copy (when `local.json.mode` is `shared`) | `~/.lumpcode/project-copies/<projectName>/` |
206
+ | Background daemon PID / logs | `~/.lumpcode/daemons/` |
207
+
208
+ Commit `.lumpcode/` if you want lump definitions and status tracked in git; omit secrets and machine-only paths from shared configs.
209
+
210
+ ---
211
+
212
+ ## Next steps
213
+
214
+ You have now your first working lump ! Browse when you need more depth:
215
+
216
+ - [concepts.md](./concepts.md) — Lifecycle diagrams and workspace details
217
+ - [commands.md](./commands.md) — Every subcommand and flag
218
+ - [local-config.md](./local-config.md) — `.lumpcode/local.json` (`mode`, `projectBaseBranch`)
219
+ - [lump-config.md](./lump-config.md) — All lump config keys
220
+ - [advanced-config.md](./advanced-config.md) — Hooks, dynamic `steps`, custom commands
221
+ - [types.md](./types.md) — Hook parameter shapes
222
+ - [examples.md](./examples.md) — Short smoke-test style recipes
@@ -0,0 +1,80 @@
1
+ # Local configuration (`.lumpcode/local.json`)
2
+
3
+ `.lumpcode/local.json` is a **per-machine**, **gitignored** file that tells Lumpcode where and how to run lumps from the current checkout. **Every command that runs a lump (`run`, `start`) requires it**—Lumpcode hard-fails if it is missing or invalid.
4
+
5
+ `lumpcode project-setup` scaffolds the file with safe defaults and appends it to `.gitignore` so it never makes it into commits or shared branches.
6
+
7
+ ## Minimal example
8
+
9
+ ```json
10
+ {
11
+ "mode": "shared",
12
+ "projectBaseBranch": "main",
13
+ "workspaceStrategy": "checkout"
14
+ }
15
+ ```
16
+
17
+ ## Fields
18
+
19
+ | Field | Type | Description |
20
+ |-------|------|-------------|
21
+ | `mode` | `"shared"` \| `"dedicated"` | How Lumpcode treats the current checkout. See [Modes](#modes) below. |
22
+ | `projectBaseBranch` | string | Branch Lumpcode pulls (and resets to) before any lump runs. Also the default `baseBranch` for lumps that don't set their own. Status checks (`finished`) compare against `origin/<projectBaseBranch>`. |
23
+ | `workspaceStrategy` | `"checkout"` \| `"worktree"` | How each lump run prepares git inside the [execution workspace](concepts.md#three-workspaces). Default: `"checkout"`. See [Workspace strategies](#workspace-strategies). |
24
+ | `disabled` | boolean | When `true`, the background daemon (`lumpcode start`) skips every lump on this machine without stopping the scheduler. Manual `lumpcode run` is unaffected. |
25
+
26
+ `mode` and `projectBaseBranch` are **required**. `workspaceStrategy` and `disabled` are optional (`workspaceStrategy` defaults to `"checkout"` when omitted). Unknown fields are rejected.
27
+
28
+ ## Modes
29
+
30
+ ### `shared` (default)
31
+
32
+ You use this clone for your **day-to-day work**. Lumpcode never touches it; every run happens in a **separate copy** at `~/.lumpcode/project-copies/<projectName>/`. The copy is created once and kept up to date by pre-flight on subsequent runs.
33
+
34
+ ```text
35
+ ~/your-repo/ ← your editor / git client; untouched by Lumpcode
36
+ ~/.lumpcode/
37
+ └── project-copies/<projectName>/ ← Lumpcode runs here
38
+ ```
39
+
40
+ Pick `shared` on **workstations**.
41
+
42
+ ### `dedicated`
43
+
44
+ The clone is **owned by Lumpcode** (typical for a daemon machine on a small server). Lumpcode runs in place: pre-flight does `git fetch && git switch <projectBaseBranch> && git reset --hard origin/<projectBaseBranch>` in the checkout itself. **This wipes any uncommitted local changes.** Do not pick `dedicated` for a clone you also edit.
45
+
46
+ Pick `dedicated` on **machines you don't develop on**, including `lumpcode start` daemons.
47
+
48
+ ## Workspace strategies
49
+
50
+ ### `checkout` (default)
51
+
52
+ Each lump run switches the main worktree to a fresh `lump/<lumpName>/…` branch (fetch, reset, pull `baseBranch`, then `git switch -c`). When the lump finishes, the workspace switches back to `projectBaseBranch`.
53
+
54
+ ### `worktree`
55
+
56
+ Each lump run uses a **linked git worktree** under `.lumpcode/worktrees/<branch>/` inside the execution workspace (the project copy in `shared` mode, the checkout in `dedicated`). The main worktree stays on `projectBaseBranch` while the agent runs inside the worktree (the **branch workspace**). Worktree paths mirror branch segments (e.g. branch `lump/migrate-vue/Button.tsx` → `.lumpcode/worktrees/lump/migrate-vue/Button.tsx`). `project-setup` gitignores `.lumpcode/worktrees/`. `lumpcode clean` removes worktrees when it deletes lump branches.
57
+
58
+ Pick `worktree` when you want the base branch checked out in the main tree during runs, or when planning parallel lump execution later.
59
+
60
+ ## Pre-flight
61
+
62
+ Before every `run` and every daemon tick, Lumpcode runs a **pre-flight** that:
63
+
64
+ 1. Resolves the execution workspace from `mode` (project copy in `shared`, the checkout itself in `dedicated`).
65
+ 2. In that workspace: `git fetch --all && git switch <projectBaseBranch> && git reset --hard origin/<projectBaseBranch> && git pull origin <projectBaseBranch>`.
66
+
67
+ If pre-flight fails, `run` reports a `commandFailure` and the daemon **skips the tick** (logged to the daemon log) and tries again on the next schedule.
68
+
69
+ After pre-flight, each lump runs its own per-lump git flow on the execution workspace (see [Workspace strategies](#workspace-strategies)): fetch/pull of the lump's `baseBranch` (defaults to `projectBaseBranch`), then either a checkout branch or a worktree branch workspace. After the lump finishes, checkout mode switches back to `projectBaseBranch`; worktree mode removes the linked worktree while leaving the main tree on `projectBaseBranch`.
70
+
71
+ ## Commit vs. gitignore
72
+
73
+ `.lumpcode/local.json` is **gitignored**. `project-setup` writes the entry to `.gitignore` for you. Each machine gets its own `local.json`; you should never share it through git.
74
+
75
+ ## Related topics
76
+
77
+ - [project-config.md](./project-config.md) — `project.json`, project name rules
78
+ - [lump-config.md](./lump-config.md) — Per-lump `config.json` / `config.js`, optional `baseBranch` override
79
+ - [commands.md](./commands.md) — `run` / `start` and other subcommands
80
+ - [concepts.md](./concepts.md) — Pre-flight, lifecycle, daemon overview