vibe-cokit 0.1.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/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # vibe-cokit (vk)
2
+
3
+ A toolkit for interacting with Claude Code.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun install -g vibe-cokit
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ # Initialize vibe-cokit for current project
15
+ vk init
16
+
17
+ # Show help
18
+ vk --help
19
+ ```
20
+
21
+ ## Development
22
+
23
+ ```bash
24
+ bun install
25
+ bun run build
26
+ bun test
27
+ ```
package/bin/vk.cjs ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ const { execFileSync } = require('child_process')
3
+ const { resolve } = require('path')
4
+
5
+ try {
6
+ execFileSync('bun', [resolve(__dirname, '../dist/cli.js'), ...process.argv.slice(2)], {
7
+ stdio: 'inherit'
8
+ })
9
+ } catch (err) {
10
+ if (err.status != null) process.exit(err.status)
11
+ console.error('bun is required to run vibe-cokit. Install: https://bun.sh')
12
+ process.exit(1)
13
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,720 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // node_modules/cac/dist/index.mjs
5
+ import { EventEmitter } from "events";
6
+ function toArr(any) {
7
+ return any == null ? [] : Array.isArray(any) ? any : [any];
8
+ }
9
+ function toVal(out, key, val, opts) {
10
+ var x, old = out[key], nxt = ~opts.string.indexOf(key) ? val == null || val === true ? "" : String(val) : typeof val === "boolean" ? val : ~opts.boolean.indexOf(key) ? val === "false" ? false : val === "true" || (out._.push((x = +val, x * 0 === 0) ? x : val), !!val) : (x = +val, x * 0 === 0) ? x : val;
11
+ out[key] = old == null ? nxt : Array.isArray(old) ? old.concat(nxt) : [old, nxt];
12
+ }
13
+ function mri2(args, opts) {
14
+ args = args || [];
15
+ opts = opts || {};
16
+ var k, arr, arg, name, val, out = { _: [] };
17
+ var i = 0, j = 0, idx = 0, len = args.length;
18
+ const alibi = opts.alias !== undefined;
19
+ const strict = opts.unknown !== undefined;
20
+ const defaults = opts.default !== undefined;
21
+ opts.alias = opts.alias || {};
22
+ opts.string = toArr(opts.string);
23
+ opts.boolean = toArr(opts.boolean);
24
+ if (alibi) {
25
+ for (k in opts.alias) {
26
+ arr = opts.alias[k] = toArr(opts.alias[k]);
27
+ for (i = 0;i < arr.length; i++) {
28
+ (opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
29
+ }
30
+ }
31
+ }
32
+ for (i = opts.boolean.length;i-- > 0; ) {
33
+ arr = opts.alias[opts.boolean[i]] || [];
34
+ for (j = arr.length;j-- > 0; )
35
+ opts.boolean.push(arr[j]);
36
+ }
37
+ for (i = opts.string.length;i-- > 0; ) {
38
+ arr = opts.alias[opts.string[i]] || [];
39
+ for (j = arr.length;j-- > 0; )
40
+ opts.string.push(arr[j]);
41
+ }
42
+ if (defaults) {
43
+ for (k in opts.default) {
44
+ name = typeof opts.default[k];
45
+ arr = opts.alias[k] = opts.alias[k] || [];
46
+ if (opts[name] !== undefined) {
47
+ opts[name].push(k);
48
+ for (i = 0;i < arr.length; i++) {
49
+ opts[name].push(arr[i]);
50
+ }
51
+ }
52
+ }
53
+ }
54
+ const keys = strict ? Object.keys(opts.alias) : [];
55
+ for (i = 0;i < len; i++) {
56
+ arg = args[i];
57
+ if (arg === "--") {
58
+ out._ = out._.concat(args.slice(++i));
59
+ break;
60
+ }
61
+ for (j = 0;j < arg.length; j++) {
62
+ if (arg.charCodeAt(j) !== 45)
63
+ break;
64
+ }
65
+ if (j === 0) {
66
+ out._.push(arg);
67
+ } else if (arg.substring(j, j + 3) === "no-") {
68
+ name = arg.substring(j + 3);
69
+ if (strict && !~keys.indexOf(name)) {
70
+ return opts.unknown(arg);
71
+ }
72
+ out[name] = false;
73
+ } else {
74
+ for (idx = j + 1;idx < arg.length; idx++) {
75
+ if (arg.charCodeAt(idx) === 61)
76
+ break;
77
+ }
78
+ name = arg.substring(j, idx);
79
+ val = arg.substring(++idx) || (i + 1 === len || ("" + args[i + 1]).charCodeAt(0) === 45 || args[++i]);
80
+ arr = j === 2 ? [name] : name;
81
+ for (idx = 0;idx < arr.length; idx++) {
82
+ name = arr[idx];
83
+ if (strict && !~keys.indexOf(name))
84
+ return opts.unknown("-".repeat(j) + name);
85
+ toVal(out, name, idx + 1 < arr.length || val, opts);
86
+ }
87
+ }
88
+ }
89
+ if (defaults) {
90
+ for (k in opts.default) {
91
+ if (out[k] === undefined) {
92
+ out[k] = opts.default[k];
93
+ }
94
+ }
95
+ }
96
+ if (alibi) {
97
+ for (k in out) {
98
+ arr = opts.alias[k] || [];
99
+ while (arr.length > 0) {
100
+ out[arr.shift()] = out[k];
101
+ }
102
+ }
103
+ }
104
+ return out;
105
+ }
106
+ var removeBrackets = (v) => v.replace(/[<[].+/, "").trim();
107
+ var findAllBrackets = (v) => {
108
+ const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
109
+ const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
110
+ const res = [];
111
+ const parse = (match) => {
112
+ let variadic = false;
113
+ let value = match[1];
114
+ if (value.startsWith("...")) {
115
+ value = value.slice(3);
116
+ variadic = true;
117
+ }
118
+ return {
119
+ required: match[0].startsWith("<"),
120
+ value,
121
+ variadic
122
+ };
123
+ };
124
+ let angledMatch;
125
+ while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
126
+ res.push(parse(angledMatch));
127
+ }
128
+ let squareMatch;
129
+ while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
130
+ res.push(parse(squareMatch));
131
+ }
132
+ return res;
133
+ };
134
+ var getMriOptions = (options) => {
135
+ const result = { alias: {}, boolean: [] };
136
+ for (const [index, option] of options.entries()) {
137
+ if (option.names.length > 1) {
138
+ result.alias[option.names[0]] = option.names.slice(1);
139
+ }
140
+ if (option.isBoolean) {
141
+ if (option.negated) {
142
+ const hasStringTypeOption = options.some((o, i) => {
143
+ return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
144
+ });
145
+ if (!hasStringTypeOption) {
146
+ result.boolean.push(option.names[0]);
147
+ }
148
+ } else {
149
+ result.boolean.push(option.names[0]);
150
+ }
151
+ }
152
+ }
153
+ return result;
154
+ };
155
+ var findLongest = (arr) => {
156
+ return arr.sort((a, b) => {
157
+ return a.length > b.length ? -1 : 1;
158
+ })[0];
159
+ };
160
+ var padRight = (str, length) => {
161
+ return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
162
+ };
163
+ var camelcase = (input) => {
164
+ return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
165
+ return p1 + p2.toUpperCase();
166
+ });
167
+ };
168
+ var setDotProp = (obj, keys, val) => {
169
+ let i = 0;
170
+ let length = keys.length;
171
+ let t = obj;
172
+ let x;
173
+ for (;i < length; ++i) {
174
+ x = t[keys[i]];
175
+ t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf(".") || !(+keys[i + 1] > -1) ? {} : [];
176
+ }
177
+ };
178
+ var setByType = (obj, transforms) => {
179
+ for (const key of Object.keys(transforms)) {
180
+ const transform = transforms[key];
181
+ if (transform.shouldTransform) {
182
+ obj[key] = Array.prototype.concat.call([], obj[key]);
183
+ if (typeof transform.transformFunction === "function") {
184
+ obj[key] = obj[key].map(transform.transformFunction);
185
+ }
186
+ }
187
+ }
188
+ };
189
+ var getFileName = (input) => {
190
+ const m = /([^\\\/]+)$/.exec(input);
191
+ return m ? m[1] : "";
192
+ };
193
+ var camelcaseOptionName = (name) => {
194
+ return name.split(".").map((v, i) => {
195
+ return i === 0 ? camelcase(v) : v;
196
+ }).join(".");
197
+ };
198
+
199
+ class CACError extends Error {
200
+ constructor(message) {
201
+ super(message);
202
+ this.name = this.constructor.name;
203
+ if (typeof Error.captureStackTrace === "function") {
204
+ Error.captureStackTrace(this, this.constructor);
205
+ } else {
206
+ this.stack = new Error(message).stack;
207
+ }
208
+ }
209
+ }
210
+
211
+ class Option {
212
+ constructor(rawName, description, config) {
213
+ this.rawName = rawName;
214
+ this.description = description;
215
+ this.config = Object.assign({}, config);
216
+ rawName = rawName.replace(/\.\*/g, "");
217
+ this.negated = false;
218
+ this.names = removeBrackets(rawName).split(",").map((v) => {
219
+ let name = v.trim().replace(/^-{1,2}/, "");
220
+ if (name.startsWith("no-")) {
221
+ this.negated = true;
222
+ name = name.replace(/^no-/, "");
223
+ }
224
+ return camelcaseOptionName(name);
225
+ }).sort((a, b) => a.length > b.length ? 1 : -1);
226
+ this.name = this.names[this.names.length - 1];
227
+ if (this.negated && this.config.default == null) {
228
+ this.config.default = true;
229
+ }
230
+ if (rawName.includes("<")) {
231
+ this.required = true;
232
+ } else if (rawName.includes("[")) {
233
+ this.required = false;
234
+ } else {
235
+ this.isBoolean = true;
236
+ }
237
+ }
238
+ }
239
+ var processArgs = process.argv;
240
+ var platformInfo = `${process.platform}-${process.arch} node-${process.version}`;
241
+
242
+ class Command {
243
+ constructor(rawName, description, config = {}, cli) {
244
+ this.rawName = rawName;
245
+ this.description = description;
246
+ this.config = config;
247
+ this.cli = cli;
248
+ this.options = [];
249
+ this.aliasNames = [];
250
+ this.name = removeBrackets(rawName);
251
+ this.args = findAllBrackets(rawName);
252
+ this.examples = [];
253
+ }
254
+ usage(text) {
255
+ this.usageText = text;
256
+ return this;
257
+ }
258
+ allowUnknownOptions() {
259
+ this.config.allowUnknownOptions = true;
260
+ return this;
261
+ }
262
+ ignoreOptionDefaultValue() {
263
+ this.config.ignoreOptionDefaultValue = true;
264
+ return this;
265
+ }
266
+ version(version, customFlags = "-v, --version") {
267
+ this.versionNumber = version;
268
+ this.option(customFlags, "Display version number");
269
+ return this;
270
+ }
271
+ example(example) {
272
+ this.examples.push(example);
273
+ return this;
274
+ }
275
+ option(rawName, description, config) {
276
+ const option = new Option(rawName, description, config);
277
+ this.options.push(option);
278
+ return this;
279
+ }
280
+ alias(name) {
281
+ this.aliasNames.push(name);
282
+ return this;
283
+ }
284
+ action(callback) {
285
+ this.commandAction = callback;
286
+ return this;
287
+ }
288
+ isMatched(name) {
289
+ return this.name === name || this.aliasNames.includes(name);
290
+ }
291
+ get isDefaultCommand() {
292
+ return this.name === "" || this.aliasNames.includes("!");
293
+ }
294
+ get isGlobalCommand() {
295
+ return this instanceof GlobalCommand;
296
+ }
297
+ hasOption(name) {
298
+ name = name.split(".")[0];
299
+ return this.options.find((option) => {
300
+ return option.names.includes(name);
301
+ });
302
+ }
303
+ outputHelp() {
304
+ const { name, commands } = this.cli;
305
+ const {
306
+ versionNumber,
307
+ options: globalOptions,
308
+ helpCallback
309
+ } = this.cli.globalCommand;
310
+ let sections = [
311
+ {
312
+ body: `${name}${versionNumber ? `/${versionNumber}` : ""}`
313
+ }
314
+ ];
315
+ sections.push({
316
+ title: "Usage",
317
+ body: ` $ ${name} ${this.usageText || this.rawName}`
318
+ });
319
+ const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
320
+ if (showCommands) {
321
+ const longestCommandName = findLongest(commands.map((command) => command.rawName));
322
+ sections.push({
323
+ title: "Commands",
324
+ body: commands.map((command) => {
325
+ return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
326
+ }).join(`
327
+ `)
328
+ });
329
+ sections.push({
330
+ title: `For more info, run any command with the \`--help\` flag`,
331
+ body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join(`
332
+ `)
333
+ });
334
+ }
335
+ let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
336
+ if (!this.isGlobalCommand && !this.isDefaultCommand) {
337
+ options = options.filter((option) => option.name !== "version");
338
+ }
339
+ if (options.length > 0) {
340
+ const longestOptionName = findLongest(options.map((option) => option.rawName));
341
+ sections.push({
342
+ title: "Options",
343
+ body: options.map((option) => {
344
+ return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === undefined ? "" : `(default: ${option.config.default})`}`;
345
+ }).join(`
346
+ `)
347
+ });
348
+ }
349
+ if (this.examples.length > 0) {
350
+ sections.push({
351
+ title: "Examples",
352
+ body: this.examples.map((example) => {
353
+ if (typeof example === "function") {
354
+ return example(name);
355
+ }
356
+ return example;
357
+ }).join(`
358
+ `)
359
+ });
360
+ }
361
+ if (helpCallback) {
362
+ sections = helpCallback(sections) || sections;
363
+ }
364
+ console.log(sections.map((section) => {
365
+ return section.title ? `${section.title}:
366
+ ${section.body}` : section.body;
367
+ }).join(`
368
+
369
+ `));
370
+ }
371
+ outputVersion() {
372
+ const { name } = this.cli;
373
+ const { versionNumber } = this.cli.globalCommand;
374
+ if (versionNumber) {
375
+ console.log(`${name}/${versionNumber} ${platformInfo}`);
376
+ }
377
+ }
378
+ checkRequiredArgs() {
379
+ const minimalArgsCount = this.args.filter((arg) => arg.required).length;
380
+ if (this.cli.args.length < minimalArgsCount) {
381
+ throw new CACError(`missing required args for command \`${this.rawName}\``);
382
+ }
383
+ }
384
+ checkUnknownOptions() {
385
+ const { options, globalCommand } = this.cli;
386
+ if (!this.config.allowUnknownOptions) {
387
+ for (const name of Object.keys(options)) {
388
+ if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
389
+ throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
390
+ }
391
+ }
392
+ }
393
+ }
394
+ checkOptionValue() {
395
+ const { options: parsedOptions, globalCommand } = this.cli;
396
+ const options = [...globalCommand.options, ...this.options];
397
+ for (const option of options) {
398
+ const value = parsedOptions[option.name.split(".")[0]];
399
+ if (option.required) {
400
+ const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
401
+ if (value === true || value === false && !hasNegated) {
402
+ throw new CACError(`option \`${option.rawName}\` value is missing`);
403
+ }
404
+ }
405
+ }
406
+ }
407
+ }
408
+
409
+ class GlobalCommand extends Command {
410
+ constructor(cli) {
411
+ super("@@global@@", "", {}, cli);
412
+ }
413
+ }
414
+ var __assign = Object.assign;
415
+
416
+ class CAC extends EventEmitter {
417
+ constructor(name = "") {
418
+ super();
419
+ this.name = name;
420
+ this.commands = [];
421
+ this.rawArgs = [];
422
+ this.args = [];
423
+ this.options = {};
424
+ this.globalCommand = new GlobalCommand(this);
425
+ this.globalCommand.usage("<command> [options]");
426
+ }
427
+ usage(text) {
428
+ this.globalCommand.usage(text);
429
+ return this;
430
+ }
431
+ command(rawName, description, config) {
432
+ const command = new Command(rawName, description || "", config, this);
433
+ command.globalCommand = this.globalCommand;
434
+ this.commands.push(command);
435
+ return command;
436
+ }
437
+ option(rawName, description, config) {
438
+ this.globalCommand.option(rawName, description, config);
439
+ return this;
440
+ }
441
+ help(callback) {
442
+ this.globalCommand.option("-h, --help", "Display this message");
443
+ this.globalCommand.helpCallback = callback;
444
+ this.showHelpOnExit = true;
445
+ return this;
446
+ }
447
+ version(version, customFlags = "-v, --version") {
448
+ this.globalCommand.version(version, customFlags);
449
+ this.showVersionOnExit = true;
450
+ return this;
451
+ }
452
+ example(example) {
453
+ this.globalCommand.example(example);
454
+ return this;
455
+ }
456
+ outputHelp() {
457
+ if (this.matchedCommand) {
458
+ this.matchedCommand.outputHelp();
459
+ } else {
460
+ this.globalCommand.outputHelp();
461
+ }
462
+ }
463
+ outputVersion() {
464
+ this.globalCommand.outputVersion();
465
+ }
466
+ setParsedInfo({ args, options }, matchedCommand, matchedCommandName) {
467
+ this.args = args;
468
+ this.options = options;
469
+ if (matchedCommand) {
470
+ this.matchedCommand = matchedCommand;
471
+ }
472
+ if (matchedCommandName) {
473
+ this.matchedCommandName = matchedCommandName;
474
+ }
475
+ return this;
476
+ }
477
+ unsetMatchedCommand() {
478
+ this.matchedCommand = undefined;
479
+ this.matchedCommandName = undefined;
480
+ }
481
+ parse(argv = processArgs, {
482
+ run = true
483
+ } = {}) {
484
+ this.rawArgs = argv;
485
+ if (!this.name) {
486
+ this.name = argv[1] ? getFileName(argv[1]) : "cli";
487
+ }
488
+ let shouldParse = true;
489
+ for (const command of this.commands) {
490
+ const parsed = this.mri(argv.slice(2), command);
491
+ const commandName = parsed.args[0];
492
+ if (command.isMatched(commandName)) {
493
+ shouldParse = false;
494
+ const parsedInfo = __assign(__assign({}, parsed), {
495
+ args: parsed.args.slice(1)
496
+ });
497
+ this.setParsedInfo(parsedInfo, command, commandName);
498
+ this.emit(`command:${commandName}`, command);
499
+ }
500
+ }
501
+ if (shouldParse) {
502
+ for (const command of this.commands) {
503
+ if (command.name === "") {
504
+ shouldParse = false;
505
+ const parsed = this.mri(argv.slice(2), command);
506
+ this.setParsedInfo(parsed, command);
507
+ this.emit(`command:!`, command);
508
+ }
509
+ }
510
+ }
511
+ if (shouldParse) {
512
+ const parsed = this.mri(argv.slice(2));
513
+ this.setParsedInfo(parsed);
514
+ }
515
+ if (this.options.help && this.showHelpOnExit) {
516
+ this.outputHelp();
517
+ run = false;
518
+ this.unsetMatchedCommand();
519
+ }
520
+ if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
521
+ this.outputVersion();
522
+ run = false;
523
+ this.unsetMatchedCommand();
524
+ }
525
+ const parsedArgv = { args: this.args, options: this.options };
526
+ if (run) {
527
+ this.runMatchedCommand();
528
+ }
529
+ if (!this.matchedCommand && this.args[0]) {
530
+ this.emit("command:*");
531
+ }
532
+ return parsedArgv;
533
+ }
534
+ mri(argv, command) {
535
+ const cliOptions = [
536
+ ...this.globalCommand.options,
537
+ ...command ? command.options : []
538
+ ];
539
+ const mriOptions = getMriOptions(cliOptions);
540
+ let argsAfterDoubleDashes = [];
541
+ const doubleDashesIndex = argv.indexOf("--");
542
+ if (doubleDashesIndex > -1) {
543
+ argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
544
+ argv = argv.slice(0, doubleDashesIndex);
545
+ }
546
+ let parsed = mri2(argv, mriOptions);
547
+ parsed = Object.keys(parsed).reduce((res, name) => {
548
+ return __assign(__assign({}, res), {
549
+ [camelcaseOptionName(name)]: parsed[name]
550
+ });
551
+ }, { _: [] });
552
+ const args = parsed._;
553
+ const options = {
554
+ "--": argsAfterDoubleDashes
555
+ };
556
+ const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
557
+ let transforms = Object.create(null);
558
+ for (const cliOption of cliOptions) {
559
+ if (!ignoreDefault && cliOption.config.default !== undefined) {
560
+ for (const name of cliOption.names) {
561
+ options[name] = cliOption.config.default;
562
+ }
563
+ }
564
+ if (Array.isArray(cliOption.config.type)) {
565
+ if (transforms[cliOption.name] === undefined) {
566
+ transforms[cliOption.name] = Object.create(null);
567
+ transforms[cliOption.name]["shouldTransform"] = true;
568
+ transforms[cliOption.name]["transformFunction"] = cliOption.config.type[0];
569
+ }
570
+ }
571
+ }
572
+ for (const key of Object.keys(parsed)) {
573
+ if (key !== "_") {
574
+ const keys = key.split(".");
575
+ setDotProp(options, keys, parsed[key]);
576
+ setByType(options, transforms);
577
+ }
578
+ }
579
+ return {
580
+ args,
581
+ options
582
+ };
583
+ }
584
+ runMatchedCommand() {
585
+ const { args, options, matchedCommand: command } = this;
586
+ if (!command || !command.commandAction)
587
+ return;
588
+ command.checkUnknownOptions();
589
+ command.checkOptionValue();
590
+ command.checkRequiredArgs();
591
+ const actionArgs = [];
592
+ command.args.forEach((arg, index) => {
593
+ if (arg.variadic) {
594
+ actionArgs.push(args.slice(index));
595
+ } else {
596
+ actionArgs.push(args[index]);
597
+ }
598
+ });
599
+ actionArgs.push(options);
600
+ return command.commandAction.apply(this, actionArgs);
601
+ }
602
+ }
603
+ var cac = (name = "") => new CAC(name);
604
+ var dist_default = cac;
605
+ // package.json
606
+ var version = "0.1.0";
607
+
608
+ // src/commands/init.ts
609
+ var {$ } = globalThis.Bun;
610
+ import { homedir } from "os";
611
+ import { join } from "path";
612
+ var REPO = "vibe-cokit/claude-code";
613
+ var CLAUDE_DIR = join(homedir(), ".claude");
614
+ var CONFIG_FOLDERS = ["agents", "commands", "hooks", "prompts", "workflows"];
615
+ function log(step) {
616
+ console.log(` \u2192 ${step}`);
617
+ }
618
+ async function verifyPrerequisites() {
619
+ const gh = await $`which gh`.quiet().nothrow();
620
+ if (gh.exitCode !== 0) {
621
+ throw new Error("gh CLI not found. Install: https://cli.github.com");
622
+ }
623
+ }
624
+ async function cloneRepo(tmpDir) {
625
+ const result = await $`gh repo clone ${REPO} ${tmpDir}`.quiet().nothrow();
626
+ if (result.exitCode !== 0) {
627
+ throw new Error(`Failed to clone repo: ${result.stderr.toString().trim()}`);
628
+ }
629
+ }
630
+ async function copyConfigFolders(srcDir) {
631
+ await $`mkdir -p ${CLAUDE_DIR}`.quiet();
632
+ for (const folder of CONFIG_FOLDERS) {
633
+ const src = join(srcDir, folder);
634
+ const exists = await Bun.file(join(src, ".")).exists().catch(() => false);
635
+ const check = await $`test -d ${src}`.quiet().nothrow();
636
+ if (check.exitCode === 0) {
637
+ await $`cp -r ${src} ${CLAUDE_DIR}/`.quiet();
638
+ log(`Copied ${folder}/`);
639
+ }
640
+ }
641
+ }
642
+ async function copyClaudeMd(srcDir) {
643
+ const src = join(srcDir, "CLAUDE.md");
644
+ const dest = join(process.cwd(), "CLAUDE.md");
645
+ const check = await $`test -f ${src}`.quiet().nothrow();
646
+ if (check.exitCode === 0) {
647
+ await $`cp ${src} ${dest}`.quiet();
648
+ }
649
+ }
650
+ async function runClaudeInit() {
651
+ const result = await $`claude init`.quiet().nothrow();
652
+ if (result.exitCode !== 0) {
653
+ console.log(" \u26A0 claude CLI not available, skipping CLAUDE.md enrichment");
654
+ return false;
655
+ }
656
+ return true;
657
+ }
658
+ async function getCommitSha(tmpDir) {
659
+ const sha = await $`git -C ${tmpDir} rev-parse HEAD`.text();
660
+ return sha.trim();
661
+ }
662
+ async function updateSettings(commitSha) {
663
+ const settingsPath = join(CLAUDE_DIR, "settings.json");
664
+ let settings = {};
665
+ const file = Bun.file(settingsPath);
666
+ if (await file.exists()) {
667
+ settings = await file.json();
668
+ }
669
+ settings.version = commitSha;
670
+ await Bun.write(settingsPath, JSON.stringify(settings, null, 2));
671
+ }
672
+ async function cleanup(tmpDir) {
673
+ await $`rm -rf ${tmpDir}`.quiet().nothrow();
674
+ }
675
+ async function initCommand() {
676
+ const tmpDir = `/tmp/vibe-cokit-${crypto.randomUUID()}`;
677
+ try {
678
+ console.log(`
679
+ vibe-cokit init
680
+ `);
681
+ log("Verifying prerequisites...");
682
+ await verifyPrerequisites();
683
+ log("Cloning vibe-cokit configuration...");
684
+ await cloneRepo(tmpDir);
685
+ log("Installing config folders to ~/.claude/");
686
+ await copyConfigFolders(tmpDir);
687
+ log("Copying CLAUDE.md to current project...");
688
+ await copyClaudeMd(tmpDir);
689
+ log("Running claude init...");
690
+ await runClaudeInit();
691
+ log("Updating version tracking...");
692
+ const sha = await getCommitSha(tmpDir);
693
+ await updateSettings(sha);
694
+ log("Cleaning up...");
695
+ await cleanup(tmpDir);
696
+ console.log(`
697
+ \u2713 vibe-cokit initialized successfully!`);
698
+ console.log(` Version: ${sha.slice(0, 8)}`);
699
+ console.log(` Config: ~/.claude/`);
700
+ console.log(` Claude: ./CLAUDE.md
701
+ `);
702
+ } catch (err) {
703
+ await cleanup(tmpDir);
704
+ const msg = err instanceof Error ? err.message : String(err);
705
+ console.error(`
706
+ \u2717 Init failed: ${msg}
707
+ `);
708
+ process.exit(1);
709
+ }
710
+ }
711
+
712
+ // src/cli.ts
713
+ var cli = dist_default("vibe-cokit");
714
+ cli.command("", "A toolkit for interacting with Claude Code").action(() => {
715
+ cli.outputHelp();
716
+ });
717
+ cli.command("init", "Initialize vibe-cokit for current project").action(initCommand);
718
+ cli.help();
719
+ cli.version(version);
720
+ cli.parse();
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "vibe-cokit",
3
+ "version": "0.1.0",
4
+ "description": "A toolkit for interacting with Claude Code",
5
+ "module": "index.ts",
6
+ "type": "module",
7
+ "bin": {
8
+ "vibe-cokit": "bin/vk.cjs",
9
+ "vk": "bin/vk.cjs"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "dist/",
14
+ "package.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "bun build src/cli.ts --outdir dist --target bun",
19
+ "typecheck": "bunx tsc --noEmit"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/vibe-cokit/cli.git"
27
+ },
28
+ "devDependencies": {
29
+ "@types/bun": "latest"
30
+ },
31
+ "peerDependencies": {
32
+ "typescript": "^5"
33
+ },
34
+ "dependencies": {
35
+ "cac": "^6.7.14"
36
+ }
37
+ }