lanekeeper 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -102,17 +102,11 @@ This does the whole setup, not just the config file:
102
102
  - **`.husky/pre-push`** — created or appended to, *if* you already have
103
103
  Husky. If you don't, `init` tells you so instead of silently writing to
104
104
  the untracked, not-shared-with-your-team `.git/hooks/pre-push`.
105
+ - **`package.json` scripts** — `land`, `sync`, `promote`, `preview`, and
106
+ `preview:restore` added, skipping any you've already defined yourself.
105
107
 
106
- **Commit everything it wrote.** Then add to `package.json`:
107
- ```json
108
- "scripts": {
109
- "land": "lanekeeper land",
110
- "sync": "lanekeeper sync",
111
- "promote": "lanekeeper promote",
112
- "preview": "lanekeeper preview",
113
- "preview:restore": "lanekeeper preview --restore"
114
- }
115
- ```
108
+ **Commit everything it wrote**, then you're running. Two steps, not a setup
109
+ guide.
116
110
 
117
111
  If `init` couldn't detect a `checkCommand` (no matching script in
118
112
  package.json), every push is **blocked** until you set one — see 🧰 What's
@@ -16,7 +16,7 @@ import { runWorktreeCreateHook } from "../hooks/worktree-create.js";
16
16
  import { lanePort } from "../lib/lane-port.js";
17
17
  import { claudeMdSnippet, MARKER } from "../lib/claude-md-snippet.js";
18
18
  import { detectCheckCommand, runCheckCommand } from "../lib/check-command.js";
19
- import { wireClaudeSettings, wireHuskyPrePush, ensureHooksPath } from "../lib/wire-hooks.js";
19
+ import { wireClaudeSettings, wireHuskyPrePush, ensureHooksPath, wirePackageJsonScripts } from "../lib/wire-hooks.js";
20
20
  import { resolveMainCheckout } from "../lib/main-checkout.js";
21
21
  import { pruneLandedLanes } from "../lib/prune-lanes.js";
22
22
  const [, , command, ...rest] = process.argv;
@@ -139,13 +139,27 @@ export default ${JSON.stringify(generated, null, 2)};
139
139
  break;
140
140
  }
141
141
  }
142
+ const scriptsResult = wirePackageJsonScripts(root);
143
+ switch (scriptsResult.result) {
144
+ case "added":
145
+ console.log(`lanekeeper init: added "${scriptsResult.added.join('", "')}" to package.json scripts.`);
146
+ break;
147
+ case "already-wired":
148
+ console.log("lanekeeper init: package.json already has all five scripts — leaving them alone.");
149
+ break;
150
+ case "no-package-json":
151
+ console.log("lanekeeper init: no package.json found — scripts NOT wired automatically.");
152
+ console.log(' Add "land"/"sync"/"promote"/"preview"/"preview:restore" -> "lanekeeper <name>" yourself.');
153
+ break;
154
+ case "unparseable":
155
+ console.log("lanekeeper init: package.json exists but isn't valid JSON — left untouched. Wire the scripts manually.");
156
+ break;
157
+ }
142
158
  console.log("");
143
159
  console.log("Next steps:");
144
- console.log(" 1. Check lanekeeper.config.mjs integrationBranch/checkCommand were auto-detected;");
145
- console.log(" set productionBranch too if you run a two-stage model.");
146
- console.log(' 2. Add to package.json "scripts": land, sync, promote, preview -> "lanekeeper <name>".');
147
- console.log(" 3. Commit lanekeeper.config.mjs, CLAUDE.md, .claude/settings.json, and .husky/pre-push.");
148
- console.log(" 4. claude --worktree <name> — the agent takes it from there.");
160
+ console.log(" 1. Commit everything it wrote — lanekeeper.config.mjs, CLAUDE.md, .claude/settings.json,");
161
+ console.log(" .husky/pre-push, and package.json.");
162
+ console.log(" 2. claude --worktree <name> the agent takes it from there.");
149
163
  }
150
164
  async function main() {
151
165
  switch (command) {
@@ -24,3 +24,16 @@ export type HooksPathResult = "set" | "already-set" | "custom-path";
24
24
  * husky's own next real install corrects it to `.husky/_`.
25
25
  */
26
26
  export declare function ensureHooksPath(root: string): HooksPathResult;
27
+ export type ScriptsWireResult = "added" | "already-wired" | "unparseable" | "no-package-json";
28
+ /**
29
+ * The last "copy this yourself" step `init` used to leave on the table:
30
+ * Quickstart told you to hand-add five scripts to package.json instead of
31
+ * just adding them. Same additive/idempotent contract as the rest of this
32
+ * file — only ever fills in scripts that don't exist yet, never overwrites
33
+ * one you've customized (e.g. if `land` already runs something of yours
34
+ * first), and does nothing if all five are already there.
35
+ */
36
+ export declare function wirePackageJsonScripts(root: string): {
37
+ result: ScriptsWireResult;
38
+ added: string[];
39
+ };
@@ -15,6 +15,13 @@ import { dirname, join } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
16
  const HOOK_COMMAND = "npx lanekeeper hook worktree-create";
17
17
  const PRE_PUSH_MARKER = "lanekeeper check-push";
18
+ const PACKAGE_SCRIPTS = {
19
+ land: "lanekeeper land",
20
+ sync: "lanekeeper sync",
21
+ promote: "lanekeeper promote",
22
+ preview: "lanekeeper preview",
23
+ "preview:restore": "lanekeeper preview --restore",
24
+ };
18
25
  export function wireClaudeSettings(root) {
19
26
  const dir = join(root, ".claude");
20
27
  const path = join(dir, "settings.json");
@@ -121,3 +128,35 @@ export function ensureHooksPath(root) {
121
128
  execFileSync("git", ["config", "core.hooksPath", ".husky"], { cwd: root });
122
129
  return "set";
123
130
  }
131
+ /**
132
+ * The last "copy this yourself" step `init` used to leave on the table:
133
+ * Quickstart told you to hand-add five scripts to package.json instead of
134
+ * just adding them. Same additive/idempotent contract as the rest of this
135
+ * file — only ever fills in scripts that don't exist yet, never overwrites
136
+ * one you've customized (e.g. if `land` already runs something of yours
137
+ * first), and does nothing if all five are already there.
138
+ */
139
+ export function wirePackageJsonScripts(root) {
140
+ const path = join(root, "package.json");
141
+ if (!existsSync(path))
142
+ return { result: "no-package-json", added: [] };
143
+ let pkg;
144
+ try {
145
+ pkg = JSON.parse(readFileSync(path, "utf8"));
146
+ }
147
+ catch {
148
+ return { result: "unparseable", added: [] };
149
+ }
150
+ pkg.scripts ??= {};
151
+ const added = [];
152
+ for (const [name, command] of Object.entries(PACKAGE_SCRIPTS)) {
153
+ if (!(name in pkg.scripts)) {
154
+ pkg.scripts[name] = command;
155
+ added.push(name);
156
+ }
157
+ }
158
+ if (added.length === 0)
159
+ return { result: "already-wired", added: [] };
160
+ writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n");
161
+ return { result: "added", added };
162
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lanekeeper",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "The local, zero-cost merge queue for parallel Claude Code agents. Plugs into Claude Code's native worktree isolation; one build at a time, one landing at a time, zero races.",
5
5
  "type": "module",
6
6
  "license": "MIT",