@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,276 @@
|
|
|
1
|
+
# Lump configuration (`config.json` / `config.js`)
|
|
2
|
+
|
|
3
|
+
Each lump lives under:
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
.lumpcode/lumps/<lumpName>/
|
|
7
|
+
├── config.json # JSON config (recommended for beginners)
|
|
8
|
+
│ or config.js # ESM default export (dynamic logic)
|
|
9
|
+
├── contextStatusRecord.json # auto-maintained status cache
|
|
10
|
+
├── history/ # optional per-context prompt run logs (when keepHistory is true)
|
|
11
|
+
└── … templates, prompt files, hook modules …
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Preview a lump before running: `lumpcode lump-plan <lumpName>` (see [commands.md](./commands.md#ref-cmd-lump-plan)).
|
|
15
|
+
|
|
16
|
+
## Required pieces
|
|
17
|
+
|
|
18
|
+
Every runnable lump has **two required parts**:
|
|
19
|
+
|
|
20
|
+
1. **Exactly one context source** — mutually exclusive in the JSON schema:
|
|
21
|
+
|
|
22
|
+
| Field | Form | Purpose |
|
|
23
|
+
|-------|------|---------|
|
|
24
|
+
| `contextListJson` | [JSON reference](#field-forms-conventions) (`Record<string,string>`) | Declarative templates expanded by scanning the tree |
|
|
25
|
+
| `getContextListFn` | [Function reference](#field-forms-conventions) | Fully custom context list |
|
|
26
|
+
| `contextMatchFn` | [Function reference](#field-forms-conventions) | Per-file scan → grouped contexts |
|
|
27
|
+
|
|
28
|
+
2. **Exactly one prompt definition**:
|
|
29
|
+
|
|
30
|
+
| Field | Purpose |
|
|
31
|
+
|-------|---------|
|
|
32
|
+
| `prompt` | Single prompt step. Object (full item), or string shorthand (treated as inline `promptTemplate` text — **not** a file path; use `promptFn` to load from disk) |
|
|
33
|
+
| `steps` | Ordered list of steps (mix objects, strings, or dynamic functions — see [advanced-config.md](./advanced-config.md#dynamic-steps)) |
|
|
34
|
+
|
|
35
|
+
Minimal shape:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"contextListJson": { "FILE": "src/{NAME}.ts" },
|
|
40
|
+
"prompt": {
|
|
41
|
+
"promptTemplate": "Improve types in @{FILE}",
|
|
42
|
+
"command": "claude"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The base branch comes from **`.lumpcode/local.json.projectBaseBranch`** by default — set `baseBranch` here only when this specific lump should run against a different branch. Workspace setup (in-place vs. on a copy) is also per machine, configured in `.lumpcode/local.json.mode` — see [local-config.md](./local-config.md).
|
|
48
|
+
|
|
49
|
+
Everything else (`command` at top level when using shorthand strings, hooks, etc.) is optional — see [Optional top-level fields](#optional-top-level-fields).
|
|
50
|
+
|
|
51
|
+
## Runtime: which files actually load?
|
|
52
|
+
|
|
53
|
+
- The CLI loads **`config.json` or `config.js`**. If **both** exist, **`config.js` wins** (it is strictly more capable; use JSON-only when you want a static lump without dynamic hooks).
|
|
54
|
+
- **`config.ts` is not supported** for lump configuration—use **`config.js`** or **`config.json`**.
|
|
55
|
+
|
|
56
|
+
## Field forms (conventions)
|
|
57
|
+
|
|
58
|
+
Two forms appear repeatedly in the field tables below. Each is defined here once and referenced by name throughout the docs.
|
|
59
|
+
|
|
60
|
+
- **Function reference** — used for every field whose name ends with `Fn` (e.g. `branchFn`, `setupFn`, `getContextListFn`, `contextOptionsFn`, `promptFn`, `postCommandExecFn`). Accepts either:
|
|
61
|
+
- an **inline function** — only in `config.js`, or
|
|
62
|
+
- a **string path** to a `.js` file whose **default export** is the function — works in both `config.json` and `config.js`.
|
|
63
|
+
|
|
64
|
+
Relative paths resolve from the lump folder (`.lumpcode/lumps/<lumpName>/`). Modules are loaded with dynamic `import()`.
|
|
65
|
+
|
|
66
|
+
- **JSON reference** — used by `contextListJson`. Accepts either:
|
|
67
|
+
- an **inline JSON object**, or
|
|
68
|
+
- a **string path** to a JSON file with the same shape
|
|
69
|
+
|
|
70
|
+
### Command names
|
|
71
|
+
|
|
72
|
+
`command` fields (top-level and per-prompt-item) are **not** function references. They hold the **registered name** of a command module:
|
|
73
|
+
|
|
74
|
+
- **String** (e.g. `"cursor"`, `"copilot"`, `"claude"`, `"aider"`, `"my-agent"`) — resolved against `commands/<name>.js` under the project (`.lumpcode/commands/`), then the global config folder (`~/.lumpcode/commands/`), then shipped presets (`~/.lumpcode/commands/presets/`). Project-local wins over global override; global wins over preset. **`cursor`** and **`copilot`** are built-in preset names (require `cursor-agent` / `copilot` on `PATH`).
|
|
75
|
+
- **Inline function** (`config.js` only) — a `CommandFn` used directly without registry lookup.
|
|
76
|
+
|
|
77
|
+
Pass agent flags inside the command module's exported `command` function (`executable` + `args`), not in the `command` string. See [advanced-config.md](./advanced-config.md#custom-agent-commands).
|
|
78
|
+
|
|
79
|
+
## Prompt template syntax
|
|
80
|
+
|
|
81
|
+
In `promptTemplate` (and string shorthand prompts), the engine substitutes **only** braced placeholders like this:
|
|
82
|
+
|
|
83
|
+
- **`{VAR}`** → literal string value of `context.variables.VAR`
|
|
84
|
+
|
|
85
|
+
`VAR` must match a key from `contextListJson` (or a `variables` key returned by `getContextListFn` / `contextMatchFn`).
|
|
86
|
+
|
|
87
|
+
## Optional top-level fields
|
|
88
|
+
|
|
89
|
+
| Field | Type | Description |
|
|
90
|
+
|-------|------|-------------|
|
|
91
|
+
| `baseBranch` | string | Override `local.json.projectBaseBranch` for this lump only. Set when this campaign should branch off something other than the project-wide base (e.g. a long-lived release branch). |
|
|
92
|
+
| `command` | [Command name](#command-names) | Default agent command for all prompt items that don’t set their own `command` |
|
|
93
|
+
| `branchFn` | [Function reference](#field-forms-conventions) | Custom branch naming; default is `lump/<lumpName>/<contextNames…>` |
|
|
94
|
+
| `disabled` | boolean | When `true`, the background daemon skips this lump (`lumpcode start`); `run` still executes if invoked manually |
|
|
95
|
+
| `maximumNumberOfConcurrentBranches` | number | If set (≥ 0), `run` / daemon tick **skips** when open `lump/<lumpName>/*` branches on `origin` ≥ limit (local-only branches are not counted) |
|
|
96
|
+
| `numberOfContextsPerBranch` | number | How many contexts share one branch (default `1`) |
|
|
97
|
+
| `lumpVariables` | object | Arbitrary JSON passed into hooks and prompt functions as `lumpVariables` |
|
|
98
|
+
| `verbose` | boolean | Extra engine logging |
|
|
99
|
+
| `registerCommands` | string[] | Pre-load command modules (`.lumpcode/commands/<name>.js`) before resolving dynamic `steps` |
|
|
100
|
+
| `setupFn` / `teardownFn` | [Function reference](#field-forms-conventions) | Per-context lifecycle hooks |
|
|
101
|
+
| `contextOptionsFn` | [Function reference](#field-forms-conventions) | **Only with `contextListJson`:** set per-context `options` (`priority`, `dependsOnContexts`) after template expansion. See [under **contextListJson**](#contextoptionsfn-only-with-contextlistjson) |
|
|
102
|
+
| `keepHistory` | boolean | When `true`, append one JSON object per prompt step (after the agent command) to `.lumpcode/lumps/<lumpName>/history/<contextName>.json` |
|
|
103
|
+
|
|
104
|
+
Workspace preparation (fetch/pull/branch) is generated for you from `local.json` and the resolved `baseBranch`—there are no `workspaceSetup`, `setupWorkspaceFn`, or `teardownWorkspaceFn` knobs.
|
|
105
|
+
|
|
106
|
+
### Commit messages
|
|
107
|
+
|
|
108
|
+
The CLI **always** uses this git commit subject for each context:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
LUMP: <lumpName> - <contextName>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This format is fixed (not configurable) so that `clean`, `context-status`, and remote status detection stay in sync.
|
|
115
|
+
|
|
116
|
+
## `contextListJson`
|
|
117
|
+
|
|
118
|
+
### Inline object
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
"contextListJson": {
|
|
122
|
+
"FILE": "packages/{PKG}/src/index.ts"
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Each **key** becomes a **variable** name inside each generated context. Values are **path templates** containing:
|
|
127
|
+
|
|
128
|
+
- **`{PLACEHOLDER}`** — Captures a path segment from the real file tree; all placeholders in one template row must match the **same** file path for a row to contribute to a context.
|
|
129
|
+
- **`$modifier{PLACEHOLDER}`** — Same capture, but the on-disk text must equal `modifier(extractedPlaceholderValue)` (used for file naming conventions).
|
|
130
|
+
|
|
131
|
+
Default modifiers shipped with the template expander:
|
|
132
|
+
|
|
133
|
+
| Token | Effect |
|
|
134
|
+
|-------|--------|
|
|
135
|
+
| `$upperFirst` | `UpperFirst` |
|
|
136
|
+
| `$camel` | `camelCase` |
|
|
137
|
+
| `$kebab` | `kebab-case` |
|
|
138
|
+
| `$snake` | `snake_case` |
|
|
139
|
+
| `$lower` | `lowercase` |
|
|
140
|
+
| `$pascal` | `PascalCase` |
|
|
141
|
+
|
|
142
|
+
The **context name** is derived by concatenating every captured placeholder tuples with `-` between parts. In most cases, you will use only one placeholder.
|
|
143
|
+
|
|
144
|
+
### External JSON file
|
|
145
|
+
|
|
146
|
+
Pass `contextListJson` as a **JSON reference** path (a [JSON reference](#field-forms-conventions) string) instead of an inline object. The file must contain a JSON object of string templates.
|
|
147
|
+
|
|
148
|
+
Use plain relative paths in templates—**prefer patterns without a leading `./`** (e.g. `"src/{NAME}.ts"`, not `"./src/{NAME}.ts"`).
|
|
149
|
+
|
|
150
|
+
### `contextOptionsFn` (only with `contextListJson`)
|
|
151
|
+
|
|
152
|
+
`contextListJson` alone builds `name` and `variables` only. To add **`options`** (see [types.md](./types.md#context) — `priority`, `dependsOnContexts`) to each context, set top-level **`contextOptionsFn`** as a [function reference](#field-forms-conventions).
|
|
153
|
+
|
|
154
|
+
The function receives each context **before** `options` is set and may return a `Context['options']` object to merge, or `null` / `undefined` to return no options. Shape: [types.md](./types.md#contextoptionsfn).
|
|
155
|
+
|
|
156
|
+
`contextOptionsFn` is **not** read when the context source is `getContextListFn` or `contextMatchFn` (those already attach `options` on the returned data).
|
|
157
|
+
|
|
158
|
+
### `getContextListFn` and `contextMatchFn`
|
|
159
|
+
|
|
160
|
+
Both are [function references](#field-forms-conventions). Shapes: [types.md](./types.md). Examples: [advanced-config.md](./advanced-config.md). **`contextMatchFn`** is invoked once per scanned path with `codeBasePath` (the current entry), `codeBasePaths` (the full list for that run), and `lumpVariables`. Matches that share a `contextName` are merged into one context (see [types.md § ContextMatchFn](./types.md#contextmatchfn)); use a distinct `contextName` per unit of work when you want separate contexts. Put per-context `priority` and `dependsOnContexts` on each `Context` returned from **`getContextListFn`**, or in **`contextOptions`** on **`contextMatchFn`** results.
|
|
161
|
+
|
|
162
|
+
## Prompt configuration
|
|
163
|
+
|
|
164
|
+
### Shorthand `prompt`
|
|
165
|
+
|
|
166
|
+
`prompt` may be:
|
|
167
|
+
|
|
168
|
+
1. **String** — Treated as inline **`promptTemplate`** text (with `{VAR}` substitution). This string is **never** read as a file path—use a [function reference](#field-forms-conventions) on `promptFn` to load from disk.
|
|
169
|
+
2. **Object** — `LumpJsonConfigStep` fields below.
|
|
170
|
+
|
|
171
|
+
### `steps` array
|
|
172
|
+
|
|
173
|
+
Each element may be:
|
|
174
|
+
|
|
175
|
+
- **String** — Same as shorthand template above.
|
|
176
|
+
- **Object** — Full `LumpJsonConfigStep`.
|
|
177
|
+
- **Function** (`config.js` only) — A function-form item that returns more items dynamically (see [advanced-config.md](./advanced-config.md#dynamic-steps)).
|
|
178
|
+
|
|
179
|
+
### Per-item fields (`LumpJsonConfigStep`)
|
|
180
|
+
|
|
181
|
+
| Field | Type | Description |
|
|
182
|
+
|-------|------|-------------|
|
|
183
|
+
| `promptTemplate` | string | Optional. Inline template text — same `{VAR}` rules as [Prompt template syntax](#prompt-template-syntax). Mutually exclusive with `promptFn` on the same step. When omitted, the command receives an empty prompt string. |
|
|
184
|
+
| `promptFn` | [Function reference](#field-forms-conventions) | Optional. Returns prompt text. Mutually exclusive with `promptTemplate` on the same step. |
|
|
185
|
+
| `command` | [Command name](#command-names) | Required on each step unless overridden inline via `commandFn` in `config.js`; inherits top-level `command` when omitted. |
|
|
186
|
+
| `postCommandExecFn` | [Function reference](#field-forms-conventions) | Hook called after the agent finishes |
|
|
187
|
+
| `stepVariables` | object | JSON-serializable bag passed to promptFn/command/postCommandExecFn hooks |
|
|
188
|
+
| `timeoutMillis` | number | Millis cap for the agent process |
|
|
189
|
+
|
|
190
|
+
## Prompt run history (`keepHistory`)
|
|
191
|
+
|
|
192
|
+
By default, Lumpcode does **not** write prompt or agent output to disk. Set **`"keepHistory": true`** on a lump (in `config.json` or `config.js`) to record each prompt step locally.
|
|
193
|
+
|
|
194
|
+
### File layout
|
|
195
|
+
|
|
196
|
+
When enabled, after each successful agent command the engine appends one entry to:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
.lumpcode/lumps/<lumpName>/history/<contextName>.json
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
There is **One file per context** — all prompt steps for that context are in the same JSON array.
|
|
203
|
+
|
|
204
|
+
### Entry shape
|
|
205
|
+
|
|
206
|
+
Each array element matches the input passed to **`postCommandExecFn`** (see [types.md](./types.md) and the [core README](https://github.com/lumpcode/lumpcode/blob/main/packages/core/README.md)):
|
|
207
|
+
|
|
208
|
+
| Field | Description |
|
|
209
|
+
|-------|-------------|
|
|
210
|
+
| `commandResult` | Agent stdout/stderr combined (can be large; may contain secrets) |
|
|
211
|
+
| `context` | The context object (`name`, `variables`, optional `options`) |
|
|
212
|
+
| `prompt` | Resolved prompt string sent to the agent |
|
|
213
|
+
| `stepIndex` | Step index at the root, or a path like `[1, 0]` for nested dynamic items |
|
|
214
|
+
| `contextRunState` | Mutable bag for this context run |
|
|
215
|
+
| `lumpVariables` | Lump-level variables from config |
|
|
216
|
+
| `stepVariables` | Per-item variables, if set |
|
|
217
|
+
| `projectRoot` | Absolute project root path |
|
|
218
|
+
|
|
219
|
+
History is written **before** an optional `postCommandExecFn` on the same prompt item runs.
|
|
220
|
+
|
|
221
|
+
### Git and privacy
|
|
222
|
+
|
|
223
|
+
`lumpcode project-setup` appends **`.lumpcode/**/history/`** to `.gitignore` so run logs stay local. History is intended for debugging and inspection on your machine—not for sharing via git.
|
|
224
|
+
|
|
225
|
+
### Example
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"contextListJson": { "FILE": "src/{NAME}.ts" },
|
|
230
|
+
"keepHistory": true,
|
|
231
|
+
"prompt": {
|
|
232
|
+
"promptTemplate": "Improve @{FILE}",
|
|
233
|
+
"command": "claude"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## `contextStatusRecord.json`
|
|
239
|
+
|
|
240
|
+
Auto-maintained cache of the context statuses under each lump folder. Keys are **context names**; each value:
|
|
241
|
+
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"status": "toDo | branchPushed | finished",
|
|
245
|
+
"contextName": "same-as-key",
|
|
246
|
+
"branchName": "lump/myLump/foo-bar or empty",
|
|
247
|
+
"commitMessage": "LUMP: myLump - foo-bar"
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Status semantics: [concepts.md#core-terms](./concepts.md#core-terms). Refresh with `lumpcode lump-status` or automatically after `run`.
|
|
252
|
+
|
|
253
|
+
## Typed JavaScript config (optional)
|
|
254
|
+
|
|
255
|
+
Install [`@lumpcode/cli-types`](https://www.npmjs.com/package/@lumpcode/cli-types) as a dev dependency and use its `defineConfig` (and other `define*` helpers) so `config.js` gets accurate TypeScript hints for every hook and field:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npm install --save-dev @lumpcode/cli-types
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
import { defineConfig } from '@lumpcode/cli-types';
|
|
263
|
+
|
|
264
|
+
export default defineConfig({
|
|
265
|
+
contextListJson: { FILE: 'src/{NAME}.ts' },
|
|
266
|
+
prompt: { promptTemplate: 'Fix @{FILE}', command: 'claude' },
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Related documentation
|
|
271
|
+
|
|
272
|
+
- [concepts.md](./concepts.md) — Status lifecycle, pre-flight, daemon overview
|
|
273
|
+
- [local-config.md](./local-config.md) — Per-machine `local.json` (`mode`, `projectBaseBranch`)
|
|
274
|
+
- [advanced-config.md](./advanced-config.md) — Hooks, dynamic prompts, custom commands
|
|
275
|
+
- [types.md](./types.md) — Callback signatures
|
|
276
|
+
- [commands.md](./commands.md) — `run`, `daemon-status`, `lump-status`, `context-status`
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Project configuration (`.lumpcode/project.json`)
|
|
2
|
+
|
|
3
|
+
When you run `lumpcode project-setup`, the CLI creates **`.lumpcode/project.json`** at the root of your git repository (next to `.lumpcode/lumps/` and `.lumpcode/commands/`). This file identifies the project for **daemon files**, **project copy** folder names, and human-readable status output.
|
|
4
|
+
|
|
5
|
+
## Minimal example
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"projectName": "my-monorepo"
|
|
10
|
+
}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## `projectName` rules
|
|
14
|
+
|
|
15
|
+
- **Required for Lumpcode to run:** After setup, every command that needs a project identity reads **`projectName`** from this file. If `project.json` is missing, `projectName` is empty, or the value is invalid, those commands **fail** with an error that points you to `project-setup` or editing `project.json`.
|
|
16
|
+
- **Allowed characters only:** Letters, digits, underscore (`_`), and hyphen (`-`). No spaces or other punctuation (pattern: `^[a-zA-Z0-9_-]+$`).
|
|
17
|
+
|
|
18
|
+
**`lumpcode project-setup`** writes `projectName` for you: if you omit `--projectName`, it infers a name from **`git remote get-url origin`** (last URL segment, without `.git`) or from the **directory basename**, then normalizes it so it satisfies the rules above. If you pass **`--projectName`**, it must already satisfy the rules (no silent rewriting).
|
|
19
|
+
|
|
20
|
+
## Schema (other fields optional)
|
|
21
|
+
|
|
22
|
+
| Field | Type | Description |
|
|
23
|
+
|-------|------|-------------|
|
|
24
|
+
| `projectName` | string | **Required** for runs once the project exists; see [rules](#projectname-rules) above. Used as-is for daemon filenames under `~/.lumpcode/daemons/` and for `~/.lumpcode/project-copies/<projectName>/` when `local.json.mode` is `shared` |
|
|
25
|
+
| `maximumNumberOfConcurrentBranches` | number | Default cap on simultaneously open `lump/<lumpName>/*` branches on `origin` across the project (local-only branches are not counted; a lump can override in its own config) |
|
|
26
|
+
|
|
27
|
+
Where Lumpcode runs lumps (in-place vs. on a copy), which branch is treated as the project base, and whether the daemon is paused on this machine are **per-machine** settings; they live in `.lumpcode/local.json` instead. See [local-config.md](./local-config.md).
|
|
28
|
+
|
|
29
|
+
## Why `.lumpcode/` lives next to `.git`
|
|
30
|
+
|
|
31
|
+
Lumpcode treats a directory as a project root only when it contains both:
|
|
32
|
+
|
|
33
|
+
- `.git/` — source of truth for branches, remotes, and commit history
|
|
34
|
+
- `.lumpcode/` — configuration, per-lump status JSON, and optional custom `commands/*.js`
|
|
35
|
+
|
|
36
|
+
Keeping both at the repo root lets you **commit** lump definitions with the same revision control as your product code.
|
|
37
|
+
|
|
38
|
+
## Commit vs. `.gitignore`
|
|
39
|
+
|
|
40
|
+
**Commit** when:
|
|
41
|
+
|
|
42
|
+
- Your team should share lump definitions, prompts, and command wrappers
|
|
43
|
+
- You want `contextStatusRecord.json` visible for review (optional—some teams prefer local-only state)
|
|
44
|
+
|
|
45
|
+
**Gitignore** (or omit specific files) when:
|
|
46
|
+
|
|
47
|
+
- Status files are noisy in PRs (`contextStatusRecord.json`)
|
|
48
|
+
- Custom commands embed machine-specific paths or secrets
|
|
49
|
+
|
|
50
|
+
## Related topics
|
|
51
|
+
|
|
52
|
+
- [concepts.md](./concepts.md) — Project root, daemon files, workspace copies
|
|
53
|
+
- [local-config.md](./local-config.md) — Per-machine `local.json` (`mode`, `projectBaseBranch`)
|
|
54
|
+
- [get-started.md](./get-started.md) — First-time setup
|
|
55
|
+
- [lump-config.md](./lump-config.md) — Per-lump `config.json`
|
|
56
|
+
- [commands.md](./commands.md) — `project-setup` flags
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Publishing `@lumpcode/*` to npm (operators)
|
|
2
|
+
|
|
3
|
+
Operator-only notes for publishing from the monorepo. End users install via `npm i -g @lumpcode/cli@beta` (see [README](../README.md)).
|
|
4
|
+
|
|
5
|
+
## Packages and order
|
|
6
|
+
|
|
7
|
+
Publish in dependency order:
|
|
8
|
+
|
|
9
|
+
1. `@lumpcode/core`
|
|
10
|
+
2. `@lumpcode/cli-types`
|
|
11
|
+
3. `@lumpcode/cli`
|
|
12
|
+
|
|
13
|
+
Each `package.json` includes `publishConfig.access: public` for the first scoped public publish under the `lumpcode` org.
|
|
14
|
+
|
|
15
|
+
## Pre-publish verification
|
|
16
|
+
|
|
17
|
+
From the monorepo root:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export ENV=prod
|
|
21
|
+
export API_URL=https://api.lumpcode.com # optional; baked into CLI bundle
|
|
22
|
+
|
|
23
|
+
npm run build -w=@lumpcode/core
|
|
24
|
+
npm run build -w=@lumpcode/cli-types
|
|
25
|
+
npm run build:bundle -w=@lumpcode/cli
|
|
26
|
+
|
|
27
|
+
npm run test -w=@lumpcode/core
|
|
28
|
+
npm run test -w=@lumpcode/cli
|
|
29
|
+
npm run test:e2e:node -w=@lumpcode/cli # optional smoke
|
|
30
|
+
|
|
31
|
+
npm pack -w=@lumpcode/core
|
|
32
|
+
npm pack -w=@lumpcode/cli-types
|
|
33
|
+
npm pack -w=@lumpcode/cli
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Inspect tarballs: `dist/`, CLI `bin/`, `postinstall` scripts, `LICENSE`, README.
|
|
37
|
+
|
|
38
|
+
Or use the helper script (build + publish):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node scripts/publish-npm-beta.mjs --dry-run # build + pack only
|
|
42
|
+
node scripts/publish-npm-beta.mjs # build + publish with beta tag
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## First publish (`beta` tag)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm login
|
|
49
|
+
npm whoami
|
|
50
|
+
|
|
51
|
+
npm publish -w=@lumpcode/core --access public --tag beta
|
|
52
|
+
npm publish -w=@lumpcode/cli-types --access public --tag beta
|
|
53
|
+
npm publish -w=@lumpcode/cli --access public --tag beta
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Beta testers:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i -g @lumpcode/cli@beta
|
|
60
|
+
npm i -D @lumpcode/cli-types@beta
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Promote to `latest`
|
|
64
|
+
|
|
65
|
+
When ready for default installs:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm dist-tag add @lumpcode/core@0.0.0 latest
|
|
69
|
+
npm dist-tag add @lumpcode/cli-types@0.0.0 latest
|
|
70
|
+
npm dist-tag add @lumpcode/cli@0.0.0 latest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Replace `0.0.0` with the version you are promoting.
|
|
74
|
+
|
|
75
|
+
## Notes
|
|
76
|
+
|
|
77
|
+
- `repository` in `package.json` is omitted (not required for publish).
|
|
78
|
+
- CLI `postinstall` binary download uses `native-binary.mjs` / `LUMPCODE_INSTALL_REPO`, separate from npm metadata.
|
|
79
|
+
- `prepublishOnly` runs builds: `core` and `cli-types` → `npm run build`; `cli` → `npm run build:bundle`.
|
package/DOCS/types.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Types for Lumpcode lump configuration
|
|
2
|
+
|
|
3
|
+
This reference lists the JSON shapes and **JavaScript function signatures** you use in `config.json` / `config.js`. Types are described in TypeScript notation for clarity.
|
|
4
|
+
|
|
5
|
+
Conventions:
|
|
6
|
+
|
|
7
|
+
- `Maybe<T>` means `T | null | undefined`
|
|
8
|
+
- `MaybePromise<T>` means `T | Promise<T>`
|
|
9
|
+
- Each function signature below is a [function reference](./lump-config.md#field-forms-conventions): in `config.js` you may pass it inline, and in either format you may pass a string path to a `.js` module whose **default export** matches the signature.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## JSON data shapes
|
|
14
|
+
|
|
15
|
+
### `Context`
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
interface Context {
|
|
19
|
+
name: string;
|
|
20
|
+
variables: Record<string, string>;
|
|
21
|
+
options?: {
|
|
22
|
+
priority?: number;
|
|
23
|
+
dependsOnContexts?: string[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `name` — unique id for the unit of work; drives default commit subject suffix.
|
|
29
|
+
- `variables` — string map substituted into `{VAR}` / `@{VAR}` in prompts.
|
|
30
|
+
- `options.priority` — lower runs sooner.
|
|
31
|
+
- `options.dependsOnContexts` — names of contexts that must be **`finished`** before this one runs.
|
|
32
|
+
|
|
33
|
+
### `ContextList`
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
type ContextList = Context[];
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Return type of `getContextListFn`; built internally for `contextMatchFn` and `contextListJson` (with optional `contextOptionsFn`) merges.
|
|
40
|
+
|
|
41
|
+
### `ContextOptionsFn`
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
type ContextOptionsFn = (
|
|
45
|
+
contextWithoutOptions: Omit<Context, 'options'>,
|
|
46
|
+
) => MaybePromise<Maybe<Context['options']>>;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- **Input** — a `Context` with `name` and `variables` only (no `options` field yet from the template expander).
|
|
50
|
+
- **Return** — `null` or `undefined` to leave `options` unset; otherwise an object merged into that context (same shape as `Context['options']`).
|
|
51
|
+
|
|
52
|
+
Runs only when **`contextListJson`** is the context source; ignored for `getContextListFn` and `contextMatchFn`.
|
|
53
|
+
|
|
54
|
+
### `CodeBasePath`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
interface CodeBasePath {
|
|
58
|
+
isDir: boolean;
|
|
59
|
+
path: string;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Paths use `/` separators, relative to the project root. Passed to `getContextListFn` as `codeBasePaths`. `contextMatchFn` receives the current path as `codeBasePath` and the full scanned list as `codeBasePaths` on every call.
|
|
64
|
+
|
|
65
|
+
### `ContextRunState`
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
type ContextRunState = Record<string, unknown>;
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Mutable bag shared across prompt items for one context execution. Seed from `setupFn`; read/write in `promptFn`, `postCommandExecFn`, and dynamic `steps` functions.
|
|
72
|
+
|
|
73
|
+
### `LumpVariables`
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type LumpVariables = Record<string, unknown>;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Top-level **`lumpVariables`** object from lump config, forwarded into every hook.
|
|
80
|
+
|
|
81
|
+
### `StepVariables`
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
type StepVariables = Record<string, unknown>;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Per–prompt-step bag from `stepVariables` on a prompt item.
|
|
88
|
+
|
|
89
|
+
### `ContextStatus`
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
type ContextStatus = 'toDo' | 'branchPushed' | 'finished';
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Semantics: [concepts.md#core-terms](./concepts.md#core-terms).
|
|
96
|
+
|
|
97
|
+
### `ContextStatusRecordItem`
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
interface ContextStatusRecordItem {
|
|
101
|
+
status: ContextStatus;
|
|
102
|
+
contextName: string;
|
|
103
|
+
branchName: string;
|
|
104
|
+
commitMessage: string;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### `ContextStatusRecord`
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
type ContextStatusRecord = Record<string, ContextStatusRecordItem>;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The on-disk JSON uses the same keys as `contextName`.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Hook signatures
|
|
119
|
+
|
|
120
|
+
### `GetContextListFn`
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
interface GetContextListFnInput {
|
|
124
|
+
codeBasePaths: CodeBasePath[];
|
|
125
|
+
lumpVariables: LumpVariables;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type GetContextListFn = (
|
|
129
|
+
params: GetContextListFnInput,
|
|
130
|
+
) => MaybePromise<ContextList>;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `ContextMatchFn`
|
|
134
|
+
|
|
135
|
+
Called once per scanned `CodeBasePath`. `codeBasePath` is the current entry; `codeBasePaths` is the full list for that run (same array reference on every call).
|
|
136
|
+
|
|
137
|
+
Every returned `contextName` must be unique in the final context list. Lumpcode enforces that by **merging** all matches that share a `contextName` into one `Context`: `variables` keys accumulate (same key from a later file overwrites), and `contextOptions` from a later match replace earlier ones. For one file per context, give each match a distinct `contextName` (path-based names are common—see [examples.md](./examples.md#3-test-coverage-sweep--add-a-test-next-to-every-untested-module)).
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
type ContextMatchFn = (params: {
|
|
141
|
+
codeBasePath: CodeBasePath;
|
|
142
|
+
codeBasePaths: CodeBasePath[];
|
|
143
|
+
lumpVariables: Record<string, unknown>;
|
|
144
|
+
}) => MaybePromise<
|
|
145
|
+
Maybe<{
|
|
146
|
+
contextName: string;
|
|
147
|
+
filePathVariableName: string;
|
|
148
|
+
moreContextVariables?: Record<string, string>;
|
|
149
|
+
contextOptions?: Context['options'];
|
|
150
|
+
}>
|
|
151
|
+
>;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `BranchFn`
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
type BranchFn = (params: {
|
|
158
|
+
contextList: Context[];
|
|
159
|
+
contextRunStateList: ContextRunState[];
|
|
160
|
+
lumpVariables: LumpVariables;
|
|
161
|
+
}) => MaybePromise<string>;
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Return the **git branch name** to use for this batch.
|
|
165
|
+
|
|
166
|
+
### `PromptFn`
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
interface PromptFnInput {
|
|
170
|
+
context: Context;
|
|
171
|
+
/** Root index or nested path for dynamic `steps` */
|
|
172
|
+
stepIndex: number | number[];
|
|
173
|
+
contextRunState: ContextRunState;
|
|
174
|
+
lumpVariables: LumpVariables;
|
|
175
|
+
stepVariables?: StepVariables;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
type PromptFn = (params: PromptFnInput) => MaybePromise<string>;
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### `CommandFn`
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
type CommandFn = ((
|
|
185
|
+
params: {
|
|
186
|
+
context: Context;
|
|
187
|
+
prompt: string;
|
|
188
|
+
stepIndex: number | number[];
|
|
189
|
+
contextRunState: ContextRunState;
|
|
190
|
+
lumpVariables: LumpVariables;
|
|
191
|
+
stepVariables?: StepVariables;
|
|
192
|
+
projectRoot: string;
|
|
193
|
+
workspacePath: string;
|
|
194
|
+
},
|
|
195
|
+
) => MaybePromise<{ executable: string; args: string[] } | null | undefined | void>) & {
|
|
196
|
+
/** Set automatically when Lumpcode resolves a named command module */
|
|
197
|
+
commandName?: string;
|
|
198
|
+
};
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Return `{ executable, args }` to run a subprocess. Return `null`, `undefined`, or nothing to skip execution; `postCommandExecFn` still runs with an empty `commandResult`. `keepHistory` entries are not written for skipped commands.
|
|
202
|
+
|
|
203
|
+
Lumpcode runs the agent as `executable` + `args`. Agent-specific flags and the prompt text go into `args` the way your agent expects (e.g. `executable: 'claude', args: ['-p', prompt]` or `executable: 'aider', args: ['--message', prompt]`). This is exactly what a command module at `.lumpcode/commands/<name>.js` exports as its `command`.
|
|
204
|
+
|
|
205
|
+
### `PostCommandExecFn`
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
type PostCommandExecFn = (input: {
|
|
209
|
+
commandResult: string;
|
|
210
|
+
context: Context;
|
|
211
|
+
prompt: string;
|
|
212
|
+
stepIndex: number | number[];
|
|
213
|
+
contextRunState: ContextRunState;
|
|
214
|
+
lumpVariables: LumpVariables;
|
|
215
|
+
stepVariables?: StepVariables;
|
|
216
|
+
projectRoot: string;
|
|
217
|
+
}) => MaybePromise<void>;
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`commandResult` is the **captured stdout** (string). Parse JSON yourself if your agent returns structured text.
|
|
221
|
+
|
|
222
|
+
### `SetupFn`
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
type SetupFn = (params: {
|
|
226
|
+
contextList: Context[];
|
|
227
|
+
lumpVariables: LumpVariables;
|
|
228
|
+
currentContextIndex: number;
|
|
229
|
+
}) => MaybePromise<
|
|
230
|
+
Maybe<Partial<{ contextRunState: ContextRunState }>>
|
|
231
|
+
>;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `TeardownFn`
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
type TeardownFn = (params: {
|
|
238
|
+
lumpVariables: LumpVariables;
|
|
239
|
+
contextList: Context[];
|
|
240
|
+
contextRunState: ContextRunState;
|
|
241
|
+
currentContextIndex: number;
|
|
242
|
+
}) => MaybePromise<void>;
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Workspace hooks
|
|
246
|
+
|
|
247
|
+
There is no user-facing `setupWorkspaceFn` / `teardownWorkspaceFn` in lump config any more — the CLI generates both from the resolved workspace (per [local-config.md](./local-config.md)'s `mode`) and the lump's `baseBranch`. See [advanced-config.md](./advanced-config.md#workspace-handling) for the rationale.
|
|
248
|
+
|
|
249
|
+
### Command module (`command` / `setup` / `teardown`)
|
|
250
|
+
|
|
251
|
+
Custom modules under `.lumpcode/commands/<name>.js` export:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
export const command: CommandFn = …;
|
|
255
|
+
export const setup?: SetupFn;
|
|
256
|
+
export const teardown?: TeardownFn;
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`setup` / `teardown` use the same parameter shapes as lump-level hooks.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Related documentation
|
|
264
|
+
|
|
265
|
+
- [lump-config.md](./lump-config.md) — Where these types appear in JSON
|
|
266
|
+
- [advanced-config.md](./advanced-config.md) — Hooks, dynamic prompts, custom commands
|
|
267
|
+
- [concepts.md](./concepts.md) — Daemon, workspace, status lifecycle
|