@lsst/pik-plugin-worktree 0.4.2

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 ADDED
@@ -0,0 +1,78 @@
1
+ # @lsst/pik-plugin-worktree
2
+
3
+ Git worktree management plugin for pik - easily create, list, and remove git worktrees.
4
+
5
+ ## Installation
6
+
7
+ This plugin is included with `@lsst/pik` by default.
8
+
9
+ ```bash
10
+ npm install -g @lsst/pik
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Interactive create (default)
17
+ pik worktree
18
+
19
+ # Create with specific name
20
+ pik worktree create my-feature
21
+
22
+ # Create new branch
23
+ pik worktree create my-feature -n -b feature/new-thing
24
+
25
+ # List all worktrees
26
+ pik worktree list
27
+
28
+ # Remove a worktree
29
+ pik worktree remove
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ Add to your `pik.config.ts`:
35
+
36
+ ```typescript
37
+ import { defineConfig } from '@lsst/pik';
38
+
39
+ export default defineConfig({
40
+ worktree: {
41
+ // Directory where worktrees are created (relative to repo root)
42
+ baseDir: '../',
43
+
44
+ // Files to copy to new worktrees
45
+ copyFiles: ['.env.local', '.env.development'],
46
+
47
+ // Command to run after creating worktree
48
+ postCreate: 'npm install',
49
+ },
50
+ });
51
+ ```
52
+
53
+ ## Commands
54
+
55
+ | Command | Alias | Description |
56
+ |---------|-------|-------------|
57
+ | `pik worktree` | `wt` | Interactive worktree creation |
58
+ | `pik worktree create [name]` | `add` | Create a new worktree |
59
+ | `pik worktree list` | `ls` | List all worktrees |
60
+ | `pik worktree remove [path]` | `rm` | Remove a worktree |
61
+
62
+ ### Create Options
63
+
64
+ | Option | Description |
65
+ |--------|-------------|
66
+ | `-b, --branch <branch>` | Branch to checkout or create |
67
+ | `-n, --new` | Create a new branch |
68
+
69
+ ### Remove Options
70
+
71
+ | Option | Description |
72
+ |--------|-------------|
73
+ | `-f, --force` | Force removal even if dirty |
74
+ | `-D, --delete-branch` | Also delete the branch |
75
+
76
+ ## License
77
+
78
+ MIT
@@ -0,0 +1,4 @@
1
+ export { worktreePlugin } from './lib/plugin.js';
2
+ export type { WorktreeConfig } from './lib/types.js';
3
+ export { git, getRepoRoot, getCurrentBranch, isClean, listWorktrees, createWorktree, removeWorktree, listBranches, branchExists, type Worktree, } from './lib/git.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EACL,GAAG,EACH,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,cAAc,EACd,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,KAAK,QAAQ,GACd,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,352 @@
1
+ import { Command } from "commander";
2
+ import { select, input, confirm } from "@inquirer/prompts";
3
+ import pc from "picocolors";
4
+ import { basename, resolve, relative } from "path";
5
+ import { execSync } from "child_process";
6
+ import { existsSync, mkdirSync, copyFileSync } from "fs";
7
+ import { glob } from "glob";
8
+ import { loadConfig } from "@lsst/pik-core";
9
+ function git(args, cwd) {
10
+ try {
11
+ return execSync(`git ${args.join(" ")}`, {
12
+ cwd,
13
+ encoding: "utf-8",
14
+ stdio: ["pipe", "pipe", "pipe"]
15
+ }).trim();
16
+ } catch (error) {
17
+ const err = error;
18
+ const gitError = new Error(
19
+ err.stderr?.toString().trim() || err.message
20
+ );
21
+ gitError.stderr = err.stderr?.toString();
22
+ throw gitError;
23
+ }
24
+ }
25
+ function getRepoRoot(cwd) {
26
+ return git(["rev-parse", "--show-toplevel"], cwd);
27
+ }
28
+ function getCurrentBranch(cwd) {
29
+ return git(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
30
+ }
31
+ function isClean(cwd) {
32
+ const status = git(["status", "--porcelain"], cwd);
33
+ return status === "";
34
+ }
35
+ function listWorktrees(cwd) {
36
+ const output = git(["worktree", "list", "--porcelain"], cwd);
37
+ if (!output) return [];
38
+ const worktrees = [];
39
+ let current = {};
40
+ for (const line of output.split("\n")) {
41
+ if (line.startsWith("worktree ")) {
42
+ if (current.path) {
43
+ worktrees.push(current);
44
+ }
45
+ current = { path: line.slice(9), isBare: false, isMain: false };
46
+ } else if (line.startsWith("HEAD ")) {
47
+ current.commit = line.slice(5);
48
+ } else if (line.startsWith("branch ")) {
49
+ current.branch = line.slice(7).replace("refs/heads/", "");
50
+ } else if (line === "bare") {
51
+ current.isBare = true;
52
+ } else if (line === "") {
53
+ if (worktrees.length === 0 && current.path) {
54
+ current.isMain = true;
55
+ }
56
+ }
57
+ }
58
+ if (current.path) {
59
+ if (worktrees.length === 0) {
60
+ current.isMain = true;
61
+ }
62
+ worktrees.push(current);
63
+ }
64
+ return worktrees;
65
+ }
66
+ function createWorktree(path, branch, options, cwd) {
67
+ const args = ["worktree", "add"];
68
+ if (options?.newBranch) {
69
+ args.push("-b", branch);
70
+ args.push(path);
71
+ if (options.baseBranch) {
72
+ args.push(options.baseBranch);
73
+ }
74
+ } else {
75
+ args.push(path, branch);
76
+ }
77
+ git(args, cwd);
78
+ }
79
+ function removeWorktree(path, force, cwd) {
80
+ const args = ["worktree", "remove"];
81
+ if (force) {
82
+ args.push("--force");
83
+ }
84
+ args.push(path);
85
+ git(args, cwd);
86
+ }
87
+ function listBranches(cwd) {
88
+ const output = git(["branch", "--format=%(refname:short)"], cwd);
89
+ return output.split("\n").filter(Boolean);
90
+ }
91
+ function branchExists(branch, cwd) {
92
+ try {
93
+ git(["rev-parse", "--verify", branch], cwd);
94
+ return true;
95
+ } catch {
96
+ return false;
97
+ }
98
+ }
99
+ const createCommand = new Command("create").alias("add").description("Create a new worktree").argument("[name]", "Name for the worktree directory").option("-b, --branch <branch>", "Branch to checkout (or create with -n)").option("-n, --new", "Create a new branch").action(async (name, options) => {
100
+ try {
101
+ const repoRoot = getRepoRoot();
102
+ const config = await loadConfig(repoRoot);
103
+ const worktreeConfig = config?.worktree ?? {};
104
+ const currentBranch = getCurrentBranch(repoRoot);
105
+ const branches = listBranches(repoRoot);
106
+ const existingWorktrees = listWorktrees(repoRoot);
107
+ const existingPaths = new Set(existingWorktrees.map((w) => w.path));
108
+ let branch = options.branch;
109
+ let isNewBranch = options.new ?? false;
110
+ if (!branch) {
111
+ const branchAction = await select({
112
+ message: "What do you want to do?",
113
+ choices: [
114
+ { name: "Create a new branch", value: "new" },
115
+ { name: "Checkout existing branch", value: "existing" }
116
+ ]
117
+ });
118
+ if (branchAction === "new") {
119
+ isNewBranch = true;
120
+ branch = await input({
121
+ message: "New branch name:",
122
+ validate: (value) => {
123
+ if (!value.trim()) return "Branch name is required";
124
+ if (branchExists(value, repoRoot)) return "Branch already exists";
125
+ return true;
126
+ }
127
+ });
128
+ } else {
129
+ const worktreeBranches = new Set(
130
+ existingWorktrees.map((w) => w.branch).filter(Boolean)
131
+ );
132
+ const availableBranches = branches.filter(
133
+ (b) => !worktreeBranches.has(b)
134
+ );
135
+ if (availableBranches.length === 0) {
136
+ console.log(pc.yellow("All branches already have worktrees"));
137
+ return;
138
+ }
139
+ branch = await select({
140
+ message: "Select branch:",
141
+ choices: availableBranches.map((b) => ({
142
+ name: b === currentBranch ? `${b} (current)` : b,
143
+ value: b
144
+ }))
145
+ });
146
+ }
147
+ }
148
+ let worktreeName = name;
149
+ if (!worktreeName) {
150
+ const defaultName = branch.replace(/\//g, "-");
151
+ worktreeName = await input({
152
+ message: "Worktree directory name:",
153
+ default: defaultName,
154
+ validate: (value) => {
155
+ if (!value.trim()) return "Name is required";
156
+ return true;
157
+ }
158
+ });
159
+ }
160
+ const baseDir = worktreeConfig.baseDir ?? "../";
161
+ const repoName = basename(repoRoot);
162
+ const worktreePath = resolve(repoRoot, baseDir, `${repoName}-${worktreeName}`);
163
+ if (existingPaths.has(worktreePath) || existsSync(worktreePath)) {
164
+ console.error(pc.red(`Path already exists: ${worktreePath}`));
165
+ process.exit(1);
166
+ }
167
+ console.log(pc.dim(`Creating worktree at ${worktreePath}...`));
168
+ createWorktree(
169
+ worktreePath,
170
+ branch,
171
+ { newBranch: isNewBranch, baseBranch: currentBranch },
172
+ repoRoot
173
+ );
174
+ console.log(pc.green(`✓ Created worktree for branch ${pc.bold(branch)}`));
175
+ if (worktreeConfig.copyFiles?.length) {
176
+ console.log(pc.dim("Copying files..."));
177
+ for (const pattern of worktreeConfig.copyFiles) {
178
+ const files = await glob(pattern, { cwd: repoRoot, nodir: true });
179
+ for (const file of files) {
180
+ const src = resolve(repoRoot, file);
181
+ const dest = resolve(worktreePath, file);
182
+ const destDir = resolve(dest, "..");
183
+ if (!existsSync(destDir)) {
184
+ mkdirSync(destDir, { recursive: true });
185
+ }
186
+ if (existsSync(src)) {
187
+ copyFileSync(src, dest);
188
+ console.log(pc.dim(` Copied ${file}`));
189
+ }
190
+ }
191
+ }
192
+ }
193
+ if (worktreeConfig.postCreate) {
194
+ const shouldRun = await confirm({
195
+ message: `Run "${worktreeConfig.postCreate}"?`,
196
+ default: true
197
+ });
198
+ if (shouldRun) {
199
+ console.log(pc.dim(`Running: ${worktreeConfig.postCreate}`));
200
+ try {
201
+ execSync(worktreeConfig.postCreate, {
202
+ cwd: worktreePath,
203
+ stdio: "inherit"
204
+ });
205
+ console.log(pc.green("✓ Post-create command completed"));
206
+ } catch {
207
+ console.log(pc.yellow("⚠ Post-create command failed"));
208
+ }
209
+ }
210
+ }
211
+ console.log();
212
+ console.log(pc.green("✓ Worktree ready!"));
213
+ console.log(pc.dim(` cd ${worktreePath}`));
214
+ } catch (error) {
215
+ if (error instanceof Error) {
216
+ if (error.name === "ExitPromptError") {
217
+ return;
218
+ }
219
+ console.error(pc.red(error.message));
220
+ }
221
+ process.exit(1);
222
+ }
223
+ });
224
+ const listCommand = new Command("list").alias("ls").description("List all worktrees").option("--json", "Output in JSON format").action(async (options) => {
225
+ try {
226
+ const repoRoot = getRepoRoot();
227
+ const worktrees = listWorktrees(repoRoot);
228
+ if (options.json) {
229
+ console.log(JSON.stringify(worktrees, null, 2));
230
+ return;
231
+ }
232
+ if (worktrees.length === 0) {
233
+ console.log(pc.yellow("No worktrees found"));
234
+ return;
235
+ }
236
+ console.log(pc.bold("Worktrees:\n"));
237
+ for (const wt of worktrees) {
238
+ const relativePath = relative(process.cwd(), wt.path) || ".";
239
+ const branchDisplay = wt.branch || pc.dim("(detached)");
240
+ const mainLabel = wt.isMain ? pc.cyan(" [main]") : "";
241
+ console.log(` ${pc.green(relativePath)}${mainLabel}`);
242
+ console.log(` Branch: ${branchDisplay}`);
243
+ console.log(` Commit: ${pc.dim(wt.commit?.slice(0, 7) || "unknown")}`);
244
+ console.log();
245
+ }
246
+ } catch (error) {
247
+ if (error instanceof Error) {
248
+ console.error(pc.red(error.message));
249
+ }
250
+ process.exit(1);
251
+ }
252
+ });
253
+ const removeCommand = new Command("remove").alias("rm").description("Remove a worktree").argument("[path]", "Path to the worktree to remove").option("-f, --force", "Force removal even if worktree is dirty").option("-D, --delete-branch", "Also delete the branch").action(async (pathArg, options) => {
254
+ try {
255
+ const repoRoot = getRepoRoot();
256
+ const worktrees = listWorktrees(repoRoot);
257
+ const removableWorktrees = worktrees.filter((w) => !w.isMain);
258
+ if (removableWorktrees.length === 0) {
259
+ console.log(pc.yellow("No removable worktrees found"));
260
+ return;
261
+ }
262
+ let targetPath = pathArg;
263
+ let targetWorktree = removableWorktrees.find((w) => w.path === targetPath);
264
+ if (!targetPath) {
265
+ const selected = await select({
266
+ message: "Select worktree to remove:",
267
+ choices: removableWorktrees.map((wt) => {
268
+ const relativePath2 = relative(process.cwd(), wt.path) || wt.path;
269
+ return {
270
+ name: `${relativePath2} (${wt.branch || "detached"})`,
271
+ value: wt
272
+ };
273
+ })
274
+ });
275
+ targetWorktree = selected;
276
+ targetPath = selected.path;
277
+ }
278
+ if (!targetWorktree) {
279
+ targetWorktree = removableWorktrees.find((w) => {
280
+ const rel = relative(process.cwd(), w.path);
281
+ return rel === targetPath || w.path.endsWith(targetPath);
282
+ });
283
+ if (!targetWorktree) {
284
+ console.error(pc.red(`Worktree not found: ${targetPath}`));
285
+ process.exit(1);
286
+ }
287
+ }
288
+ const relativePath = relative(process.cwd(), targetWorktree.path);
289
+ const shouldRemove = await confirm({
290
+ message: `Remove worktree ${pc.bold(relativePath)}?`,
291
+ default: false
292
+ });
293
+ if (!shouldRemove) {
294
+ console.log(pc.dim("Cancelled"));
295
+ return;
296
+ }
297
+ console.log(pc.dim("Removing worktree..."));
298
+ removeWorktree(targetWorktree.path, options.force, repoRoot);
299
+ console.log(pc.green(`✓ Removed worktree ${relativePath}`));
300
+ if (options.deleteBranch && targetWorktree.branch) {
301
+ const shouldDeleteBranch = await confirm({
302
+ message: `Also delete branch ${pc.bold(targetWorktree.branch)}?`,
303
+ default: false
304
+ });
305
+ if (shouldDeleteBranch) {
306
+ try {
307
+ git(["branch", "-D", targetWorktree.branch], repoRoot);
308
+ console.log(pc.green(`✓ Deleted branch ${targetWorktree.branch}`));
309
+ } catch (error) {
310
+ if (error instanceof Error) {
311
+ console.log(pc.yellow(`⚠ Could not delete branch: ${error.message}`));
312
+ }
313
+ }
314
+ }
315
+ }
316
+ } catch (error) {
317
+ if (error instanceof Error) {
318
+ if (error.name === "ExitPromptError") {
319
+ return;
320
+ }
321
+ console.error(pc.red(error.message));
322
+ }
323
+ process.exit(1);
324
+ }
325
+ });
326
+ const worktreePlugin = {
327
+ name: "Worktree",
328
+ description: "Manage git worktrees",
329
+ command: "worktree",
330
+ aliases: ["wt"],
331
+ register(program) {
332
+ const worktreeCmd = program.command("worktree").alias("wt").description("Manage git worktrees");
333
+ worktreeCmd.addCommand(createCommand);
334
+ worktreeCmd.addCommand(listCommand);
335
+ worktreeCmd.addCommand(removeCommand);
336
+ worktreeCmd.action(async () => {
337
+ await createCommand.parseAsync([], { from: "user" });
338
+ });
339
+ }
340
+ };
341
+ export {
342
+ branchExists,
343
+ createWorktree,
344
+ getCurrentBranch,
345
+ getRepoRoot,
346
+ git,
347
+ isClean,
348
+ listBranches,
349
+ listWorktrees,
350
+ removeWorktree,
351
+ worktreePlugin
352
+ };
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ import '../types.js';
3
+ export declare const createCommand: Command;
4
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,OAAO,aAAa,CAAC;AAOrB,eAAO,MAAM,aAAa,SAyJtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const listCommand: Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,WAAW,SAqCpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const removeCommand: Command;
3
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,eAAO,MAAM,aAAa,SA+FtB,CAAC"}
@@ -0,0 +1,62 @@
1
+ export interface Worktree {
2
+ path: string;
3
+ branch: string;
4
+ commit: string;
5
+ isBare: boolean;
6
+ isMain: boolean;
7
+ }
8
+ export interface GitError extends Error {
9
+ stderr?: string;
10
+ }
11
+ /**
12
+ * Execute a git command and return stdout
13
+ */
14
+ export declare function git(args: string[], cwd?: string): string;
15
+ /**
16
+ * Execute a git command asynchronously with live output
17
+ */
18
+ export declare function gitAsync(args: string[], cwd?: string): Promise<{
19
+ code: number;
20
+ stdout: string;
21
+ stderr: string;
22
+ }>;
23
+ /**
24
+ * Get the root directory of the git repository
25
+ */
26
+ export declare function getRepoRoot(cwd?: string): string;
27
+ /**
28
+ * Get the current branch name
29
+ */
30
+ export declare function getCurrentBranch(cwd?: string): string;
31
+ /**
32
+ * Check if working directory is clean
33
+ */
34
+ export declare function isClean(cwd?: string): boolean;
35
+ /**
36
+ * List all worktrees
37
+ */
38
+ export declare function listWorktrees(cwd?: string): Worktree[];
39
+ /**
40
+ * Create a new worktree
41
+ */
42
+ export declare function createWorktree(path: string, branch: string, options?: {
43
+ newBranch?: boolean;
44
+ baseBranch?: string;
45
+ }, cwd?: string): void;
46
+ /**
47
+ * Remove a worktree
48
+ */
49
+ export declare function removeWorktree(path: string, force?: boolean, cwd?: string): void;
50
+ /**
51
+ * Get list of local branches
52
+ */
53
+ export declare function listBranches(cwd?: string): string[];
54
+ /**
55
+ * Check if a branch exists
56
+ */
57
+ export declare function branchExists(branch: string, cwd?: string): boolean;
58
+ /**
59
+ * Check if path is inside a git worktree
60
+ */
61
+ export declare function isWorktree(path: string): boolean;
62
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAS,SAAQ,KAAK;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAexD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAG7C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmCtD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EACtD,GAAG,CAAC,EAAE,MAAM,GACX,IAAI,CAcN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAOhF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQhD"}
@@ -0,0 +1,3 @@
1
+ import type { PikPlugin } from '@lsst/pik-core';
2
+ export declare const worktreePlugin: PikPlugin;
3
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/lib/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKhD,eAAO,MAAM,cAAc,EAAE,SAsB5B,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Configuration for the worktree plugin
3
+ */
4
+ export interface WorktreeConfig {
5
+ /** Directory where worktrees will be created (relative to repo root, default: '../') */
6
+ baseDir?: string;
7
+ /** Files to copy to new worktrees (supports globs) */
8
+ copyFiles?: string[];
9
+ /** Command to run after creating worktree (e.g., 'npm install') */
10
+ postCreate?: string;
11
+ }
12
+ /**
13
+ * Extend PikConfig to include worktree plugin config
14
+ */
15
+ declare module '@lsst/pik-core' {
16
+ interface PikConfig {
17
+ worktree?: WorktreeConfig;
18
+ }
19
+ }
20
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,SAAS;QACjB,QAAQ,CAAC,EAAE,cAAc,CAAC;KAC3B;CACF"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@lsst/pik-plugin-worktree",
3
+ "version": "0.4.2",
4
+ "description": "Git worktree management plugin for pik CLI",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Yurii Tatar <lsst25@gmail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/lsst25/pik.git",
11
+ "directory": "packages/plugin-worktree"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ "./package.json": "./package.json",
18
+ ".": {
19
+ "@pik/source": "./src/index.ts",
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "!**/*.tsbuildinfo"
28
+ ],
29
+ "dependencies": {
30
+ "@lsst/pik-core": "*",
31
+ "@inquirer/prompts": "^8.1.0",
32
+ "commander": "^14.0.2",
33
+ "glob": "^10.5.0",
34
+ "picocolors": "^1.1.1"
35
+ }
36
+ }