@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.
- package/DOCS/advanced-config.md +261 -0
- package/DOCS/commands.md +492 -0
- package/DOCS/concepts.md +148 -0
- package/DOCS/examples.md +244 -0
- package/DOCS/get-started.md +222 -0
- package/DOCS/local-config.md +80 -0
- package/DOCS/lump-config.md +276 -0
- package/DOCS/project-config.md +56 -0
- package/DOCS/publishing.md +79 -0
- package/DOCS/types.md +267 -0
- package/LICENSE +202 -0
- package/README.md +192 -0
- package/bin/lumpcode.js +42 -0
- package/dist/index.js +7 -0
- package/dist/presets/commands/copilot.js +25 -0
- package/dist/presets/commands/cursor.js +70 -0
- package/dist/schemas/localConfig.schema.json +29 -0
- package/dist/schemas/lumpConfig.schema.json +195 -0
- package/package.json +61 -0
- package/scripts/native-binary.mjs +180 -0
- package/scripts/postinstall.mjs +52 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Advanced Lumpcode CLI configuration
|
|
2
|
+
|
|
3
|
+
This page is the deep-dive companion to [lump-config.md](./lump-config.md): where that page lists every config field at table depth, this one covers the parts that need more — **hook lifecycle**, **dynamic prompt lists**, **workspace overrides**, and **custom agent command modules**. Operations (daemon, cron, isolated repo copies, workspace presets) live in [concepts.md](./concepts.md); type shapes live in [types.md](./types.md).
|
|
4
|
+
|
|
5
|
+
Every `*Fn` field below is a [function reference](./lump-config.md#field-forms-conventions) — either:
|
|
6
|
+
|
|
7
|
+
- an **inline function** — only in `config.js`, or
|
|
8
|
+
- a **string path** to a `.js` module whose **default export** is the function — works in both `config.json` and `config.js`.
|
|
9
|
+
|
|
10
|
+
Relative paths resolve from the lump folder.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Hook lifecycle
|
|
15
|
+
|
|
16
|
+
For one tick of `lumpcode run <lumpName>`:
|
|
17
|
+
|
|
18
|
+
```pseudocode
|
|
19
|
+
pre-flight ─ pull projectBaseBranch into the resolved workspace
|
|
20
|
+
(mode = shared → copy under ~/.lumpcode/project-copies/<projectName>/)
|
|
21
|
+
(mode = dedicated → the checkout itself, with destructive reset)
|
|
22
|
+
discover contexts ─ contextListJson | getContextListFn | contextMatchFn
|
|
23
|
+
└─ contextOptionsFn (only with contextListJson)
|
|
24
|
+
batch contexts → branchFn (one branch name for the batch)
|
|
25
|
+
auto-setupWorkspace (fetch + reset + pull baseBranch, fresh lump branch)
|
|
26
|
+
for each context in batch:
|
|
27
|
+
setupFn (seeds contextRunState)
|
|
28
|
+
for each prompt item:
|
|
29
|
+
if item is a function: (dynamic steps — see below)
|
|
30
|
+
sub-items = item({ context, contextRunState, … })
|
|
31
|
+
recurse on sub-items
|
|
32
|
+
else: (classic case)
|
|
33
|
+
promptFn (or promptTemplate substitution)
|
|
34
|
+
command → CommandFn → executable + args
|
|
35
|
+
postCommandExecFn
|
|
36
|
+
teardownFn (receives accumulated contextRunState)
|
|
37
|
+
git add + git commit (LUMP: <lumpName> - <ctx>)
|
|
38
|
+
git push (once per batch)
|
|
39
|
+
auto-teardownWorkspace (git switch projectBaseBranch — always)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The pre-flight, per-lump fetch/branch, and per-lump teardown are all generated by the CLI — they are not configurable in lump config. The baseline lifecycle ties to **`projectBaseBranch`** from [local-config.md](./local-config.md); lump-level `baseBranch` only overrides the per-lump fetch, not the teardown switch-back.
|
|
43
|
+
|
|
44
|
+
`setupFn` / `teardownFn` from the lump config are **composed** with every loaded command module's `setup` / `teardown` — see [Custom agent commands](#custom-agent-commands).
|
|
45
|
+
|
|
46
|
+
### `contextRunState`
|
|
47
|
+
|
|
48
|
+
A mutable bag scoped to **one context execution**. Not shared across contexts, batches, or runs. The same object reference is passed into every hook below — any of them can read **or** mutate it. The "typical use" column is convention, not enforcement.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
| Stage | Typical use |
|
|
52
|
+
| ------------------------------ | ---------------------------------------------------------------------------------- |
|
|
53
|
+
| `setupFn` | Seed the bag — its returned `{ contextRunState: { … } }` becomes the initial value |
|
|
54
|
+
| `promptFn` | Read (e.g. interpolate previous results into prompt text) |
|
|
55
|
+
| `commandFn` | Read (e.g. switch `executable` / `args` based on a flag) |
|
|
56
|
+
| `postCommandExecFn` | Mutate (parse stdout, set flags for later steps) |
|
|
57
|
+
| Dynamic `steps` function | Read (gate the next prompt) |
|
|
58
|
+
| `teardownFn` | Read the accumulated `contextRunState` |
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
Type: [types.md](./types.md#contextrunstate).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Hook reference
|
|
66
|
+
|
|
67
|
+
Detailed shapes live in [types.md](./types.md); runnable code lives in [examples.md](./examples.md). This table summarises **purpose, gotchas, and where to look**.
|
|
68
|
+
|
|
69
|
+
### Discovery
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
| Hook | Purpose | Gotcha | Example |
|
|
73
|
+
|------|---------|--------|---------|
|
|
74
|
+
| [`getContextListFn`](./types.md#getcontextlistfn) | Return a fully custom `Context[]` (e.g. ticket queue, external API) | `variables` map values **must be strings** — they feed prompt substitution and git paths | [Example 2](./examples.md#2-feature-ticket-queue--strict-dependency-order) |
|
|
75
|
+
| [`contextMatchFn`](./types.md#contextmatchfn) | Per-file matcher: Lumpcode walks every `CodeBasePath` and calls you once per file/dir with `codeBasePath`, the full `codeBasePaths` list, and `lumpVariables` | Multiple files returning the same `contextName` **merge** into one context (variables and options merge; later files override); use `codeBasePaths` for cross-file skip or merge logic | [Examples 3 & 4](./examples.md#3-test-coverage-sweep--add-a-test-next-to-every-untested-module) |
|
|
76
|
+
| [`contextOptionsFn`](./types.md#contextoptionsfn) | Attach `priority` / `dependsOnContexts` to `contextListJson`-derived contexts | **Only** runs with `contextListJson`; ignored for `getContextListFn` / `contextMatchFn` (those attach `options` on their returned data) | — |
|
|
77
|
+
|
|
78
|
+
### Per-context lifecycle
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
| Hook | Purpose | Gotcha |
|
|
82
|
+
|------|---------|--------|
|
|
83
|
+
| [`branchFn`](./types.md#branchfn) | Override the default `lump/<lumpName>/<contextNames…>` branch name | Returns **one** branch name for the whole batch (all contexts in `numberOfContextsPerBranch`) |
|
|
84
|
+
| [`setupFn`](./types.md#setupfn) | Seed `contextRunState` before the prompt loop for one context | Runs once per context index, **not** once per prompt item |
|
|
85
|
+
| [`teardownFn`](./types.md#teardownfn) | Cleanup, metrics, post-processing after all prompt items for one context | Receives the accumulated `contextRunState` |
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
### Per-step
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
| Hook | Purpose | Gotcha |
|
|
92
|
+
|------|---------|--------|
|
|
93
|
+
| [`promptFn`](./types.md#promptfn) | Build prompt text with custom logic (inject `contextRunState`, branch on `stepIndex`, …) | Mutually exclusive with `promptTemplate` on the same item; per-item, not per-context |
|
|
94
|
+
| [`postCommandExecFn`](./types.md#postcommandexecfn) | Parse the agent's stdout and stash flags on `contextRunState` (gate the next prompt, enforce JSON contracts) | `commandResult` is **raw stdout** (string) |
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## `promptFn`
|
|
100
|
+
|
|
101
|
+
Use `promptFn` when `promptTemplate` is not enough — it gives you fine-grained control over how each prompt is built (inject `contextRunState` from a previous step, switch on `stepIndex`, run any custom logic). Inline in `config.js`, or as a [function reference](./lump-config.md#field-forms-conventions) string path from either format.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
export default {
|
|
105
|
+
baseBranch: 'main',
|
|
106
|
+
contextListJson: { FILE: 'src/{NAME}.ts' },
|
|
107
|
+
command: 'claude',
|
|
108
|
+
steps: [
|
|
109
|
+
{
|
|
110
|
+
promptFn: ({ context, contextRunState }) => {
|
|
111
|
+
const focus = contextRunState.perfIssues ? 'performance' : 'general code quality';
|
|
112
|
+
return `Review @${context.variables.FILE}, focusing on ${focus}.`;
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`promptFn` and `promptTemplate` are **mutually exclusive** on the same prompt item.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Dynamic `steps`
|
|
124
|
+
|
|
125
|
+
In `config.js`, an element of `steps` may be a **function** that receives the same inputs as a `promptFn` and returns **another** `steps` array (possibly empty) to expand inline.
|
|
126
|
+
|
|
127
|
+
This enables branching workflows:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
export default {
|
|
131
|
+
baseBranch: 'main',
|
|
132
|
+
contextListJson: { FILE: 'src/{NAME}.ts' },
|
|
133
|
+
command: 'claude',
|
|
134
|
+
steps: [
|
|
135
|
+
{
|
|
136
|
+
promptTemplate: 'Does @{FILE} need a README section? Reply YES or NO only.',
|
|
137
|
+
postCommandExecFn: ({ commandResult, contextRunState }) => {
|
|
138
|
+
contextRunState.needsDocs = commandResult.trim().toUpperCase().includes('YES');
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
({ contextRunState }) =>
|
|
142
|
+
contextRunState.needsDocs
|
|
143
|
+
? [{ promptTemplate: 'Add minimal module docs for @{FILE}.' }]
|
|
144
|
+
: [],
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Full runnable variant: [Example 6](./examples.md#6-conditional-follow-up--only-do-step-b-if-step-a-says-so).
|
|
150
|
+
|
|
151
|
+
### `stepIndex` paths
|
|
152
|
+
|
|
153
|
+
For static items, `stepIndex` is a number (`0`, `1`, …). Inside arrays returned by a function item, nested items receive `stepIndex` as `number[]` — e.g. `[1, 0]` for the first nested prompt under function item `1`. Deeper nesting grows the array.
|
|
154
|
+
|
|
155
|
+
### `registerCommands`
|
|
156
|
+
|
|
157
|
+
If the **only** reference to a custom `command` name appears inside a dynamic function return, register it up front:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
"registerCommands": ["my-agent"]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Otherwise lazy loading may throw when the nested array resolves.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Custom agent commands
|
|
168
|
+
|
|
169
|
+
Place modules at:
|
|
170
|
+
|
|
171
|
+
1. `.lumpcode/commands/<name>.js` — **project-local**
|
|
172
|
+
2. `~/.lumpcode/commands/<name>.js` — **global user override**
|
|
173
|
+
3. `~/.lumpcode/commands/presets/<name>.js` — **shipped preset** (installed automatically on first run)
|
|
174
|
+
|
|
175
|
+
Reference them from `command` fields by **string name** (`"my-agent"`, `"cursor"`, `"copilot"`), same as built-in names. **First existing file wins** in the order above.
|
|
176
|
+
|
|
177
|
+
### Shipped presets
|
|
178
|
+
|
|
179
|
+
Lumpcode ships ready-made modules for common CLI agents. Set `"command": "cursor"` or `"command": "copilot"` in lump config — no custom module required. You still need the agent binary on `PATH` (`cursor-agent`, `copilot`).
|
|
180
|
+
|
|
181
|
+
| Preset name | Agent binary | Default model (`stepVariables.model`) |
|
|
182
|
+
| ----------- | ------------ | --------------------------------------------- |
|
|
183
|
+
| `cursor` | `cursor-agent` | `composer-2.5` |
|
|
184
|
+
| `copilot` | `copilot` | `auto` |
|
|
185
|
+
|
|
186
|
+
On first `run`, `start`, or `lump-plan`, missing preset files are copied into `~/.lumpcode/commands/presets/` without overwriting files already there. To restore shipped defaults after editing presets, use `lumpcode reset-presets` (when available) or replace the files manually.
|
|
187
|
+
|
|
188
|
+
Override a preset by placing `~/.lumpcode/commands/<name>.js` (global) or `.lumpcode/commands/<name>.js` (project-local).
|
|
189
|
+
|
|
190
|
+
Each module exports:
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
| Export | Required | Description |
|
|
194
|
+
| ---------- | -------- | ---------------------------------------------------------------- |
|
|
195
|
+
| `command` | **Yes** | Same contract as `commandFn` in [types.md](./types.md#commandfn) |
|
|
196
|
+
| `setup` | No | Composed with the lump's `setupFn` (see below) |
|
|
197
|
+
| `teardown` | No | Composed with the lump's `teardownFn` (see below) |
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
For editor hints, install [`@lumpcode/cli-types`](https://www.npmjs.com/package/@lumpcode/cli-types) and use `defineCommand`, `defineCommandSetup`, `defineCommandTeardown` (or `defineCommandModule` for the whole file):
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
import { defineCommand, defineCommandSetup } from '@lumpcode/cli-types';
|
|
204
|
+
|
|
205
|
+
export const command = defineCommand(({ prompt, stepVariables }) => ({
|
|
206
|
+
executable: 'my-agent',
|
|
207
|
+
args: ['--message', prompt],
|
|
208
|
+
}));
|
|
209
|
+
|
|
210
|
+
export const setup = defineCommandSetup(async () => ({}));
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### `workspacePath` vs `projectRoot` in `command`
|
|
214
|
+
|
|
215
|
+
Lump configs do **not** define `projectRoot`; the CLI resolves it as the directory that contains `.lumpcode/`. Both fields below are runtime parameters on your `CommandFn`:
|
|
216
|
+
|
|
217
|
+
- **`projectRoot`** — **project workspace**: the source checkout where `.lumpcode/` lives (always your repo in `shared` mode; same as the execution workspace in `dedicated` mode).
|
|
218
|
+
- **`workspacePath`** — **branch workspace**: where the agent process runs for this lump (the engine sets `cwd: workspacePath` for you). With `workspaceStrategy: "checkout"`, this equals the execution workspace (project copy in `shared`, checkout in `dedicated`). With `"worktree"`, it is a linked worktree under `.lumpcode/worktrees/<branch>/` inside the execution workspace. See [concepts.md § Three workspaces](./concepts.md#three-workspaces) and [local-config.md](./local-config.md).
|
|
219
|
+
|
|
220
|
+
The CLI also resolves an **execution workspace** (git repo root after pre-flight)—not passed to `CommandFn`. In `shared` mode that is `~/.lumpcode/project-copies/<projectName>/`; in `dedicated` mode it matches `projectRoot`.
|
|
221
|
+
|
|
222
|
+
### How `setup` / `teardown` compose
|
|
223
|
+
|
|
224
|
+
Lumpcode wraps the lump-level `setupFn` and `teardownFn` to also run every loaded command module's `setup` / `teardown`, in this order:
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
| Stage | Order |
|
|
228
|
+
| -------- | ------------------------------------------------------------------------------------ |
|
|
229
|
+
| Setup | lump `setupFn` first → then each command module's `setup` (registration order) |
|
|
230
|
+
| Teardown | each command module's `teardown` first (registration order) → then lump `teardownFn` |
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
State merge in `contextRunState`:
|
|
234
|
+
|
|
235
|
+
- The lump's `setupFn` returns `{ contextRunState }` — its keys go directly into the bag.
|
|
236
|
+
- Each command module's `setup` return goes under a **namespaced key**: `contextRunState["<commandName>Setup"]`. Namespacing prevents two modules from clobbering each other.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Workspace handling
|
|
241
|
+
|
|
242
|
+
Per-lump git setup is generated by the CLI from the execution workspace (resolved at pre-flight), `local.json` `workspaceStrategy`, and the lump's `baseBranch`. There are **no** `workspaceSetup`, `setupWorkspaceFn`, or `teardownWorkspaceFn` knobs in lump config.
|
|
243
|
+
|
|
244
|
+
| `workspaceStrategy` | Behavior |
|
|
245
|
+
| ------------------- | -------- |
|
|
246
|
+
| `checkout` (default) | Main worktree: fetch/reset/pull `baseBranch`, `git switch -c` lump branch; teardown switches back to `projectBaseBranch`. |
|
|
247
|
+
| `worktree` | Main worktree stays on `projectBaseBranch`; agent runs in `.lumpcode/worktrees/<branch>/`; teardown removes the worktree. |
|
|
248
|
+
|
|
249
|
+
Pick `mode` (`shared` / `dedicated`) and `workspaceStrategy` in [local-config.md](./local-config.md). Worktrees are always created under the execution workspace (project copy in `shared`, checkout in `dedicated`).
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Related documentation
|
|
254
|
+
|
|
255
|
+
- [lump-config.md](./lump-config.md) — Field reference
|
|
256
|
+
- [local-config.md](./local-config.md) — Per-machine `local.json` (`mode`, `projectBaseBranch`, `workspaceStrategy`)
|
|
257
|
+
- [concepts.md](./concepts.md) — Daemon, pre-flight, status lifecycle
|
|
258
|
+
- [types.md](./types.md) — Hook signatures
|
|
259
|
+
- [examples.md](./examples.md) — Runnable lump configs
|
|
260
|
+
- [commands.md](./commands.md) — `run`, `start`, `daemon-status`, `clean`
|
|
261
|
+
|