@michael_magdy/mic-drop 0.1.0 → 0.1.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/dist/index.js +172 -60
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -26,9 +26,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/index.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
|
+
// package.json
|
|
30
|
+
var version = "0.1.2";
|
|
31
|
+
|
|
29
32
|
// src/commands/setup.ts
|
|
30
33
|
var import_prompts = require("@inquirer/prompts");
|
|
31
|
-
var
|
|
34
|
+
var import_path6 = __toESM(require("path"));
|
|
32
35
|
|
|
33
36
|
// src/config/credentials.ts
|
|
34
37
|
var import_keytar = __toESM(require("keytar"));
|
|
@@ -60,7 +63,9 @@ var ProjectConfigSchema = import_zod.z.object({
|
|
|
60
63
|
copyFiles: import_zod.z.array(import_zod.z.string()).default([]),
|
|
61
64
|
copyDirs: import_zod.z.array(import_zod.z.string()).default([]),
|
|
62
65
|
terminal: import_zod.z.string().default("warp"),
|
|
63
|
-
|
|
66
|
+
cliTool: import_zod.z.string().default("claude"),
|
|
67
|
+
cliCommand: import_zod.z.string().default("claude"),
|
|
68
|
+
cliFlags: import_zod.z.string().default("--permission-mode plan")
|
|
64
69
|
});
|
|
65
70
|
var PROJECT_CONFIG_DEFAULTS = {
|
|
66
71
|
baseBranch: "develop",
|
|
@@ -68,7 +73,9 @@ var PROJECT_CONFIG_DEFAULTS = {
|
|
|
68
73
|
copyFiles: [],
|
|
69
74
|
copyDirs: [],
|
|
70
75
|
terminal: "warp",
|
|
71
|
-
|
|
76
|
+
cliTool: "claude",
|
|
77
|
+
cliCommand: "claude",
|
|
78
|
+
cliFlags: "--permission-mode plan"
|
|
72
79
|
};
|
|
73
80
|
|
|
74
81
|
// src/config/projectConfig.ts
|
|
@@ -79,6 +86,12 @@ async function loadProjectConfig(repoRoot) {
|
|
|
79
86
|
const legacyPath = import_path.default.join(repoRoot, LEGACY_CONFIG);
|
|
80
87
|
if (import_fs.default.existsSync(jsonPath)) {
|
|
81
88
|
const raw = JSON.parse(import_fs.default.readFileSync(jsonPath, "utf-8"));
|
|
89
|
+
if ("claudeMode" in raw && !("cliTool" in raw)) {
|
|
90
|
+
raw.cliTool = "claude";
|
|
91
|
+
raw.cliCommand = "claude";
|
|
92
|
+
raw.cliFlags = raw.claudeMode;
|
|
93
|
+
delete raw.claudeMode;
|
|
94
|
+
}
|
|
82
95
|
const config = ProjectConfigSchema.parse(raw);
|
|
83
96
|
return { config, source: "json" };
|
|
84
97
|
}
|
|
@@ -115,16 +128,52 @@ function parseLegacyConf(content) {
|
|
|
115
128
|
partial[key] = value;
|
|
116
129
|
}
|
|
117
130
|
}
|
|
131
|
+
const legacyFlags = partial["CLAUDE_MODE"];
|
|
118
132
|
return ProjectConfigSchema.parse({
|
|
119
133
|
baseBranch: partial["BASE_BRANCH"],
|
|
120
134
|
worktreesDir: partial["WORKTREES_DIR"],
|
|
121
135
|
copyFiles: partial["COPY_FILES"],
|
|
122
136
|
copyDirs: partial["COPY_DIRS"],
|
|
123
137
|
terminal: partial["TERMINAL"],
|
|
124
|
-
|
|
138
|
+
cliTool: "claude",
|
|
139
|
+
cliCommand: "claude",
|
|
140
|
+
cliFlags: legacyFlags
|
|
125
141
|
});
|
|
126
142
|
}
|
|
127
143
|
|
|
144
|
+
// src/config/cliTools.ts
|
|
145
|
+
var CLI_TOOLS = [
|
|
146
|
+
{
|
|
147
|
+
id: "claude",
|
|
148
|
+
label: "Claude Code",
|
|
149
|
+
command: "claude",
|
|
150
|
+
defaultFlags: "--permission-mode plan"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: "gemini",
|
|
154
|
+
label: "Gemini CLI",
|
|
155
|
+
command: "gemini",
|
|
156
|
+
defaultFlags: ""
|
|
157
|
+
// default interactive mode (omit --yolo for safety)
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "codex",
|
|
161
|
+
label: "OpenAI Codex CLI",
|
|
162
|
+
command: "codex",
|
|
163
|
+
defaultFlags: "--approval-mode suggest"
|
|
164
|
+
// suggest-only, mirrors plan mode
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: "other",
|
|
168
|
+
label: "Other",
|
|
169
|
+
command: "",
|
|
170
|
+
defaultFlags: ""
|
|
171
|
+
}
|
|
172
|
+
];
|
|
173
|
+
function getCliTool(id) {
|
|
174
|
+
return CLI_TOOLS.find((t) => t.id === id);
|
|
175
|
+
}
|
|
176
|
+
|
|
128
177
|
// src/jira/adfParser.ts
|
|
129
178
|
function extractText(node) {
|
|
130
179
|
const parts = [];
|
|
@@ -274,18 +323,58 @@ function sleep(ms) {
|
|
|
274
323
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
275
324
|
}
|
|
276
325
|
|
|
277
|
-
// src/terminal/launchers/
|
|
326
|
+
// src/terminal/launchers/warp-windows.ts
|
|
327
|
+
var import_fs3 = __toESM(require("fs"));
|
|
328
|
+
var import_path3 = __toESM(require("path"));
|
|
278
329
|
var import_child_process2 = require("child_process");
|
|
330
|
+
var WarpWindowsLauncher = class {
|
|
331
|
+
name = "warp";
|
|
332
|
+
platform = ["win32"];
|
|
333
|
+
async isAvailable() {
|
|
334
|
+
try {
|
|
335
|
+
(0, import_child_process2.execSync)("where warp-terminal", { stdio: "ignore" });
|
|
336
|
+
return true;
|
|
337
|
+
} catch {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
async launch({ workingDirectory, command }) {
|
|
342
|
+
const scriptPath = import_path3.default.join(workingDirectory, ".start-claude.sh");
|
|
343
|
+
import_fs3.default.writeFileSync(scriptPath, `#!/bin/bash
|
|
344
|
+
${command}
|
|
345
|
+
`);
|
|
346
|
+
(0, import_child_process2.spawn)("warp-terminal", ["--working-directory", workingDirectory], {
|
|
347
|
+
detached: true,
|
|
348
|
+
stdio: "ignore",
|
|
349
|
+
shell: true
|
|
350
|
+
}).unref();
|
|
351
|
+
await sleep2(2e3);
|
|
352
|
+
const psScript = [
|
|
353
|
+
`Add-Type -AssemblyName System.Windows.Forms`,
|
|
354
|
+
`[System.Windows.Forms.SendKeys]::SendWait("bash .start-claude.sh{ENTER}")`
|
|
355
|
+
].join("; ");
|
|
356
|
+
(0, import_child_process2.spawn)("powershell", ["-NoProfile", "-Command", psScript], {
|
|
357
|
+
detached: true,
|
|
358
|
+
stdio: "ignore"
|
|
359
|
+
}).unref();
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
function sleep2(ms) {
|
|
363
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/terminal/launchers/iterm.ts
|
|
367
|
+
var import_child_process3 = require("child_process");
|
|
279
368
|
var ITermLauncher = class {
|
|
280
369
|
name = "iterm";
|
|
281
370
|
platform = ["darwin"];
|
|
282
371
|
async isAvailable() {
|
|
283
372
|
try {
|
|
284
|
-
(0,
|
|
373
|
+
(0, import_child_process3.execSync)("test -d '/Applications/iTerm.app'", { stdio: "ignore" });
|
|
285
374
|
return true;
|
|
286
375
|
} catch {
|
|
287
376
|
try {
|
|
288
|
-
(0,
|
|
377
|
+
(0, import_child_process3.execSync)("test -d '/Applications/iTerm2.app'", { stdio: "ignore" });
|
|
289
378
|
return true;
|
|
290
379
|
} catch {
|
|
291
380
|
return false;
|
|
@@ -303,12 +392,12 @@ tell application "iTerm"
|
|
|
303
392
|
write text "cd '${escapedDir}' && ${escapedCmd}"
|
|
304
393
|
end tell
|
|
305
394
|
end tell`;
|
|
306
|
-
(0,
|
|
395
|
+
(0, import_child_process3.spawn)("osascript", ["-e", script], { detached: true, stdio: "ignore" }).unref();
|
|
307
396
|
}
|
|
308
397
|
};
|
|
309
398
|
|
|
310
399
|
// src/terminal/launchers/terminal-app.ts
|
|
311
|
-
var
|
|
400
|
+
var import_child_process4 = require("child_process");
|
|
312
401
|
var TerminalAppLauncher = class {
|
|
313
402
|
name = "terminal";
|
|
314
403
|
platform = ["darwin"];
|
|
@@ -323,25 +412,25 @@ tell application "Terminal"
|
|
|
323
412
|
activate
|
|
324
413
|
do script "cd '${escapedDir}' && ${escapedCmd}"
|
|
325
414
|
end tell`;
|
|
326
|
-
(0,
|
|
415
|
+
(0, import_child_process4.spawn)("osascript", ["-e", script], { detached: true, stdio: "ignore" }).unref();
|
|
327
416
|
}
|
|
328
417
|
};
|
|
329
418
|
|
|
330
419
|
// src/terminal/launchers/gnome-terminal.ts
|
|
331
|
-
var
|
|
420
|
+
var import_child_process5 = require("child_process");
|
|
332
421
|
var GnomeTerminalLauncher = class {
|
|
333
422
|
name = "gnome-terminal";
|
|
334
423
|
platform = ["linux"];
|
|
335
424
|
async isAvailable() {
|
|
336
425
|
try {
|
|
337
|
-
(0,
|
|
426
|
+
(0, import_child_process5.execSync)("which gnome-terminal", { stdio: "ignore" });
|
|
338
427
|
return true;
|
|
339
428
|
} catch {
|
|
340
429
|
return false;
|
|
341
430
|
}
|
|
342
431
|
}
|
|
343
432
|
async launch({ workingDirectory, command }) {
|
|
344
|
-
(0,
|
|
433
|
+
(0, import_child_process5.spawn)(
|
|
345
434
|
"gnome-terminal",
|
|
346
435
|
["--working-directory", workingDirectory, "--", "bash", "-c", command],
|
|
347
436
|
{ detached: true, stdio: "ignore" }
|
|
@@ -350,20 +439,20 @@ var GnomeTerminalLauncher = class {
|
|
|
350
439
|
};
|
|
351
440
|
|
|
352
441
|
// src/terminal/launchers/konsole.ts
|
|
353
|
-
var
|
|
442
|
+
var import_child_process6 = require("child_process");
|
|
354
443
|
var KonsoleLauncher = class {
|
|
355
444
|
name = "konsole";
|
|
356
445
|
platform = ["linux"];
|
|
357
446
|
async isAvailable() {
|
|
358
447
|
try {
|
|
359
|
-
(0,
|
|
448
|
+
(0, import_child_process6.execSync)("which konsole", { stdio: "ignore" });
|
|
360
449
|
return true;
|
|
361
450
|
} catch {
|
|
362
451
|
return false;
|
|
363
452
|
}
|
|
364
453
|
}
|
|
365
454
|
async launch({ workingDirectory, command }) {
|
|
366
|
-
(0,
|
|
455
|
+
(0, import_child_process6.spawn)("konsole", ["--workdir", workingDirectory, "-e", command], {
|
|
367
456
|
detached: true,
|
|
368
457
|
stdio: "ignore"
|
|
369
458
|
}).unref();
|
|
@@ -371,20 +460,20 @@ var KonsoleLauncher = class {
|
|
|
371
460
|
};
|
|
372
461
|
|
|
373
462
|
// src/terminal/launchers/windows-terminal.ts
|
|
374
|
-
var
|
|
463
|
+
var import_child_process7 = require("child_process");
|
|
375
464
|
var WindowsTerminalLauncher = class {
|
|
376
465
|
name = "windows-terminal";
|
|
377
466
|
platform = ["win32"];
|
|
378
467
|
async isAvailable() {
|
|
379
468
|
try {
|
|
380
|
-
(0,
|
|
469
|
+
(0, import_child_process7.execSync)("where wt", { stdio: "ignore" });
|
|
381
470
|
return true;
|
|
382
471
|
} catch {
|
|
383
472
|
return false;
|
|
384
473
|
}
|
|
385
474
|
}
|
|
386
475
|
async launch({ workingDirectory, command }) {
|
|
387
|
-
(0,
|
|
476
|
+
(0, import_child_process7.spawn)("wt", ["-d", workingDirectory, "powershell", "-Command", command], {
|
|
388
477
|
detached: true,
|
|
389
478
|
stdio: "ignore"
|
|
390
479
|
}).unref();
|
|
@@ -394,6 +483,7 @@ var WindowsTerminalLauncher = class {
|
|
|
394
483
|
// src/terminal/registry.ts
|
|
395
484
|
var ALL_LAUNCHERS = [
|
|
396
485
|
new WarpLauncher(),
|
|
486
|
+
new WarpWindowsLauncher(),
|
|
397
487
|
new ITermLauncher(),
|
|
398
488
|
new TerminalAppLauncher(),
|
|
399
489
|
new GnomeTerminalLauncher(),
|
|
@@ -423,15 +513,15 @@ async function getAvailableLaunchers() {
|
|
|
423
513
|
}
|
|
424
514
|
|
|
425
515
|
// src/git/gitignore.ts
|
|
426
|
-
var
|
|
427
|
-
var
|
|
516
|
+
var import_fs4 = __toESM(require("fs"));
|
|
517
|
+
var import_path4 = __toESM(require("path"));
|
|
428
518
|
function ensureGitignoreEntry(repoRoot, entry) {
|
|
429
|
-
const gitignorePath =
|
|
519
|
+
const gitignorePath = import_path4.default.join(repoRoot, ".gitignore");
|
|
430
520
|
const entryNorm = entry.endsWith("/") ? entry : entry + "/";
|
|
431
521
|
const entryBase = entry.replace(/\/$/, "");
|
|
432
522
|
let existing = "";
|
|
433
|
-
if (
|
|
434
|
-
existing =
|
|
523
|
+
if (import_fs4.default.existsSync(gitignorePath)) {
|
|
524
|
+
existing = import_fs4.default.readFileSync(gitignorePath, "utf-8");
|
|
435
525
|
const lines = existing.split("\n");
|
|
436
526
|
for (const line of lines) {
|
|
437
527
|
const trimmed = line.trim();
|
|
@@ -441,12 +531,12 @@ function ensureGitignoreEntry(repoRoot, entry) {
|
|
|
441
531
|
}
|
|
442
532
|
}
|
|
443
533
|
const toAppend = existing.endsWith("\n") || existing === "" ? entryNorm + "\n" : "\n" + entryNorm + "\n";
|
|
444
|
-
|
|
534
|
+
import_fs4.default.appendFileSync(gitignorePath, toAppend, "utf-8");
|
|
445
535
|
}
|
|
446
536
|
|
|
447
537
|
// src/git/worktree.ts
|
|
448
|
-
var
|
|
449
|
-
var
|
|
538
|
+
var import_fs5 = __toESM(require("fs"));
|
|
539
|
+
var import_path5 = __toESM(require("path"));
|
|
450
540
|
var import_simple_git = __toESM(require("simple-git"));
|
|
451
541
|
var WorktreeExistsError = class extends Error {
|
|
452
542
|
constructor(targetDir) {
|
|
@@ -470,14 +560,14 @@ async function resolveRepoRoot(startDir) {
|
|
|
470
560
|
async function createWorktree(opts) {
|
|
471
561
|
const { repoRoot, targetDir, branchName, baseBranch } = opts;
|
|
472
562
|
const git = (0, import_simple_git.default)(repoRoot);
|
|
473
|
-
if (
|
|
563
|
+
if (import_fs5.default.existsSync(targetDir)) {
|
|
474
564
|
throw new WorktreeExistsError(targetDir);
|
|
475
565
|
}
|
|
476
566
|
await git.raw(["worktree", "prune"]);
|
|
477
567
|
await git.fetch("origin", baseBranch);
|
|
478
568
|
const branchSummary = await git.branch(["-a"]);
|
|
479
569
|
const branchExists = branchName in branchSummary.branches || `remotes/origin/${branchName}` in branchSummary.branches;
|
|
480
|
-
|
|
570
|
+
import_fs5.default.mkdirSync(import_path5.default.dirname(targetDir), { recursive: true });
|
|
481
571
|
if (branchExists) {
|
|
482
572
|
await git.raw(["worktree", "add", targetDir, branchName]);
|
|
483
573
|
} else {
|
|
@@ -500,34 +590,34 @@ async function createWorktree(opts) {
|
|
|
500
590
|
async function excludeFromWorktree(worktreeDir, entries) {
|
|
501
591
|
const git = (0, import_simple_git.default)(worktreeDir);
|
|
502
592
|
const gitDir = (await git.revparse(["--git-dir"])).trim();
|
|
503
|
-
const absoluteGitDir =
|
|
504
|
-
const excludePath =
|
|
505
|
-
|
|
506
|
-
const existing =
|
|
593
|
+
const absoluteGitDir = import_path5.default.isAbsolute(gitDir) ? gitDir : import_path5.default.join(worktreeDir, gitDir);
|
|
594
|
+
const excludePath = import_path5.default.join(absoluteGitDir, "info", "exclude");
|
|
595
|
+
import_fs5.default.mkdirSync(import_path5.default.dirname(excludePath), { recursive: true });
|
|
596
|
+
const existing = import_fs5.default.existsSync(excludePath) ? import_fs5.default.readFileSync(excludePath, "utf-8") : "";
|
|
507
597
|
const existingLines = existing.split("\n");
|
|
508
598
|
const toAdd = entries.filter((e) => !existingLines.includes(e));
|
|
509
599
|
if (toAdd.length > 0) {
|
|
510
|
-
|
|
600
|
+
import_fs5.default.appendFileSync(excludePath, toAdd.join("\n") + "\n", "utf-8");
|
|
511
601
|
}
|
|
512
602
|
}
|
|
513
603
|
function copyProjectFiles(repoRoot, targetDir, copyFiles, copyDirs) {
|
|
514
604
|
const copied = [];
|
|
515
605
|
const missing = [];
|
|
516
606
|
for (const file of copyFiles) {
|
|
517
|
-
const src =
|
|
518
|
-
const dest =
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
607
|
+
const src = import_path5.default.join(repoRoot, file);
|
|
608
|
+
const dest = import_path5.default.join(targetDir, file);
|
|
609
|
+
if (import_fs5.default.existsSync(src)) {
|
|
610
|
+
import_fs5.default.mkdirSync(import_path5.default.dirname(dest), { recursive: true });
|
|
611
|
+
import_fs5.default.copyFileSync(src, dest);
|
|
522
612
|
copied.push(file);
|
|
523
613
|
} else {
|
|
524
614
|
missing.push(file);
|
|
525
615
|
}
|
|
526
616
|
}
|
|
527
617
|
for (const dir of copyDirs) {
|
|
528
|
-
const src =
|
|
529
|
-
const dest =
|
|
530
|
-
if (
|
|
618
|
+
const src = import_path5.default.join(repoRoot, dir);
|
|
619
|
+
const dest = import_path5.default.join(targetDir, dir);
|
|
620
|
+
if (import_fs5.default.existsSync(src) && import_fs5.default.statSync(src).isDirectory()) {
|
|
531
621
|
copyDirRecursive(src, dest);
|
|
532
622
|
copied.push(dir + "/");
|
|
533
623
|
} else {
|
|
@@ -537,14 +627,14 @@ function copyProjectFiles(repoRoot, targetDir, copyFiles, copyDirs) {
|
|
|
537
627
|
return { copied, missing };
|
|
538
628
|
}
|
|
539
629
|
function copyDirRecursive(src, dest) {
|
|
540
|
-
|
|
541
|
-
for (const entry of
|
|
542
|
-
const srcPath =
|
|
543
|
-
const destPath =
|
|
630
|
+
import_fs5.default.mkdirSync(dest, { recursive: true });
|
|
631
|
+
for (const entry of import_fs5.default.readdirSync(src, { withFileTypes: true })) {
|
|
632
|
+
const srcPath = import_path5.default.join(src, entry.name);
|
|
633
|
+
const destPath = import_path5.default.join(dest, entry.name);
|
|
544
634
|
if (entry.isDirectory()) {
|
|
545
635
|
copyDirRecursive(srcPath, destPath);
|
|
546
636
|
} else {
|
|
547
|
-
|
|
637
|
+
import_fs5.default.copyFileSync(srcPath, destPath);
|
|
548
638
|
}
|
|
549
639
|
}
|
|
550
640
|
}
|
|
@@ -657,9 +747,28 @@ async function runSetup() {
|
|
|
657
747
|
choices: terminalChoices,
|
|
658
748
|
default: available.find((l) => l.name === existing.terminal) ? existing.terminal : terminalChoices[0].value
|
|
659
749
|
}) : terminalChoices[0].value;
|
|
660
|
-
const
|
|
661
|
-
message: "
|
|
662
|
-
|
|
750
|
+
const cliToolId = await (0, import_prompts.select)({
|
|
751
|
+
message: "AI CLI tool:",
|
|
752
|
+
choices: CLI_TOOLS.map((t) => ({ name: t.label, value: t.id })),
|
|
753
|
+
default: existing.cliTool
|
|
754
|
+
});
|
|
755
|
+
const toolDef = getCliTool(cliToolId);
|
|
756
|
+
let cliCommand;
|
|
757
|
+
if (cliToolId === "other") {
|
|
758
|
+
console.log(' Enter the CLI command to run (e.g. "my-ai-tool").');
|
|
759
|
+
console.log(' It will be invoked as: <command> <flags> "$(cat .ticket.md)"');
|
|
760
|
+
cliCommand = await (0, import_prompts.input)({
|
|
761
|
+
message: "CLI command:",
|
|
762
|
+
default: existing.cliTool === "other" ? existing.cliCommand : "",
|
|
763
|
+
validate: (v) => v.trim() ? true : "Required"
|
|
764
|
+
});
|
|
765
|
+
} else {
|
|
766
|
+
cliCommand = toolDef.command;
|
|
767
|
+
}
|
|
768
|
+
const flagsDefault = toolDef.defaultFlags !== "" ? toolDef.defaultFlags : existing.cliTool === cliToolId ? existing.cliFlags : "";
|
|
769
|
+
const cliFlags = await (0, import_prompts.input)({
|
|
770
|
+
message: `${cliToolId === "other" ? "CLI" : toolDef.label} flags:`,
|
|
771
|
+
default: flagsDefault
|
|
663
772
|
});
|
|
664
773
|
const parseList = (raw) => raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
665
774
|
const newConfig = {
|
|
@@ -668,18 +777,20 @@ async function runSetup() {
|
|
|
668
777
|
copyFiles: parseList(copyFilesRaw),
|
|
669
778
|
copyDirs: parseList(copyDirsRaw),
|
|
670
779
|
terminal,
|
|
671
|
-
|
|
780
|
+
cliTool: cliToolId,
|
|
781
|
+
cliCommand: cliCommand.trim(),
|
|
782
|
+
cliFlags: cliFlags.trim()
|
|
672
783
|
};
|
|
673
784
|
saveProjectConfig(repoRoot, newConfig);
|
|
674
|
-
logger.success(`Config written to ${
|
|
785
|
+
logger.success(`Config written to ${import_path6.default.join(repoRoot, ".worktree.json")}`);
|
|
675
786
|
ensureGitignoreEntry(repoRoot, newConfig.worktreesDir);
|
|
676
787
|
logger.success(`.gitignore updated with ${newConfig.worktreesDir}/`);
|
|
677
788
|
console.log("\nSetup complete. Run: mic-drop PROJ-123\n");
|
|
678
789
|
}
|
|
679
790
|
|
|
680
791
|
// src/commands/run.ts
|
|
681
|
-
var
|
|
682
|
-
var
|
|
792
|
+
var import_path7 = __toESM(require("path"));
|
|
793
|
+
var import_fs6 = __toESM(require("fs"));
|
|
683
794
|
|
|
684
795
|
// src/utils/slugify.ts
|
|
685
796
|
var MAX_DESC_LENGTH = 60;
|
|
@@ -733,8 +844,8 @@ async function runTicket(issueKey, opts) {
|
|
|
733
844
|
});
|
|
734
845
|
logger.detail("Title", issue.title);
|
|
735
846
|
const branchName = buildBranchName(issueKey, issue.title);
|
|
736
|
-
const worktreesRoot =
|
|
737
|
-
const targetDir =
|
|
847
|
+
const worktreesRoot = import_path7.default.isAbsolute(config.worktreesDir) ? config.worktreesDir : import_path7.default.join(repoRoot, config.worktreesDir);
|
|
848
|
+
const targetDir = import_path7.default.join(worktreesRoot, issueKey);
|
|
738
849
|
logger.step("Preparing worktree...");
|
|
739
850
|
logger.detail("Branch", branchName);
|
|
740
851
|
logger.detail("Base", `origin/${config.baseBranch}`);
|
|
@@ -771,13 +882,14 @@ async function runTicket(issueKey, opts) {
|
|
|
771
882
|
for (const f of missing) logger.warn(`Not found, skipped: ${f}`);
|
|
772
883
|
}
|
|
773
884
|
const ticketContent = formatTicketFile(issue, config.baseBranch);
|
|
774
|
-
const ticketFile =
|
|
775
|
-
|
|
885
|
+
const ticketFile = import_path7.default.join(targetDir, ".ticket.md");
|
|
886
|
+
import_fs6.default.writeFileSync(ticketFile, ticketContent, "utf-8");
|
|
776
887
|
logger.success("Wrote .ticket.md");
|
|
777
888
|
await excludeFromWorktree(targetDir, [".ticket.md", ".start-claude.sh"]);
|
|
778
889
|
ensureGitignoreEntry(repoRoot, config.worktreesDir);
|
|
779
890
|
logger.success("Updated .gitignore");
|
|
780
|
-
const
|
|
891
|
+
const flags = config.cliFlags.trim();
|
|
892
|
+
const claudeCommand = flags ? `${config.cliCommand} ${flags} "$(cat .ticket.md)"` : `${config.cliCommand} "$(cat .ticket.md)"`;
|
|
781
893
|
logger.step("Launching terminal...");
|
|
782
894
|
const launcher = getLauncher(config.terminal);
|
|
783
895
|
logger.detail("Terminal", launcher.name);
|
|
@@ -793,7 +905,7 @@ async function runTicket(issueKey, opts) {
|
|
|
793
905
|
|
|
794
906
|
// src/index.ts
|
|
795
907
|
var program = new import_commander.Command();
|
|
796
|
-
program.name("mic-drop").description("Turn a Jira ticket into an isolated git worktree with Claude Code \u2014 in one command.").version(
|
|
908
|
+
program.name("mic-drop").description("Turn a Jira ticket into an isolated git worktree with Claude Code \u2014 in one command.").version(version);
|
|
797
909
|
program.command("setup").description("Interactive setup wizard for Jira credentials and project configuration").action(async () => {
|
|
798
910
|
await runSetup();
|
|
799
911
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michael_magdy/mic-drop",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"author": "Michael Magdy",
|
|
5
5
|
"description": "Turn a Jira ticket into an isolated git worktree with Claude Code running automatically — in one command.",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -19,7 +19,14 @@
|
|
|
19
19
|
"engines": {
|
|
20
20
|
"node": ">=18.0.0"
|
|
21
21
|
},
|
|
22
|
-
"keywords": [
|
|
22
|
+
"keywords": [
|
|
23
|
+
"jira",
|
|
24
|
+
"git",
|
|
25
|
+
"worktree",
|
|
26
|
+
"claude",
|
|
27
|
+
"cli",
|
|
28
|
+
"ai"
|
|
29
|
+
],
|
|
23
30
|
"license": "MIT",
|
|
24
31
|
"files": [
|
|
25
32
|
"dist"
|