@automagik/genie 0.260201.2240
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/.github/workflows/publish.yml +26 -0
- package/.worktrees/.metadata.json +3 -0
- package/README.md +532 -0
- package/bun.lock +101 -0
- package/dist/claudio.js +76 -0
- package/dist/genie.js +201 -0
- package/dist/term.js +136 -0
- package/install.sh +351 -0
- package/package.json +37 -0
- package/scripts/version.ts +48 -0
- package/src/claudio.ts +128 -0
- package/src/commands/launch.ts +245 -0
- package/src/commands/models.ts +43 -0
- package/src/commands/profiles.ts +95 -0
- package/src/commands/setup.ts +5 -0
- package/src/genie-commands/hooks.ts +317 -0
- package/src/genie-commands/install.ts +351 -0
- package/src/genie-commands/setup.ts +282 -0
- package/src/genie-commands/shortcuts.ts +62 -0
- package/src/genie-commands/update.ts +228 -0
- package/src/genie.ts +106 -0
- package/src/lib/api-client.ts +109 -0
- package/src/lib/claude-settings.ts +252 -0
- package/src/lib/config.ts +109 -0
- package/src/lib/genie-config.ts +164 -0
- package/src/lib/hook-manager.ts +130 -0
- package/src/lib/hook-script.ts +256 -0
- package/src/lib/hooks/compose.ts +72 -0
- package/src/lib/hooks/index.ts +163 -0
- package/src/lib/hooks/presets/audited.ts +191 -0
- package/src/lib/hooks/presets/collaborative.ts +143 -0
- package/src/lib/hooks/presets/sandboxed.ts +153 -0
- package/src/lib/hooks/presets/supervised.ts +66 -0
- package/src/lib/hooks/utils/escape.ts +46 -0
- package/src/lib/log-reader.ts +213 -0
- package/src/lib/picker.ts +62 -0
- package/src/lib/session-metadata.ts +58 -0
- package/src/lib/system-detect.ts +185 -0
- package/src/lib/tmux.ts +410 -0
- package/src/lib/version.ts +15 -0
- package/src/lib/wizard.ts +104 -0
- package/src/lib/worktree.ts +362 -0
- package/src/term-commands/attach.ts +23 -0
- package/src/term-commands/exec.ts +34 -0
- package/src/term-commands/hook.ts +42 -0
- package/src/term-commands/ls.ts +33 -0
- package/src/term-commands/new.ts +73 -0
- package/src/term-commands/pane.ts +81 -0
- package/src/term-commands/read.ts +70 -0
- package/src/term-commands/rm.ts +47 -0
- package/src/term-commands/send.ts +34 -0
- package/src/term-commands/shortcuts.ts +355 -0
- package/src/term-commands/split.ts +87 -0
- package/src/term-commands/status.ts +116 -0
- package/src/term-commands/window.ts +72 -0
- package/src/term.ts +192 -0
- package/src/types/config.ts +17 -0
- package/src/types/genie-config.ts +104 -0
- package/tsconfig.json +17 -0
package/dist/term.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var M0=Object.create;var{getPrototypeOf:T0,defineProperty:d,getOwnPropertyNames:V0}=Object;var F0=Object.prototype.hasOwnProperty;var D0=($,J,q)=>{q=$!=null?M0(T0($)):{};let U=J||!$||!$.__esModule?d(q,"default",{value:$,enumerable:!0}):q;for(let X of V0($))if(!F0.call(U,X))d(U,X,{get:()=>$[X],enumerable:!0});return U};var I=($,J)=>()=>(J||$((J={exports:{}}).exports,J),J.exports);var U6=($,J)=>{for(var q in J)d($,q,{get:J[q],enumerable:!0,configurable:!0,set:(U)=>J[q]=()=>U})};var k=import.meta.require;var x=I((y0)=>{class p extends Error{constructor($,J,q){super(q);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=J,this.exitCode=$,this.nestedError=void 0}}class W1 extends p{constructor($){super(1,"commander.invalidArgument",$);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}y0.CommanderError=p;y0.InvalidArgumentError=W1});var v=I((N0)=>{var{InvalidArgumentError:I0}=x();class H1{constructor($,J){switch(this.description=J||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,$[0]){case"<":this.required=!0,this._name=$.slice(1,-1);break;case"[":this.required=!1,this._name=$.slice(1,-1);break;default:this.required=!0,this._name=$;break}if(this._name.length>3&&this._name.slice(-3)==="...")this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_concatValue($,J){if(J===this.defaultValue||!Array.isArray(J))return[$];return J.concat($)}default($,J){return this.defaultValue=$,this.defaultValueDescription=J,this}argParser($){return this.parseArg=$,this}choices($){return this.argChoices=$.slice(),this.parseArg=(J,q)=>{if(!this.argChoices.includes(J))throw new I0(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(J,q);return J},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function A0($){let J=$.name()+($.variadic===!0?"...":"");return $.required?"<"+J+">":"["+J+"]"}N0.Argument=H1;N0.humanReadableArgName=A0});var m=I((C0)=>{var{humanReadableArgName:f0}=v();class R1{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands($){let J=$.commands.filter((U)=>!U._hidden),q=$._getHelpCommand();if(q&&!q._hidden)J.push(q);if(this.sortSubcommands)J.sort((U,X)=>{return U.name().localeCompare(X.name())});return J}compareOptions($,J){let q=(U)=>{return U.short?U.short.replace(/^-/,""):U.long.replace(/^--/,"")};return q($).localeCompare(q(J))}visibleOptions($){let J=$.options.filter((U)=>!U.hidden),q=$._getHelpOption();if(q&&!q.hidden){let U=q.short&&$._findOption(q.short),X=q.long&&$._findOption(q.long);if(!U&&!X)J.push(q);else if(q.long&&!X)J.push($.createOption(q.long,q.description));else if(q.short&&!U)J.push($.createOption(q.short,q.description))}if(this.sortOptions)J.sort(this.compareOptions);return J}visibleGlobalOptions($){if(!this.showGlobalOptions)return[];let J=[];for(let q=$.parent;q;q=q.parent){let U=q.options.filter((X)=>!X.hidden);J.push(...U)}if(this.sortOptions)J.sort(this.compareOptions);return J}visibleArguments($){if($._argsDescription)$.registeredArguments.forEach((J)=>{J.description=J.description||$._argsDescription[J.name()]||""});if($.registeredArguments.find((J)=>J.description))return $.registeredArguments;return[]}subcommandTerm($){let J=$.registeredArguments.map((q)=>f0(q)).join(" ");return $._name+($._aliases[0]?"|"+$._aliases[0]:"")+($.options.length?" [options]":"")+(J?" "+J:"")}optionTerm($){return $.flags}argumentTerm($){return $.name()}longestSubcommandTermLength($,J){return J.visibleCommands($).reduce((q,U)=>{return Math.max(q,J.subcommandTerm(U).length)},0)}longestOptionTermLength($,J){return J.visibleOptions($).reduce((q,U)=>{return Math.max(q,J.optionTerm(U).length)},0)}longestGlobalOptionTermLength($,J){return J.visibleGlobalOptions($).reduce((q,U)=>{return Math.max(q,J.optionTerm(U).length)},0)}longestArgumentTermLength($,J){return J.visibleArguments($).reduce((q,U)=>{return Math.max(q,J.argumentTerm(U).length)},0)}commandUsage($){let J=$._name;if($._aliases[0])J=J+"|"+$._aliases[0];let q="";for(let U=$.parent;U;U=U.parent)q=U.name()+" "+q;return q+J+" "+$.usage()}commandDescription($){return $.description()}subcommandDescription($){return $.summary()||$.description()}optionDescription($){let J=[];if($.argChoices)J.push(`choices: ${$.argChoices.map((q)=>JSON.stringify(q)).join(", ")}`);if($.defaultValue!==void 0){if($.required||$.optional||$.isBoolean()&&typeof $.defaultValue==="boolean")J.push(`default: ${$.defaultValueDescription||JSON.stringify($.defaultValue)}`)}if($.presetArg!==void 0&&$.optional)J.push(`preset: ${JSON.stringify($.presetArg)}`);if($.envVar!==void 0)J.push(`env: ${$.envVar}`);if(J.length>0)return`${$.description} (${J.join(", ")})`;return $.description}argumentDescription($){let J=[];if($.argChoices)J.push(`choices: ${$.argChoices.map((q)=>JSON.stringify(q)).join(", ")}`);if($.defaultValue!==void 0)J.push(`default: ${$.defaultValueDescription||JSON.stringify($.defaultValue)}`);if(J.length>0){let q=`(${J.join(", ")})`;if($.description)return`${$.description} ${q}`;return q}return $.description}formatHelp($,J){let q=J.padWidth($,J),U=J.helpWidth||80,X=2,G=2;function Q(W,V){if(V){let j=`${W.padEnd(q+2)}${V}`;return J.wrap(j,U-2,q+2)}return W}function S(W){return W.join(`
|
|
4
|
+
`).replace(/^/gm," ".repeat(2))}let Y=[`Usage: ${J.commandUsage($)}`,""],Z=J.commandDescription($);if(Z.length>0)Y=Y.concat([J.wrap(Z,U,0),""]);let _=J.visibleArguments($).map((W)=>{return Q(J.argumentTerm(W),J.argumentDescription(W))});if(_.length>0)Y=Y.concat(["Arguments:",S(_),""]);let B=J.visibleOptions($).map((W)=>{return Q(J.optionTerm(W),J.optionDescription(W))});if(B.length>0)Y=Y.concat(["Options:",S(B),""]);if(this.showGlobalOptions){let W=J.visibleGlobalOptions($).map((V)=>{return Q(J.optionTerm(V),J.optionDescription(V))});if(W.length>0)Y=Y.concat(["Global Options:",S(W),""])}let K=J.visibleCommands($).map((W)=>{return Q(J.subcommandTerm(W),J.subcommandDescription(W))});if(K.length>0)Y=Y.concat(["Commands:",S(K),""]);return Y.join(`
|
|
5
|
+
`)}padWidth($,J){return Math.max(J.longestOptionTermLength($,J),J.longestGlobalOptionTermLength($,J),J.longestSubcommandTermLength($,J),J.longestArgumentTermLength($,J))}wrap($,J,q,U=40){let G=new RegExp(`[\\n][${" \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF"}]+`);if($.match(G))return $;let Q=J-q;if(Q<U)return $;let S=$.slice(0,q),Y=$.slice(q).replace(`\r
|
|
6
|
+
`,`
|
|
7
|
+
`),Z=" ".repeat(q),B=`\\s${"\u200B"}`,K=new RegExp(`
|
|
8
|
+
|.{1,${Q-1}}([${B}]|$)|[^${B}]+?([${B}]|$)`,"g"),W=Y.match(K)||[];return S+W.map((V,j)=>{if(V===`
|
|
9
|
+
`)return"";return(j>0?Z:"")+V.trimEnd()}).join(`
|
|
10
|
+
`)}}C0.Help=R1});var r=I((h0)=>{var{InvalidArgumentError:x0}=x();class E1{constructor($,J){this.flags=$,this.description=J||"",this.required=$.includes("<"),this.optional=$.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test($),this.mandatory=!1;let q=v0($);if(this.short=q.shortFlag,this.long=q.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default($,J){return this.defaultValue=$,this.defaultValueDescription=J,this}preset($){return this.presetArg=$,this}conflicts($){return this.conflictsWith=this.conflictsWith.concat($),this}implies($){let J=$;if(typeof $==="string")J={[$]:!0};return this.implied=Object.assign(this.implied||{},J),this}env($){return this.envVar=$,this}argParser($){return this.parseArg=$,this}makeOptionMandatory($=!0){return this.mandatory=!!$,this}hideHelp($=!0){return this.hidden=!!$,this}_concatValue($,J){if(J===this.defaultValue||!Array.isArray(J))return[$];return J.concat($)}choices($){return this.argChoices=$.slice(),this.parseArg=(J,q)=>{if(!this.argChoices.includes(J))throw new x0(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(J,q);return J},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){return b0(this.name().replace(/^no-/,""))}is($){return this.short===$||this.long===$}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class B1{constructor($){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,$.forEach((J)=>{if(J.negate)this.negativeOptions.set(J.attributeName(),J);else this.positiveOptions.set(J.attributeName(),J)}),this.negativeOptions.forEach((J,q)=>{if(this.positiveOptions.has(q))this.dualOptions.add(q)})}valueFromOption($,J){let q=J.attributeName();if(!this.dualOptions.has(q))return!0;let U=this.negativeOptions.get(q).presetArg,X=U!==void 0?U:!1;return J.negate===(X===$)}}function b0($){return $.split("-").reduce((J,q)=>{return J+q[0].toUpperCase()+q.slice(1)})}function v0($){let J,q,U=$.split(/[ |,]+/);if(U.length>1&&!/^[[<]/.test(U[1]))J=U.shift();if(q=U.shift(),!J&&/^-[^-]$/.test(q))J=q,q=void 0;return{shortFlag:J,longFlag:q}}h0.Option=E1;h0.DualOptions=B1});var K1=I((d0)=>{function l0($,J){if(Math.abs($.length-J.length)>3)return Math.max($.length,J.length);let q=[];for(let U=0;U<=$.length;U++)q[U]=[U];for(let U=0;U<=J.length;U++)q[0][U]=U;for(let U=1;U<=J.length;U++)for(let X=1;X<=$.length;X++){let G=1;if($[X-1]===J[U-1])G=0;else G=1;if(q[X][U]=Math.min(q[X-1][U]+1,q[X][U-1]+1,q[X-1][U-1]+G),X>1&&U>1&&$[X-1]===J[U-2]&&$[X-2]===J[U-1])q[X][U]=Math.min(q[X][U],q[X-2][U-2]+1)}return q[$.length][J.length]}function c0($,J){if(!J||J.length===0)return"";J=Array.from(new Set(J));let q=$.startsWith("--");if(q)$=$.slice(2),J=J.map((Q)=>Q.slice(2));let U=[],X=3,G=0.4;if(J.forEach((Q)=>{if(Q.length<=1)return;let S=l0($,Q),Y=Math.max($.length,Q.length);if((Y-S)/Y>G){if(S<X)X=S,U=[Q];else if(S===X)U.push(Q)}}),U.sort((Q,S)=>Q.localeCompare(S)),q)U=U.map((Q)=>`--${Q}`);if(U.length>1)return`
|
|
11
|
+
(Did you mean one of ${U.join(", ")}?)`;if(U.length===1)return`
|
|
12
|
+
(Did you mean ${U[0]}?)`;return""}d0.suggestSimilar=c0});var T1=I((o0)=>{var m0=k("events").EventEmitter,s=k("child_process"),y=k("path"),i=k("fs"),E=k("process"),{Argument:r0,humanReadableArgName:s0}=v(),{CommanderError:t}=x(),{Help:i0}=m(),{Option:z1,DualOptions:t0}=r(),{suggestSimilar:L1}=K1();class o extends m0{constructor($){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=$||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:(J)=>E.stdout.write(J),writeErr:(J)=>E.stderr.write(J),getOutHelpWidth:()=>E.stdout.isTTY?E.stdout.columns:void 0,getErrHelpWidth:()=>E.stderr.isTTY?E.stderr.columns:void 0,outputError:(J,q)=>q(J)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings($){return this._outputConfiguration=$._outputConfiguration,this._helpOption=$._helpOption,this._helpCommand=$._helpCommand,this._helpConfiguration=$._helpConfiguration,this._exitCallback=$._exitCallback,this._storeOptionsAsProperties=$._storeOptionsAsProperties,this._combineFlagAndOptionalValue=$._combineFlagAndOptionalValue,this._allowExcessArguments=$._allowExcessArguments,this._enablePositionalOptions=$._enablePositionalOptions,this._showHelpAfterError=$._showHelpAfterError,this._showSuggestionAfterError=$._showSuggestionAfterError,this}_getCommandAndAncestors(){let $=[];for(let J=this;J;J=J.parent)$.push(J);return $}command($,J,q){let U=J,X=q;if(typeof U==="object"&&U!==null)X=U,U=null;X=X||{};let[,G,Q]=$.match(/([^ ]+) *(.*)/),S=this.createCommand(G);if(U)S.description(U),S._executableHandler=!0;if(X.isDefault)this._defaultCommandName=S._name;if(S._hidden=!!(X.noHelp||X.hidden),S._executableFile=X.executableFile||null,Q)S.arguments(Q);if(this._registerCommand(S),S.parent=this,S.copyInheritedSettings(this),U)return this;return S}createCommand($){return new o($)}createHelp(){return Object.assign(new i0,this.configureHelp())}configureHelp($){if($===void 0)return this._helpConfiguration;return this._helpConfiguration=$,this}configureOutput($){if($===void 0)return this._outputConfiguration;return Object.assign(this._outputConfiguration,$),this}showHelpAfterError($=!0){if(typeof $!=="string")$=!!$;return this._showHelpAfterError=$,this}showSuggestionAfterError($=!0){return this._showSuggestionAfterError=!!$,this}addCommand($,J){if(!$._name)throw Error(`Command passed to .addCommand() must have a name
|
|
13
|
+
- specify the name in Command constructor or using .name()`);if(J=J||{},J.isDefault)this._defaultCommandName=$._name;if(J.noHelp||J.hidden)$._hidden=!0;return this._registerCommand($),$.parent=this,$._checkForBrokenPassThrough(),this}createArgument($,J){return new r0($,J)}argument($,J,q,U){let X=this.createArgument($,J);if(typeof q==="function")X.default(U).argParser(q);else X.default(q);return this.addArgument(X),this}arguments($){return $.trim().split(/ +/).forEach((J)=>{this.argument(J)}),this}addArgument($){let J=this.registeredArguments.slice(-1)[0];if(J&&J.variadic)throw Error(`only the last argument can be variadic '${J.name()}'`);if($.required&&$.defaultValue!==void 0&&$.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${$.name()}'`);return this.registeredArguments.push($),this}helpCommand($,J){if(typeof $==="boolean")return this._addImplicitHelpCommand=$,this;$=$??"help [command]";let[,q,U]=$.match(/([^ ]+) *(.*)/),X=J??"display help for command",G=this.createCommand(q);if(G.helpOption(!1),U)G.arguments(U);if(X)G.description(X);return this._addImplicitHelpCommand=!0,this._helpCommand=G,this}addHelpCommand($,J){if(typeof $!=="object")return this.helpCommand($,J),this;return this._addImplicitHelpCommand=!0,this._helpCommand=$,this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook($,J){let q=["preSubcommand","preAction","postAction"];if(!q.includes($))throw Error(`Unexpected value for event passed to hook : '${$}'.
|
|
14
|
+
Expecting one of '${q.join("', '")}'`);if(this._lifeCycleHooks[$])this._lifeCycleHooks[$].push(J);else this._lifeCycleHooks[$]=[J];return this}exitOverride($){if($)this._exitCallback=$;else this._exitCallback=(J)=>{if(J.code!=="commander.executeSubCommandAsync")throw J};return this}_exit($,J,q){if(this._exitCallback)this._exitCallback(new t($,J,q));E.exit($)}action($){let J=(q)=>{let U=this.registeredArguments.length,X=q.slice(0,U);if(this._storeOptionsAsProperties)X[U]=this;else X[U]=this.opts();return X.push(this),$.apply(this,X)};return this._actionHandler=J,this}createOption($,J){return new z1($,J)}_callParseArg($,J,q,U){try{return $.parseArg(J,q)}catch(X){if(X.code==="commander.invalidArgument"){let G=`${U} ${X.message}`;this.error(G,{exitCode:X.exitCode,code:X.code})}throw X}}_registerOption($){let J=$.short&&this._findOption($.short)||$.long&&this._findOption($.long);if(J){let q=$.long&&this._findOption($.long)?$.long:$.short;throw Error(`Cannot add option '${$.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${q}'
|
|
15
|
+
- already used by option '${J.flags}'`)}this.options.push($)}_registerCommand($){let J=(U)=>{return[U.name()].concat(U.aliases())},q=J($).find((U)=>this._findCommand(U));if(q){let U=J(this._findCommand(q)).join("|"),X=J($).join("|");throw Error(`cannot add command '${X}' as already have command '${U}'`)}this.commands.push($)}addOption($){this._registerOption($);let J=$.name(),q=$.attributeName();if($.negate){let X=$.long.replace(/^--no-/,"--");if(!this._findOption(X))this.setOptionValueWithSource(q,$.defaultValue===void 0?!0:$.defaultValue,"default")}else if($.defaultValue!==void 0)this.setOptionValueWithSource(q,$.defaultValue,"default");let U=(X,G,Q)=>{if(X==null&&$.presetArg!==void 0)X=$.presetArg;let S=this.getOptionValue(q);if(X!==null&&$.parseArg)X=this._callParseArg($,X,S,G);else if(X!==null&&$.variadic)X=$._concatValue(X,S);if(X==null)if($.negate)X=!1;else if($.isBoolean()||$.optional)X=!0;else X="";this.setOptionValueWithSource(q,X,Q)};if(this.on("option:"+J,(X)=>{let G=`error: option '${$.flags}' argument '${X}' is invalid.`;U(X,G,"cli")}),$.envVar)this.on("optionEnv:"+J,(X)=>{let G=`error: option '${$.flags}' value '${X}' from env '${$.envVar}' is invalid.`;U(X,G,"env")});return this}_optionEx($,J,q,U,X){if(typeof J==="object"&&J instanceof z1)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let G=this.createOption(J,q);if(G.makeOptionMandatory(!!$.mandatory),typeof U==="function")G.default(X).argParser(U);else if(U instanceof RegExp){let Q=U;U=(S,Y)=>{let Z=Q.exec(S);return Z?Z[0]:Y},G.default(X).argParser(U)}else G.default(U);return this.addOption(G)}option($,J,q,U){return this._optionEx({},$,J,q,U)}requiredOption($,J,q,U){return this._optionEx({mandatory:!0},$,J,q,U)}combineFlagAndOptionalValue($=!0){return this._combineFlagAndOptionalValue=!!$,this}allowUnknownOption($=!0){return this._allowUnknownOption=!!$,this}allowExcessArguments($=!0){return this._allowExcessArguments=!!$,this}enablePositionalOptions($=!0){return this._enablePositionalOptions=!!$,this}passThroughOptions($=!0){return this._passThroughOptions=!!$,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties($=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!$,this}getOptionValue($){if(this._storeOptionsAsProperties)return this[$];return this._optionValues[$]}setOptionValue($,J){return this.setOptionValueWithSource($,J,void 0)}setOptionValueWithSource($,J,q){if(this._storeOptionsAsProperties)this[$]=J;else this._optionValues[$]=J;return this._optionValueSources[$]=q,this}getOptionValueSource($){return this._optionValueSources[$]}getOptionValueSourceWithGlobals($){let J;return this._getCommandAndAncestors().forEach((q)=>{if(q.getOptionValueSource($)!==void 0)J=q.getOptionValueSource($)}),J}_prepareUserArgs($,J){if($!==void 0&&!Array.isArray($))throw Error("first parameter to parse must be array or undefined");if(J=J||{},$===void 0&&J.from===void 0){if(E.versions?.electron)J.from="electron";let U=E.execArgv??[];if(U.includes("-e")||U.includes("--eval")||U.includes("-p")||U.includes("--print"))J.from="eval"}if($===void 0)$=E.argv;this.rawArgs=$.slice();let q;switch(J.from){case void 0:case"node":this._scriptPath=$[1],q=$.slice(2);break;case"electron":if(E.defaultApp)this._scriptPath=$[1],q=$.slice(2);else q=$.slice(1);break;case"user":q=$.slice(0);break;case"eval":q=$.slice(1);break;default:throw Error(`unexpected parse option { from: '${J.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",q}parse($,J){let q=this._prepareUserArgs($,J);return this._parseCommand([],q),this}async parseAsync($,J){let q=this._prepareUserArgs($,J);return await this._parseCommand([],q),this}_executeSubCommand($,J){J=J.slice();let q=!1,U=[".js",".ts",".tsx",".mjs",".cjs"];function X(Z,_){let B=y.resolve(Z,_);if(i.existsSync(B))return B;if(U.includes(y.extname(_)))return;let K=U.find((W)=>i.existsSync(`${B}${W}`));if(K)return`${B}${K}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let G=$._executableFile||`${this._name}-${$._name}`,Q=this._executableDir||"";if(this._scriptPath){let Z;try{Z=i.realpathSync(this._scriptPath)}catch(_){Z=this._scriptPath}Q=y.resolve(y.dirname(Z),Q)}if(Q){let Z=X(Q,G);if(!Z&&!$._executableFile&&this._scriptPath){let _=y.basename(this._scriptPath,y.extname(this._scriptPath));if(_!==this._name)Z=X(Q,`${_}-${$._name}`)}G=Z||G}q=U.includes(y.extname(G));let S;if(E.platform!=="win32")if(q)J.unshift(G),J=M1(E.execArgv).concat(J),S=s.spawn(E.argv[0],J,{stdio:"inherit"});else S=s.spawn(G,J,{stdio:"inherit"});else J.unshift(G),J=M1(E.execArgv).concat(J),S=s.spawn(E.execPath,J,{stdio:"inherit"});if(!S.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((_)=>{E.on(_,()=>{if(S.killed===!1&&S.exitCode===null)S.kill(_)})});let Y=this._exitCallback;S.on("close",(Z)=>{if(Z=Z??1,!Y)E.exit(Z);else Y(new t(Z,"commander.executeSubCommandAsync","(close)"))}),S.on("error",(Z)=>{if(Z.code==="ENOENT"){let _=Q?`searched for local subcommand relative to directory '${Q}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",B=`'${G}' does not exist
|
|
16
|
+
- if '${$._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
17
|
+
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
18
|
+
- ${_}`;throw Error(B)}else if(Z.code==="EACCES")throw Error(`'${G}' not executable`);if(!Y)E.exit(1);else{let _=new t(1,"commander.executeSubCommandAsync","(error)");_.nestedError=Z,Y(_)}}),this.runningCommand=S}_dispatchSubcommand($,J,q){let U=this._findCommand($);if(!U)this.help({error:!0});let X;return X=this._chainOrCallSubCommandHook(X,U,"preSubcommand"),X=this._chainOrCall(X,()=>{if(U._executableHandler)this._executeSubCommand(U,J.concat(q));else return U._parseCommand(J,q)}),X}_dispatchHelpCommand($){if(!$)this.help();let J=this._findCommand($);if(J&&!J._executableHandler)J.help();return this._dispatchSubcommand($,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach(($,J)=>{if($.required&&this.args[J]==null)this.missingArgument($.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let $=(q,U,X)=>{let G=U;if(U!==null&&q.parseArg){let Q=`error: command-argument value '${U}' is invalid for argument '${q.name()}'.`;G=this._callParseArg(q,U,X,Q)}return G};this._checkNumberOfArguments();let J=[];this.registeredArguments.forEach((q,U)=>{let X=q.defaultValue;if(q.variadic){if(U<this.args.length){if(X=this.args.slice(U),q.parseArg)X=X.reduce((G,Q)=>{return $(q,Q,G)},q.defaultValue)}else if(X===void 0)X=[]}else if(U<this.args.length){if(X=this.args[U],q.parseArg)X=$(q,X,q.defaultValue)}J[U]=X}),this.processedArgs=J}_chainOrCall($,J){if($&&$.then&&typeof $.then==="function")return $.then(()=>J());return J()}_chainOrCallHooks($,J){let q=$,U=[];if(this._getCommandAndAncestors().reverse().filter((X)=>X._lifeCycleHooks[J]!==void 0).forEach((X)=>{X._lifeCycleHooks[J].forEach((G)=>{U.push({hookedCommand:X,callback:G})})}),J==="postAction")U.reverse();return U.forEach((X)=>{q=this._chainOrCall(q,()=>{return X.callback(X.hookedCommand,this)})}),q}_chainOrCallSubCommandHook($,J,q){let U=$;if(this._lifeCycleHooks[q]!==void 0)this._lifeCycleHooks[q].forEach((X)=>{U=this._chainOrCall(U,()=>{return X(this,J)})});return U}_parseCommand($,J){let q=this.parseOptions(J);if(this._parseOptionsEnv(),this._parseOptionsImplied(),$=$.concat(q.operands),J=q.unknown,this.args=$.concat(J),$&&this._findCommand($[0]))return this._dispatchSubcommand($[0],$.slice(1),J);if(this._getHelpCommand()&&$[0]===this._getHelpCommand().name())return this._dispatchHelpCommand($[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(J),this._dispatchSubcommand(this._defaultCommandName,$,J);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(q.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let U=()=>{if(q.unknown.length>0)this.unknownOption(q.unknown[0])},X=`command:${this.name()}`;if(this._actionHandler){U(),this._processArguments();let G;if(G=this._chainOrCallHooks(G,"preAction"),G=this._chainOrCall(G,()=>this._actionHandler(this.processedArgs)),this.parent)G=this._chainOrCall(G,()=>{this.parent.emit(X,$,J)});return G=this._chainOrCallHooks(G,"postAction"),G}if(this.parent&&this.parent.listenerCount(X))U(),this._processArguments(),this.parent.emit(X,$,J);else if($.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",$,J);if(this.listenerCount("command:*"))this.emit("command:*",$,J);else if(this.commands.length)this.unknownCommand();else U(),this._processArguments()}else if(this.commands.length)U(),this.help({error:!0});else U(),this._processArguments()}_findCommand($){if(!$)return;return this.commands.find((J)=>J._name===$||J._aliases.includes($))}_findOption($){return this.options.find((J)=>J.is($))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(($)=>{$.options.forEach((J)=>{if(J.mandatory&&$.getOptionValue(J.attributeName())===void 0)$.missingMandatoryOptionValue(J)})})}_checkForConflictingLocalOptions(){let $=this.options.filter((q)=>{let U=q.attributeName();if(this.getOptionValue(U)===void 0)return!1;return this.getOptionValueSource(U)!=="default"});$.filter((q)=>q.conflictsWith.length>0).forEach((q)=>{let U=$.find((X)=>q.conflictsWith.includes(X.attributeName()));if(U)this._conflictingOption(q,U)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(($)=>{$._checkForConflictingLocalOptions()})}parseOptions($){let J=[],q=[],U=J,X=$.slice();function G(S){return S.length>1&&S[0]==="-"}let Q=null;while(X.length){let S=X.shift();if(S==="--"){if(U===q)U.push(S);U.push(...X);break}if(Q&&!G(S)){this.emit(`option:${Q.name()}`,S);continue}if(Q=null,G(S)){let Y=this._findOption(S);if(Y){if(Y.required){let Z=X.shift();if(Z===void 0)this.optionMissingArgument(Y);this.emit(`option:${Y.name()}`,Z)}else if(Y.optional){let Z=null;if(X.length>0&&!G(X[0]))Z=X.shift();this.emit(`option:${Y.name()}`,Z)}else this.emit(`option:${Y.name()}`);Q=Y.variadic?Y:null;continue}}if(S.length>2&&S[0]==="-"&&S[1]!=="-"){let Y=this._findOption(`-${S[1]}`);if(Y){if(Y.required||Y.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${Y.name()}`,S.slice(2));else this.emit(`option:${Y.name()}`),X.unshift(`-${S.slice(2)}`);continue}}if(/^--[^=]+=/.test(S)){let Y=S.indexOf("="),Z=this._findOption(S.slice(0,Y));if(Z&&(Z.required||Z.optional)){this.emit(`option:${Z.name()}`,S.slice(Y+1));continue}}if(G(S))U=q;if((this._enablePositionalOptions||this._passThroughOptions)&&J.length===0&&q.length===0){if(this._findCommand(S)){if(J.push(S),X.length>0)q.push(...X);break}else if(this._getHelpCommand()&&S===this._getHelpCommand().name()){if(J.push(S),X.length>0)J.push(...X);break}else if(this._defaultCommandName){if(q.push(S),X.length>0)q.push(...X);break}}if(this._passThroughOptions){if(U.push(S),X.length>0)U.push(...X);break}U.push(S)}return{operands:J,unknown:q}}opts(){if(this._storeOptionsAsProperties){let $={},J=this.options.length;for(let q=0;q<J;q++){let U=this.options[q].attributeName();$[U]=U===this._versionOptionName?this._version:this[U]}return $}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce(($,J)=>Object.assign($,J.opts()),{})}error($,J){if(this._outputConfiguration.outputError(`${$}
|
|
19
|
+
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError==="string")this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
20
|
+
`);else if(this._showHelpAfterError)this._outputConfiguration.writeErr(`
|
|
21
|
+
`),this.outputHelp({error:!0});let q=J||{},U=q.exitCode||1,X=q.code||"commander.error";this._exit(U,X,$)}_parseOptionsEnv(){this.options.forEach(($)=>{if($.envVar&&$.envVar in E.env){let J=$.attributeName();if(this.getOptionValue(J)===void 0||["default","config","env"].includes(this.getOptionValueSource(J)))if($.required||$.optional)this.emit(`optionEnv:${$.name()}`,E.env[$.envVar]);else this.emit(`optionEnv:${$.name()}`)}})}_parseOptionsImplied(){let $=new t0(this.options),J=(q)=>{return this.getOptionValue(q)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(q))};this.options.filter((q)=>q.implied!==void 0&&J(q.attributeName())&&$.valueFromOption(this.getOptionValue(q.attributeName()),q)).forEach((q)=>{Object.keys(q.implied).filter((U)=>!J(U)).forEach((U)=>{this.setOptionValueWithSource(U,q.implied[U],"implied")})})}missingArgument($){let J=`error: missing required argument '${$}'`;this.error(J,{code:"commander.missingArgument"})}optionMissingArgument($){let J=`error: option '${$.flags}' argument missing`;this.error(J,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue($){let J=`error: required option '${$.flags}' not specified`;this.error(J,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption($,J){let q=(G)=>{let Q=G.attributeName(),S=this.getOptionValue(Q),Y=this.options.find((_)=>_.negate&&Q===_.attributeName()),Z=this.options.find((_)=>!_.negate&&Q===_.attributeName());if(Y&&(Y.presetArg===void 0&&S===!1||Y.presetArg!==void 0&&S===Y.presetArg))return Y;return Z||G},U=(G)=>{let Q=q(G),S=Q.attributeName();if(this.getOptionValueSource(S)==="env")return`environment variable '${Q.envVar}'`;return`option '${Q.flags}'`},X=`error: ${U($)} cannot be used with ${U(J)}`;this.error(X,{code:"commander.conflictingOption"})}unknownOption($){if(this._allowUnknownOption)return;let J="";if($.startsWith("--")&&this._showSuggestionAfterError){let U=[],X=this;do{let G=X.createHelp().visibleOptions(X).filter((Q)=>Q.long).map((Q)=>Q.long);U=U.concat(G),X=X.parent}while(X&&!X._enablePositionalOptions);J=L1($,U)}let q=`error: unknown option '${$}'${J}`;this.error(q,{code:"commander.unknownOption"})}_excessArguments($){if(this._allowExcessArguments)return;let J=this.registeredArguments.length,q=J===1?"":"s",X=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${J} argument${q} but got ${$.length}.`;this.error(X,{code:"commander.excessArguments"})}unknownCommand(){let $=this.args[0],J="";if(this._showSuggestionAfterError){let U=[];this.createHelp().visibleCommands(this).forEach((X)=>{if(U.push(X.name()),X.alias())U.push(X.alias())}),J=L1($,U)}let q=`error: unknown command '${$}'${J}`;this.error(q,{code:"commander.unknownCommand"})}version($,J,q){if($===void 0)return this._version;this._version=$,J=J||"-V, --version",q=q||"output the version number";let U=this.createOption(J,q);return this._versionOptionName=U.attributeName(),this._registerOption(U),this.on("option:"+U.name(),()=>{this._outputConfiguration.writeOut(`${$}
|
|
22
|
+
`),this._exit(0,"commander.version",$)}),this}description($,J){if($===void 0&&J===void 0)return this._description;if(this._description=$,J)this._argsDescription=J;return this}summary($){if($===void 0)return this._summary;return this._summary=$,this}alias($){if($===void 0)return this._aliases[0];let J=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)J=this.commands[this.commands.length-1];if($===J._name)throw Error("Command alias can't be the same as its name");let q=this.parent?._findCommand($);if(q){let U=[q.name()].concat(q.aliases()).join("|");throw Error(`cannot add alias '${$}' to command '${this.name()}' as already have command '${U}'`)}return J._aliases.push($),this}aliases($){if($===void 0)return this._aliases;return $.forEach((J)=>this.alias(J)),this}usage($){if($===void 0){if(this._usage)return this._usage;let J=this.registeredArguments.map((q)=>{return s0(q)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?J:[]).join(" ")}return this._usage=$,this}name($){if($===void 0)return this._name;return this._name=$,this}nameFromFilename($){return this._name=y.basename($,y.extname($)),this}executableDir($){if($===void 0)return this._executableDir;return this._executableDir=$,this}helpInformation($){let J=this.createHelp();if(J.helpWidth===void 0)J.helpWidth=$&&$.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth();return J.formatHelp(this,J)}_getHelpContext($){$=$||{};let J={error:!!$.error},q;if(J.error)q=(U)=>this._outputConfiguration.writeErr(U);else q=(U)=>this._outputConfiguration.writeOut(U);return J.write=$.write||q,J.command=this,J}outputHelp($){let J;if(typeof $==="function")J=$,$=void 0;let q=this._getHelpContext($);this._getCommandAndAncestors().reverse().forEach((X)=>X.emit("beforeAllHelp",q)),this.emit("beforeHelp",q);let U=this.helpInformation(q);if(J){if(U=J(U),typeof U!=="string"&&!Buffer.isBuffer(U))throw Error("outputHelp callback must return a string or a Buffer")}if(q.write(U),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",q),this._getCommandAndAncestors().forEach((X)=>X.emit("afterAllHelp",q))}helpOption($,J){if(typeof $==="boolean"){if($)this._helpOption=this._helpOption??void 0;else this._helpOption=null;return this}return $=$??"-h, --help",J=J??"display help for command",this._helpOption=this.createOption($,J),this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption($){return this._helpOption=$,this}help($){this.outputHelp($);let J=E.exitCode||0;if(J===0&&$&&typeof $!=="function"&&$.error)J=1;this._exit(J,"commander.help","(outputHelp)")}addHelpText($,J){let q=["beforeAll","before","after","afterAll"];if(!q.includes($))throw Error(`Unexpected value for position to addHelpText.
|
|
23
|
+
Expecting one of '${q.join("', '")}'`);let U=`${$}Help`;return this.on(U,(X)=>{let G;if(typeof J==="function")G=J({error:X.error,command:X.command});else G=J;if(G)X.write(`${G}
|
|
24
|
+
`)}),this}_outputHelpIfRequested($){let J=this._getHelpOption();if(J&&$.find((U)=>J.is(U)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function M1($){return $.map((J)=>{if(!J.startsWith("--inspect"))return J;let q,U="127.0.0.1",X="9229",G;if((G=J.match(/^(--inspect(-brk)?)$/))!==null)q=G[1];else if((G=J.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(q=G[1],/^\d+$/.test(G[3]))X=G[3];else U=G[3];else if((G=J.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)q=G[1],U=G[3],X=G[4];if(q&&X!=="0")return`${q}=${U}:${parseInt(X)+1}`;return J})}o0.Command=o});var y1=I(($$)=>{var{Argument:V1}=v(),{Command:a}=T1(),{CommanderError:n0,InvalidArgumentError:F1}=x(),{Help:e0}=m(),{Option:D1}=r();$$.program=new a;$$.createCommand=($)=>new a($);$$.createOption=($,J)=>new D1($,J);$$.createArgument=($,J)=>new V1($,J);$$.Command=a;$$.Option=D1;$$.Argument=V1;$$.Help=e0;$$.CommanderError=n0;$$.InvalidArgumentError=F1;$$.InvalidOptionArgumentError=F1});var P1=D0(y1(),1),{program:H6,createCommand:R6,createArgument:E6,createOption:B6,CommanderError:K6,InvalidArgumentError:z6,InvalidOptionArgumentError:L6,Command:j1,Argument:M6,Option:T6,Help:V6}=P1.default;import{join as O$}from"path";import{exec as B$}from"child_process";import{promisify as K$}from"util";var z=[];for(let $=0;$<256;++$)z.push(($+256).toString(16).slice(1));function I1($,J=0){return(z[$[J+0]]+z[$[J+1]]+z[$[J+2]]+z[$[J+3]]+"-"+z[$[J+4]]+z[$[J+5]]+"-"+z[$[J+6]]+z[$[J+7]]+"-"+z[$[J+8]]+z[$[J+9]]+"-"+z[$[J+10]]+z[$[J+11]]+z[$[J+12]]+z[$[J+13]]+z[$[J+14]]+z[$[J+15]]).toLowerCase()}import{randomFillSync as H$}from"crypto";var g=new Uint8Array(256),h=g.length;function n(){if(h>g.length-16)H$(g),h=0;return g.slice(h,h+=16)}import{randomUUID as R$}from"crypto";var e={randomUUID:R$};function E$($,J,q){if(e.randomUUID&&!J&&!$)return e.randomUUID();$=$||{};let U=$.random??$.rng?.()??n();if(U.length<16)throw Error("Random bytes length must be >= 16");if(U[6]=U[6]&15|64,U[8]=U[8]&63|128,J){if(q=q||0,q<0||q+16>J.length)throw RangeError(`UUID byte range ${q}:${q+15} is out of buffer bounds`);for(let X=0;X<16;++X)J[q+X]=U[X];return J}return I1(U)}var $1=E$;var z$=K$(B$),L$={type:"bash"};async function H($){try{let{stdout:J}=await z$(`tmux ${$}`);return J.trim()}catch(J){throw Error(`Failed to execute tmux command: ${J.message}`)}}async function U1(){try{let J=await H("list-sessions -F '#{session_id}:#{session_name}:#{?session_attached,1,0}:#{session_windows}'");if(!J)return[];return J.split(`
|
|
25
|
+
`).map((q)=>{let[U,X,G,Q]=q.split(":");return{id:U,name:X,attached:G==="1",windows:parseInt(Q,10)}})}catch($){if($.message.includes("no server running"))return[];throw $}}async function R($){try{return(await U1()).find((q)=>q.name===$)||null}catch(J){return null}}async function L($){try{let q=await H(`list-windows -t '${$}' -F '#{window_id}:#{window_name}:#{?window_active,1,0}'`);if(!q)return[];return q.split(`
|
|
26
|
+
`).map((U)=>{let[X,G,Q]=U.split(":");return{id:X,name:G,active:Q==="1",sessionId:$}})}catch(J){if(J.message.includes("no server running")||J.message.includes("session not found"))return[];throw J}}async function T($){try{let q=await H(`list-panes -t '${$}' -F '#{pane_id}:#{pane_title}:#{?pane_active,1,0}'`);if(!q)return[];return q.split(`
|
|
27
|
+
`).map((U)=>{let[X,G,Q]=U.split(":");return{id:X,windowId:$,title:G,active:Q==="1"}})}catch(J){if(J.message.includes("no server running")||J.message.includes("window not found"))return[];throw J}}async function A($,J=200,q=!1){try{return await H(`capture-pane -p ${q?"-e":""} -t '${$}' -S -${J} -E -`)}catch(U){if(U.message.includes("no server running")||U.message.includes("pane not found"))return"";throw U}}async function A1($){return await H(`new-session -d -s "${$}" -e LC_ALL=C.UTF-8 -e LANG=C.UTF-8`),R($)}async function N1($,J){let q=await H(`new-window -t '${$}' -n '${J}'`);return(await L($)).find((X)=>X.name===J)||null}async function O1($){await H(`kill-session -t '${$}'`)}async function w1($){await H(`kill-window -t '${$}'`)}async function f1($){await H(`kill-pane -t '${$}'`)}async function C1($,J="vertical",q){let U="split-window";if(J==="horizontal")U+=" -h";else U+=" -v";if(U+=` -t '${$}'`,q!==void 0&&q>0&&q<100)U+=` -p ${q}`;await H(U);let X=await H(`display-message -p -t '${$}' '#{window_id}'`),G=await T(X);return G.length>0?G[G.length-1]:null}var J1=new Map,q1="TMUX_MCP_START",u="TMUX_MCP_DONE_";async function l($,J,q,U){let X=$1(),G;if(q||U)G=J;else{let Q=M$();G=`echo "${q1}"; ${J}; echo "${Q}"`}if(J1.set(X,{id:X,paneId:$,command:J,status:"pending",startTime:new Date,rawMode:q||U}),U)if(["Up","Down","Left","Right","Escape","Tab","Enter","Space","BSpace","Delete","Home","End","PageUp","PageDown","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"].includes(G))await H(`send-keys -t '${$}' ${G}`);else for(let S of G)await H(`send-keys -t '${$}' '${S.replace(/'/g,"'\\''")}'`);else await H(`send-keys -t '${$}' '${G.replace(/'/g,"'\\''")}' Enter`);return X}async function k1($){let J=J1.get($);if(!J)return null;if(J.status!=="pending")return J;let q=await A(J.paneId,1000);if(J.rawMode)return J.result="Status tracking unavailable for rawMode commands. Use capture-pane to monitor interactive apps instead.",J;let U=q.lastIndexOf(q1),X=q.lastIndexOf(u);if(U===-1||X===-1||X<=U)return J.result="Command output could not be captured properly",J;let G=q.substring(X).split(`
|
|
28
|
+
`)[0],Q=new RegExp(`${u}(\\d+)`),S=G.match(Q);if(S){let Y=parseInt(S[1],10);J.status=Y===0?"completed":"error",J.exitCode=Y;let Z=U+q1.length,_=q.substring(Z,X).trim();J.result=_.substring(_.indexOf(`
|
|
29
|
+
`)+1).trim(),J1.set($,J)}return J}function M$(){return L$.type==="fish"?`${u}$status`:`${u}$?`}async function v6($,J){await H(`rename-window -t '${$}' '${J}'`)}var{$:P}=globalThis.Bun;import{mkdir as x1,rm as b1,access as X1,readFile as T$,writeFile as V$}from"fs/promises";import{join as w,basename as F$}from"path";function c($){return $.replace(/\//g,"-").replace(/\\/g,"-").replace(/[^a-zA-Z0-9-_.]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function D$($){let J=$.match(/^(\d+)([hdwm])$/i);if(!J)throw Error(`Invalid timeframe format: ${$}. Use format like 7d, 2w, 1m, 24h`);let q=parseInt(J[1],10),U=J[2].toLowerCase();return q*{h:3600000,d:86400000,w:604800000,m:2592000000}[U]}class v1{baseDir;repoPath;metadataPath;constructor($){this.baseDir=$.baseDir,this.repoPath=$.repoPath,this.metadataPath=w(this.baseDir,".metadata.json")}async loadMetadata(){try{let $=await T$(this.metadataPath,"utf-8");return JSON.parse($)}catch{return{worktrees:{}}}}async saveMetadata($){await x1(this.baseDir,{recursive:!0}),await V$(this.metadataPath,JSON.stringify($,null,2))}async createWorktree($,J=!1,q){let U=c($),X=w(this.baseDir,U);await x1(this.baseDir,{recursive:!0});try{throw await X1(X),Error(`Worktree already exists at ${X}`)}catch(S){if(S.code!=="ENOENT")throw S}if(J)if(q)await P`git -C ${this.repoPath} worktree add -b ${$} ${X} ${q}`.quiet();else await P`git -C ${this.repoPath} worktree add -b ${$} ${X}`.quiet();else{if(!await this.branchExists($))throw Error(`Branch '${$}' does not exist. Use -b to create a new branch.`);await P`git -C ${this.repoPath} worktree add ${X} ${$}`.quiet()}let G=await this.loadMetadata();G.worktrees[U]={branch:$,createdAt:new Date().toISOString()},await this.saveMetadata(G);let Q=await this.getCommitHash(X);return{path:X,branch:$,commitHash:Q,createdAt:new Date}}async removeWorktree($){let J=c($),q=w(this.baseDir,J);try{await P`git -C ${this.repoPath} worktree remove ${q} --force`.quiet()}catch{try{await b1(q,{recursive:!0,force:!0})}catch{}}try{await X1(q),await b1(q,{recursive:!0,force:!0})}catch{}let U=await this.loadMetadata();delete U.worktrees[J],await this.saveMetadata(U)}async listWorktrees(){let J=(await P`git -C ${this.repoPath} worktree list --porcelain`.quiet()).stdout.toString(),q=[],U={};for(let Q of J.split(`
|
|
30
|
+
`))if(Q.startsWith("worktree ")){if(U.path)q.push(U);U={path:Q.slice(9)}}else if(Q.startsWith("HEAD "))U.commitHash=Q.slice(5);else if(Q.startsWith("branch "))U.branch=Q.slice(7).replace("refs/heads/","");if(U.path)q.push(U);let X=q.filter((Q)=>Q.path.startsWith(this.baseDir)),G=await this.loadMetadata();for(let Q of X){let S=F$(Q.path),Y=G.worktrees[S];if(Y)Q.createdAt=new Date(Y.createdAt);Q.size=await this.getDiskUsage(Q.path)}return X}async cleanup($,J=!1){let q=D$($),U=Date.now(),X=await this.listWorktrees(),G=[];for(let Q of X)if(Q.createdAt){if(U-Q.createdAt.getTime()>q)G.push(Q)}if(!J)for(let Q of G)await this.removeWorktree(Q.branch);return G}async prune(){await P`git -C ${this.repoPath} worktree prune`.quiet()}async getDiskUsage($){try{let q=(await P`du -sb ${$}`.quiet()).stdout.toString().trim(),U=parseInt(q.split("\t")[0],10);return isNaN(U)?0:U}catch{return 0}}getWorktreePath($){let J=c($);return w(this.baseDir,J)}async worktreeExists($){let J=c($),q=w(this.baseDir,J);try{return await X1(q),!0}catch{return!1}}async branchExists($){try{return await P`git -C ${this.repoPath} rev-parse --verify ${$}`.quiet(),!0}catch{return!1}}async getCommitHash($){return(await P`git -C ${$} rev-parse HEAD`.quiet()).stdout.toString().trim()}}function f($){let J=$?.baseDir||w(process.cwd(),".worktrees"),q=$?.repoPath||process.cwd();return new v1({baseDir:J,repoPath:q})}import{mkdir as y$,readFile as P$,writeFile as j$,access as I$}from"fs/promises";import{join as h1}from"path";import{homedir as A$}from"os";var g1=h1(A$(),".config","term"),G1=h1(g1,"sessions.json");async function N$(){await y$(g1,{recursive:!0})}async function Q1(){try{await I$(G1);let $=await P$(G1,"utf-8");return JSON.parse($)}catch{return{sessions:{}}}}async function u1($){await N$(),await j$(G1,JSON.stringify($,null,2))}async function l1($,J){let q=await Q1();q.sessions[$]={...J,createdAt:new Date().toISOString()},await u1(q)}async function c1($){return(await Q1()).sessions[$]||null}async function d1($){let J=await Q1();delete J.sessions[$],await u1(J)}async function p1($,J={}){try{if(await R($))console.error(`\u274C Session "${$}" already exists`),process.exit(1);let U=J.workspace||process.cwd(),X;if(J.worktree){if(!J.workspace)console.error("\u274C --worktree requires --workspace"),process.exit(1);let Q=f({baseDir:O$(J.workspace,".worktrees"),repoPath:J.workspace});if(await Q.worktreeExists($))console.error(`\u274C Worktree for "${$}" already exists`),process.exit(1);let Y=await Q.createWorktree($,!0);X=Y.path,U=Y.path,console.log(`\u2705 Worktree created at ${X}`)}if(!await A1($))console.error(`\u274C Failed to create session "${$}"`),process.exit(1);if(await H(`send-keys -t '${$}' 'cd ${U}' Enter`),X)await l1($,{worktreePath:X,workspace:J.workspace});if(console.log(`\u2705 Session "${$}" created`),U!==process.cwd())console.log(` Working directory: ${U}`);console.log(`
|
|
31
|
+
To attach: term attach ${$}`)}catch(q){console.error(`\u274C Error creating session: ${q.message}`),process.exit(1)}}async function m1($={}){try{let J=await U1();if($.json){console.log(JSON.stringify(J,null,2));return}if(J.length===0){console.log("No tmux sessions found");return}console.log("SESSION ID\t\tNAME\t\t\tWINDOWS\t\tATTACHED"),console.log("\u2500".repeat(80));for(let q of J){let U=q.attached?"yes":"no";console.log(`${q.id} ${q.name} ${q.windows} ${U}`)}}catch(J){console.error(`Error listing sessions: ${J.message}`),process.exit(1)}}import{exec as C$}from"child_process";import{promisify as k$}from"util";var x$=k$(C$);async function r1($){try{if(!await R($))console.error(`\u274C Session "${$}" not found`),process.exit(1);console.log(`\uD83D\uDCCE Attaching to session "${$}"...`),await x$(`tmux attach -t "${$}"`)}catch(J){console.error(`\u274C Error attaching to session: ${J.message}`),process.exit(1)}}import{join as v$}from"path";async function s1($,J={}){try{let q=await R($);if(!q)console.error(`\u274C Session "${$}" not found`),process.exit(1);let U=await c1($);if(await O1(q.id),U?.worktreePath&&U?.workspace&&!J.keepWorktree)await f({baseDir:v$(U.workspace,".worktrees"),repoPath:U.workspace}).removeWorktree($),console.log(`\u2705 Session "${$}" and worktree removed`);else if(U?.worktreePath&&J.keepWorktree)console.log(`\u2705 Session "${$}" removed (worktree kept at ${U.worktreePath})`);else console.log(`\u2705 Session "${$}" removed`);if(U)await d1($)}catch(q){console.error(`\u274C Error removing session: ${q.message}`),process.exit(1)}}function b($){let q=$.split(`
|
|
32
|
+
`).filter((U)=>{let X=U.trim();if(X.match(/^TMUX_MCP_START$/))return!1;if(X.match(/^TMUX_MCP_DONE_\d+$/))return!1;if(X.includes("TMUX_MCP_START"))return!1;if(X.includes("TMUX_MCP_DONE_"))return!1;if(U.includes('echo "TMUX_MCP_START"'))return!1;if(U.includes('echo "TMUX_MCP_DONE_'))return!1;if(U.includes("-bash:"))return!1;if(U.includes("warning: setlocale:"))return!1;if(U.includes("cannot change locale"))return!1;if(X==="or directory")return!1;return!0});while(q.length>0&&q[0].trim()==="")q.shift();while(q.length>0&&q[q.length-1].trim()==="")q.pop();return q.join(`
|
|
33
|
+
`)}async function i1($,J={}){let q=await R($);if(!q)throw Error(`Session "${$}" not found`);let U=await L(q.id);if(!U||U.length===0)throw Error(`No windows found in session "${$}"`);let X=await T(U[0].id);if(!X||X.length===0)throw Error(`No panes found in session "${$}"`);let G=X[0].id;if(J.range){let Y=J.range.split(":");if(Y.length===2)J.from=parseInt(Y[0],10),J.to=parseInt(Y[1],10)}if(J.all){let Y=await A(G,1e4);return b(Y)}if(J.from!==void 0&&J.to!==void 0){let Y=await A(G,1e4),B=b(Y).split(`
|
|
34
|
+
`).slice(J.from,J.to+1).join(`
|
|
35
|
+
`);if(J.reverse)return B.split(`
|
|
36
|
+
`).reverse().join(`
|
|
37
|
+
`);return B}if(J.search||J.grep){let Y=J.search||J.grep,Z=await A(G,1e4),B=b(Z).split(`
|
|
38
|
+
`);try{let K=new RegExp(Y,"i"),W=B.filter((V)=>K.test(V));if(J.reverse)return W.reverse().join(`
|
|
39
|
+
`);return W.join(`
|
|
40
|
+
`)}catch(K){throw Error(`Invalid regex pattern: ${K.message}`)}}let Q=J.lines||100,S=await A(G,Q);if(S=b(S),J.reverse)S=S.split(`
|
|
41
|
+
`).reverse().join(`
|
|
42
|
+
`);return S}async function t1($,J){let q=await R($);if(!q)throw Error(`Session "${$}" not found`);let U=await L(q.id);if(!U||U.length===0)throw Error(`No windows found in session "${$}"`);let X=await T(U[0].id);if(!X||X.length===0)throw Error(`No panes found in session "${$}"`);let G=X[0].id,Q="",S=!0,Y=setInterval(async()=>{if(!S){clearInterval(Y);return}try{let Z=await A(G,100),_=b(Z);if(_!==Q){let B=_.split(`
|
|
43
|
+
`),K=Q.split(`
|
|
44
|
+
`),W=K.length>0?K.length-1:0;B.slice(W).forEach((j)=>{if(j&&j!==K[K.length-1])J(j)}),Q=_}}catch(Z){clearInterval(Y),S=!1}},500);return()=>{S=!1,clearInterval(Y)}}async function o1($,J){try{let q={lines:J.lines?parseInt(J.lines,10):100,from:J.from?parseInt(J.from,10):void 0,to:J.to?parseInt(J.to,10):void 0,range:J.range,search:J.search,grep:J.grep,follow:J.follow,all:J.all,reverse:J.reverse};if(J.follow){console.log(`Following session "${$}" (Ctrl+C to stop)...`),console.log("");let X=await t1($,(G)=>{console.log(G)});process.on("SIGINT",()=>{X(),console.log(`
|
|
45
|
+
Stopped following`),process.exit(0)}),await new Promise(()=>{});return}let U=await i1($,q);if(J.json){let X=U.split(`
|
|
46
|
+
`);console.log(JSON.stringify({session:$,lineCount:X.length,content:X},null,2));return}console.log(U)}catch(q){console.error(`Error reading session logs: ${q.message}`),process.exit(1)}}async function a1($,J){try{let q=await R($);if(!q)console.error(`\u274C Session "${$}" not found`),process.exit(1);let U=await L(q.id);if(!U||U.length===0)console.error(`\u274C No windows found in session "${$}"`),process.exit(1);let X=await T(U[0].id);if(!X||X.length===0)console.error(`\u274C No panes found in session "${$}"`),process.exit(1);let G=X[0].id;await l(G,J),console.log(`\u2705 Command sent to session "${$}"`)}catch(q){console.error(`\u274C Error executing command: ${q.message}`),process.exit(1)}}async function n1($,J){try{let q=await R($);if(!q)console.error(`\u274C Session "${$}" not found`),process.exit(1);let U=await L(q.id);if(!U||U.length===0)console.error(`\u274C No windows found in session "${$}"`),process.exit(1);let X=await T(U[0].id);if(!X||X.length===0)console.error(`\u274C No panes found in session "${$}"`),process.exit(1);let G=X[0].id;await l(G,J,!1,!0),console.log(`\u2705 Keys sent to session "${$}"`)}catch(q){console.error(`\u274C Error sending keys: ${q.message}`),process.exit(1)}}import{join as d$}from"path";async function e1($,J,q={}){try{let U=await R($);if(!U)console.error(`\u274C Session "${$}" not found`),process.exit(1);let X=await L(U.id);if(!X||X.length===0)console.error(`\u274C No windows found in session "${$}"`),process.exit(1);let G=await T(X[0].id);if(!G||G.length===0)console.error(`\u274C No panes found in session "${$}"`),process.exit(1);let Q=G[0].id,S=J==="h"?"horizontal":"vertical",Y;if(q.worktree){if(!q.workspace)console.error("\u274C --worktree requires --workspace"),process.exit(1);let _=f({baseDir:d$(q.workspace,".worktrees"),repoPath:q.workspace});if(!await _.worktreeExists(q.worktree)){let K=await _.createWorktree(q.worktree,!0);console.log(`\u2705 Worktree created at ${K.path}`)}Y=_.getWorktreePath(q.worktree)}else if(q.workspace)Y=q.workspace;let Z=await C1(Q,S);if(!Z)console.error("\u274C Failed to split pane"),process.exit(1);if(Y&&Z)await H(`send-keys -t '${Z.id}' 'cd ${Y}' Enter`);if(console.log(`\u2705 Pane split ${S}ly in session "${$}"`),Y)console.log(` Working directory: ${Y}`)}catch(U){console.error(`\u274C Error splitting pane: ${U.message}`),process.exit(1)}}async function $0($,J){await H(`set-hook -g ${$} '${J.replace(/'/g,"'\\''")}'`)}async function J0($){await H(`set-hook -gu ${$}`)}async function q0(){let $=["after-bind-key","after-capture-pane","after-copy-mode","after-display-message","after-display-panes","after-kill-pane","after-list-buffers","after-list-clients","after-list-keys","after-list-panes","after-list-sessions","after-list-windows","after-load-buffer","after-lock-server","after-new-session","after-new-window","after-paste-buffer","after-pipe-pane","after-queue","after-refresh-client","after-rename-session","after-rename-window","after-resize-pane","after-resize-window","after-save-buffer","after-select-layout","after-select-pane","after-select-window","after-send-keys","after-set-buffer","after-set-environment","after-set-option","after-show-environment","after-show-messages","after-show-options","after-split-window","after-unbind-key","alert-activity","alert-bell","alert-silence","client-attached","client-detached","client-resized","client-session-changed","pane-died","pane-exited","pane-focus-in","pane-focus-out","pane-mode-changed","pane-set-clipboard","session-closed","session-created","session-renamed","session-window-changed","window-linked","window-pane-changed","window-renamed","window-unlinked"],J=[];for(let q of $)try{let U=await H(`show-hooks -g ${q}`);if(U.trim()){let X=U.trim().split(" ");if(X.length>=2)J.push({event:X[0],command:X.slice(1).join(" ")})}}catch(U){continue}return J}async function U0($,J){try{await $0($,J),console.log(`\u2705 Hook set: ${$} \u2192 ${J}`)}catch(q){console.error(`\u274C Error setting hook: ${q.message}`),process.exit(1)}}async function X0(){try{let $=await q0();if($.length===0){console.log("No hooks configured");return}console.log("EVENT\t\t\t\tCOMMAND"),console.log("\u2500".repeat(80));for(let J of $)console.log(`${J.event} ${J.command}`)}catch($){console.error(`\u274C Error listing hooks: ${$.message}`),process.exit(1)}}async function G0($){try{await J0($),console.log(`\u2705 Hook removed: ${$}`)}catch(J){console.error(`\u274C Error removing hook: ${J.message}`),process.exit(1)}}async function Q0($,J={}){try{let q=await R($);if(!q)console.error(`Session "${$}" not found`),process.exit(1);let U=await L(q.id);if(J.json){console.log(JSON.stringify(U,null,2));return}if(U.length===0){console.log("No windows found");return}console.log("WINDOW ID\t\tNAME\t\t\tACTIVE"),console.log("\u2500".repeat(60));for(let X of U){let G=X.active?"yes":"no";console.log(`${X.id} ${X.name} ${G}`)}}catch(q){console.error(`Error listing windows: ${q.message}`),process.exit(1)}}async function S0($,J){try{let q=await R($);if(!q)console.error(`Session "${$}" not found`),process.exit(1);let U=await N1(q.id,J);if(U)console.log(`Window created: ${U.id}`);else console.error("Failed to create window"),process.exit(1)}catch(q){console.error(`Error creating window: ${q.message}`),process.exit(1)}}async function Y0($){try{await w1($),console.log(`Window removed: ${$}`)}catch(J){console.error(`Error removing window: ${J.message}`),process.exit(1)}}async function Z0($,J={}){try{let q=await R($);if(!q)console.error(`Session "${$}" not found`),process.exit(1);let U=await L(q.id);if(U.length===0){if(J.json)console.log("[]");else console.log("No panes found");return}let X=[];for(let G of U){let Q=await T(G.id);for(let S of Q)X.push({id:S.id,windowId:G.id,windowName:G.name,title:S.title,active:S.active})}if(J.json){console.log(JSON.stringify(X,null,2));return}if(X.length===0){console.log("No panes found");return}console.log("PANE ID\t\tWINDOW\t\t\tTITLE\t\t\tACTIVE"),console.log("\u2500".repeat(80));for(let G of X){let Q=G.active?"yes":"no",S=G.title||"-";console.log(`${G.id} ${G.windowName} ${S} ${Q}`)}}catch(q){console.error(`Error listing panes: ${q.message}`),process.exit(1)}}async function _0($){try{await f1($),console.log(`Pane removed: ${$}`)}catch(J){console.error(`Error removing pane: ${J.message}`),process.exit(1)}}async function W0($,J={}){try{if(J.command){await t$(J.command,J.json);return}let q=await R($);if(!q)console.error(`Session "${$}" not found`),process.exit(1);let U=await L(q.id),X=0;for(let S of U){let Y=await T(S.id);X+=Y.length}let G="idle",Q={session:q.name,id:q.id,attached:q.attached,windows:U.length,panes:X,state:G};if(J.json){console.log(JSON.stringify(Q,null,2));return}console.log(`Session: ${Q.session}`),console.log(`ID: ${Q.id}`),console.log(`Attached: ${Q.attached?"yes":"no"}`),console.log(`Windows: ${Q.windows}`),console.log(`Panes: ${Q.panes}`),console.log(`State: ${Q.state}`)}catch(q){console.error(`Error getting status: ${q.message}`),process.exit(1)}}async function t$($,J){try{let q=await k1($);if(!q)console.error(`Command "${$}" not found`),process.exit(1);let U={id:q.id,paneId:q.paneId,command:q.command,status:q.status,exitCode:q.exitCode,startTime:q.startTime.toISOString(),result:q.result};if(J){console.log(JSON.stringify(U,null,2));return}if(console.log(`Command: ${U.id}`),console.log(`Status: ${U.status}`),console.log(`Exit Code: ${U.exitCode??"N/A"}`),console.log(`Start Time: ${U.startTime}`),U.result)console.log(`
|
|
47
|
+
Output:
|
|
48
|
+
${U.result}`)}catch(q){console.error(`Error getting command status: ${q.message}`),process.exit(1)}}import{homedir as H0}from"os";import{join as D}from"path";import{existsSync as N,readFileSync as R0,writeFileSync as a$,mkdirSync as n$,appendFileSync as S1}from"fs";import*as E0 from"readline";function B0(){return`# Warp-like keyboard shortcuts (generated by genie-cli)
|
|
49
|
+
# To use: add to ~/.tmux.conf or source this file
|
|
50
|
+
|
|
51
|
+
# Ctrl+T: New window (tab) in current session
|
|
52
|
+
bind-key -n C-t new-window
|
|
53
|
+
|
|
54
|
+
# Ctrl+S: Vertical split (requires stty -ixon in shell rc)
|
|
55
|
+
bind-key -n C-s split-window -v
|
|
56
|
+
|
|
57
|
+
# Alt+S: Horizontal split
|
|
58
|
+
bind-key -n M-s split-window -h
|
|
59
|
+
`}function K0(){return`# Warp-like extra keys (generated by genie-cli)
|
|
60
|
+
# To use: add to ~/.termux/termux.properties
|
|
61
|
+
|
|
62
|
+
# Extra keys row with F-keys for shortcuts
|
|
63
|
+
# F1=New Tab, F2=VSplit, F3=HSplit
|
|
64
|
+
extra-keys = [['ESC','TAB','CTRL','ALT','F1','F2','F3']]
|
|
65
|
+
`}function e$(){return`# Warp-like shortcuts (generated by genie-cli)
|
|
66
|
+
# To use: add to ~/.bashrc or ~/.zshrc
|
|
67
|
+
|
|
68
|
+
# Disable Ctrl+S flow control (required for Ctrl+S to work in tmux)
|
|
69
|
+
stty -ixon 2>/dev/null
|
|
70
|
+
|
|
71
|
+
# Genie shortcuts (for Termux extra keys F1-F3)
|
|
72
|
+
genie-new-tab() {
|
|
73
|
+
local session
|
|
74
|
+
session=$(tmux display-message -p '#S' 2>/dev/null)
|
|
75
|
+
if [ -n "$session" ]; then
|
|
76
|
+
tmux new-window
|
|
77
|
+
else
|
|
78
|
+
echo "Not in a tmux session"
|
|
79
|
+
fi
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
genie-vsplit() {
|
|
83
|
+
if tmux display-message -p '#S' >/dev/null 2>&1; then
|
|
84
|
+
tmux split-window -v
|
|
85
|
+
else
|
|
86
|
+
echo "Not in a tmux session"
|
|
87
|
+
fi
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
genie-hsplit() {
|
|
91
|
+
if tmux display-message -p '#S' >/dev/null 2>&1; then
|
|
92
|
+
tmux split-window -h
|
|
93
|
+
else
|
|
94
|
+
echo "Not in a tmux session"
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Bind F1-F3 to genie shortcuts (works in Termux)
|
|
99
|
+
bind -x '"eOP":"genie-new-tab"' 2>/dev/null # F1
|
|
100
|
+
bind -x '"eOQ":"genie-vsplit"' 2>/dev/null # F2
|
|
101
|
+
bind -x '"eOR":"genie-hsplit"' 2>/dev/null # F3
|
|
102
|
+
`}function $6(){console.log(`
|
|
103
|
+
Warp-like Terminal Shortcuts for tmux + Termux
|
|
104
|
+
|
|
105
|
+
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
106
|
+
\u2502 Shortcut \u2502 Action \u2502
|
|
107
|
+
\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
|
|
108
|
+
\u2502 Ctrl+T \u2502 New tab (window) in current session \u2502
|
|
109
|
+
\u2502 Ctrl+S \u2502 Vertical split in current session \u2502
|
|
110
|
+
\u2502 Alt+S \u2502 Horizontal split in current session \u2502
|
|
111
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
112
|
+
|
|
113
|
+
Termux Extra Keys (F1-F3):
|
|
114
|
+
F1 \u2192 New tab F2 \u2192 Vertical split
|
|
115
|
+
F3 \u2192 Horizontal split
|
|
116
|
+
|
|
117
|
+
Commands:
|
|
118
|
+
term shortcuts --tmux Output tmux.conf snippet
|
|
119
|
+
term shortcuts --termux Output termux.properties snippet
|
|
120
|
+
term shortcuts --install Install to config files
|
|
121
|
+
`)}async function C($){let J=E0.createInterface({input:process.stdin,output:process.stdout});return new Promise((q)=>{J.question($,(U)=>{J.close(),q(U.trim().toLowerCase())})})}function O($,J){if(!N($))return!1;return R0($,"utf-8").includes(J)}async function J6(){let $=H0(),J="generated by genie-cli";console.log(`Installing Warp-like shortcuts...
|
|
122
|
+
`);let q=D($,".tmux.conf");if(O(q,"generated by genie-cli"))console.log("\u2713 tmux.conf already has genie shortcuts");else if(await C(`Add shortcuts to ${q}? [Y/n] `)!=="n"){let Y=`
|
|
123
|
+
`+B0();S1(q,Y),console.log(`\u2705 Added to ${q}`)}else console.log("\u23ED\uFE0F Skipped tmux.conf");let U=N(D($,".zshrc"))?D($,".zshrc"):D($,".bashrc");if(O(U,"generated by genie-cli"))console.log(`\u2713 ${U} already has genie shortcuts`);else if(await C(`Add shell functions to ${U}? [Y/n] `)!=="n"){let Y=`
|
|
124
|
+
`+e$();S1(U,Y),console.log(`\u2705 Added to ${U}`)}else console.log(`\u23ED\uFE0F Skipped ${U}`);let X=D($,".termux"),G=D(X,"termux.properties"),Q=N(X)||process.env.TERMUX_VERSION;if(Q)if(O(G,"generated by genie-cli"))console.log("\u2713 termux.properties already has genie shortcuts");else if(await C(`Add extra keys to ${G}? [Y/n] `)!=="n"){if(!N(X))n$(X,{recursive:!0});let Y=`
|
|
125
|
+
`+K0();S1(G,Y),console.log(`\u2705 Added to ${G}`),console.log(" Run: termux-reload-settings")}else console.log("\u23ED\uFE0F Skipped termux.properties");if(console.log(`
|
|
126
|
+
\u2705 Installation complete!`),console.log(`
|
|
127
|
+
Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.log(" 2. Restart your shell or run: source ~/.bashrc"),Q)console.log(" 3. Reload Termux: termux-reload-settings")}function Y8($){return O($,"generated by genie-cli")}function Y1($,J){if(!N($))return!1;let q=R0($,"utf-8");if(!q.includes(J))return!1;let U=q.split(`
|
|
128
|
+
`),X=[],G=!1,Q=-1;for(let Y=0;Y<U.length;Y++){let Z=U[Y];if(Z.includes(J)&&!G){if(G=!0,Q===-1&&X.length>0&&X[X.length-1].trim()==="")X.pop();continue}if(G){if(Z.trim()===""&&Y+1<U.length&&!U[Y+1].includes("genie")){G=!1;continue}if(!(Z.includes("genie")||Z.includes("Ctrl+")||Z.includes("split-window")||Z.includes("new-window")||Z.includes("stty -ixon")||Z.includes("Warp-like")||Z.includes("bind-key -n")||Z.includes("extra-keys")||Z.includes("F1=")||Z.includes("bind -x")||Z.startsWith("#")&&U[Y-1]?.includes("genie"))&&Z.trim()!=="")G=!1,X.push(Z);continue}X.push(Z)}while(X.length>0&&X[X.length-1].trim()==="")X.pop();let S=X.length>0?X.join(`
|
|
129
|
+
`)+`
|
|
130
|
+
`:"";return a$($,S),!0}async function Z8(){let $=H0(),J="generated by genie-cli";console.log(`Uninstalling Warp-like shortcuts...
|
|
131
|
+
`);let q=D($,".tmux.conf");if(!O(q,"generated by genie-cli"))console.log("\u2713 tmux.conf has no genie shortcuts");else if(await C(`Remove shortcuts from ${q}? [Y/n] `)!=="n"){if(Y1(q,"generated by genie-cli"))console.log(`\u2705 Removed from ${q}`)}else console.log("\u23ED\uFE0F Skipped tmux.conf");let U=D($,".zshrc"),X=D($,".bashrc");for(let Y of[U,X]){if(!N(Y))continue;if(!O(Y,"generated by genie-cli"))console.log(`\u2713 ${Y} has no genie shortcuts`);else if(await C(`Remove shell functions from ${Y}? [Y/n] `)!=="n"){if(Y1(Y,"generated by genie-cli"))console.log(`\u2705 Removed from ${Y}`)}else console.log(`\u23ED\uFE0F Skipped ${Y}`)}let G=D($,".termux"),Q=D(G,"termux.properties"),S=N(G)||process.env.TERMUX_VERSION;if(S)if(!O(Q,"generated by genie-cli"))console.log("\u2713 termux.properties has no genie shortcuts");else if(await C(`Remove extra keys from ${Q}? [Y/n] `)!=="n"){if(Y1(Q,"generated by genie-cli"))console.log(`\u2705 Removed from ${Q}`),console.log(" Run: termux-reload-settings")}else console.log("\u23ED\uFE0F Skipped termux.properties");if(console.log(`
|
|
132
|
+
\u2705 Uninstallation complete!`),console.log(`
|
|
133
|
+
Next steps:`),console.log(" 1. Reload tmux: tmux source ~/.tmux.conf"),console.log(" 2. Restart your shell or run: source ~/.bashrc"),S)console.log(" 3. Reload Termux: termux-reload-settings")}async function z0($){if($.tmux)console.log(B0());else if($.termux)console.log(K0());else if($.install)await J6();else $6()}var M=new j1;M.name("term").description(`AI-friendly terminal orchestration (tmux wrapper)
|
|
134
|
+
|
|
135
|
+
Workflow: new \u2192 exec \u2192 read \u2192 rm
|
|
136
|
+
Full control: window new/ls/rm, pane ls/rm, split, status`).version("0.2.0");M.command("new <name>").description("Create a new tmux session").option("-d, --workspace <path>","Working directory for the session").option("-w, --worktree","Create git worktree in .worktrees/<name>/").action(async($,J)=>{await p1($,J)});M.command("ls").description("List all tmux sessions").option("--json","Output as JSON").action(async($)=>{await m1($)});M.command("attach <name>").description("Attach to a tmux session").action(async($)=>{await r1($)});M.command("rm <name>").description("Remove a tmux session").option("--keep-worktree","Keep worktree folder when removing session").action(async($,J)=>{await s1($,J)});M.command("read <session>").description("Read logs from a tmux session").option("-n, --lines <number>","Number of lines to read (default: 100)","100").option("--from <line>","Start line number").option("--to <line>","End line number").option("--range <range>","Line range (e.g., 100:200)").option("--search <pattern>","Search for pattern").option("--grep <pattern>","Regex search pattern").option("-f, --follow","Follow mode (live tail)").option("--all","Export entire scrollback buffer").option("--reverse","Reverse chronological (newest first)").option("--json","Output as JSON").action(async($,J)=>{await o1($,J)});M.command("exec <session> <command...>").description("Execute command in a tmux session").action(async($,J)=>{await a1($,J.join(" "))});M.command("send <session> <keys>").description("Send raw keys to a tmux session").action(async($,J)=>{await n1($,J)});M.command("split <session> [direction]").description("Split pane in a tmux session (h=horizontal, v=vertical)").option("-d, --workspace <path>","Working directory for the new pane").option("-w, --worktree <branch>","Create git worktree in .worktrees/<branch>/").action(async($,J,q)=>{await e1($,J,q)});M.command("status <session>").description("Check session state (idle/busy, pane count)").option("--command <id>","Check specific command status").option("--json","Output as JSON").action(async($,J)=>{await W0($,J)});var Z1=M.command("window").description("Manage tmux windows");Z1.command("new <session> <name>").description("Create a new window in session").action(async($,J)=>{await S0($,J)});Z1.command("ls <session>").description("List windows in session").option("--json","Output as JSON").action(async($,J)=>{await Q0($,J)});Z1.command("rm <window-id>").description("Remove window by ID").action(async($)=>{await Y0($)});var L0=M.command("pane").description("Manage tmux panes");L0.command("ls <session>").description("List all panes in session").option("--json","Output as JSON").action(async($,J)=>{await Z0($,J)});L0.command("rm <pane-id>").description("Remove pane by ID").action(async($)=>{await _0($)});var _1=M.command("hook").description("Manage tmux hooks");_1.command("set <event> <command>").description("Set a tmux hook").action(async($,J)=>{await U0($,J)});_1.command("list").description("List all tmux hooks").action(async()=>{await X0()});_1.command("rm <event>").description("Remove a tmux hook").action(async($)=>{await G0($)});M.command("shortcuts").description("Warp-like keyboard shortcuts for tmux/Termux").option("--tmux","Output tmux.conf snippet").option("--termux","Output termux.properties snippet").option("--install","Install to config files (interactive)").action(async($)=>{await z0($)});M.parse();
|
package/install.sh
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Genie CLI Installer/Updater
|
|
5
|
+
# https://github.com/namastexlabs/genie-cli
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# Fresh install: curl -fsSL https://raw.githubusercontent.com/namastexlabs/genie-cli/main/install.sh | bash
|
|
9
|
+
# Update: Run install.sh again OR `genie update`
|
|
10
|
+
|
|
11
|
+
# Colors
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
CYAN='\033[0;36m'
|
|
16
|
+
BOLD='\033[1m'
|
|
17
|
+
DIM='\033[2m'
|
|
18
|
+
NC='\033[0m' # No Color
|
|
19
|
+
|
|
20
|
+
# Paths
|
|
21
|
+
GENIE_HOME="${GENIE_HOME:-$HOME/.genie}"
|
|
22
|
+
GENIE_SRC="$GENIE_HOME/src"
|
|
23
|
+
GENIE_BIN="$GENIE_HOME/bin"
|
|
24
|
+
LOCAL_BIN="$HOME/.local/bin"
|
|
25
|
+
REPO_URL="https://github.com/namastexlabs/genie-cli.git"
|
|
26
|
+
|
|
27
|
+
# Detect mode: install vs update
|
|
28
|
+
if [[ -d "$GENIE_SRC/.git" ]]; then
|
|
29
|
+
MODE="update"
|
|
30
|
+
else
|
|
31
|
+
MODE="install"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
35
|
+
# Helpers
|
|
36
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
log() {
|
|
39
|
+
echo -e "${GREEN}▸${NC} $1"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
warn() {
|
|
43
|
+
echo -e "${YELLOW}⚠${NC} $1"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
error() {
|
|
47
|
+
echo -e "${RED}✖${NC} $1"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
success() {
|
|
51
|
+
echo -e "${GREEN}✔${NC} $1"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
header() {
|
|
55
|
+
echo
|
|
56
|
+
echo -e "${BOLD}$1${NC}"
|
|
57
|
+
echo
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
check_command() {
|
|
61
|
+
command -v "$1" &> /dev/null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Run a command with visible output
|
|
65
|
+
run() {
|
|
66
|
+
echo -e "${DIM}$ $*${NC}"
|
|
67
|
+
"$@"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
# Prerequisite Checks & Installation
|
|
72
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
check_prerequisites() {
|
|
75
|
+
local missing=()
|
|
76
|
+
|
|
77
|
+
if ! check_command git; then
|
|
78
|
+
missing+=("git")
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
if ! check_command curl; then
|
|
82
|
+
missing+=("curl")
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
86
|
+
error "Missing required tools: ${missing[*]}"
|
|
87
|
+
echo "Please install them and run this script again."
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
install_nvm_and_node() {
|
|
93
|
+
# Check if Node 22+ is already available
|
|
94
|
+
if check_command node; then
|
|
95
|
+
local node_version
|
|
96
|
+
node_version=$(node --version 2>/dev/null | sed 's/v//' | cut -d. -f1)
|
|
97
|
+
if [[ "$node_version" -ge 22 ]]; then
|
|
98
|
+
success "Node.js v$(node --version | sed 's/v//') already installed"
|
|
99
|
+
return 0
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Check if nvm is installed
|
|
104
|
+
if [[ -z "$NVM_DIR" ]]; then
|
|
105
|
+
export NVM_DIR="$HOME/.nvm"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [[ ! -d "$NVM_DIR" ]]; then
|
|
109
|
+
log "Installing nvm..."
|
|
110
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
|
|
111
|
+
|
|
112
|
+
# Source nvm immediately
|
|
113
|
+
export NVM_DIR="$HOME/.nvm"
|
|
114
|
+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
115
|
+
else
|
|
116
|
+
# Source existing nvm
|
|
117
|
+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Install Node 22
|
|
121
|
+
log "Installing Node.js 22 via nvm..."
|
|
122
|
+
nvm install 22
|
|
123
|
+
nvm use 22
|
|
124
|
+
nvm alias default 22
|
|
125
|
+
|
|
126
|
+
success "Node.js $(node --version) installed"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
install_bun() {
|
|
130
|
+
if check_command bun; then
|
|
131
|
+
success "Bun $(bun --version) already installed"
|
|
132
|
+
return 0
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
log "Installing Bun..."
|
|
136
|
+
curl -fsSL https://bun.sh/install | bash
|
|
137
|
+
|
|
138
|
+
# Add bun to PATH for this session
|
|
139
|
+
export BUN_INSTALL="$HOME/.bun"
|
|
140
|
+
export PATH="$BUN_INSTALL/bin:$PATH"
|
|
141
|
+
|
|
142
|
+
if check_command bun; then
|
|
143
|
+
success "Bun $(bun --version) installed"
|
|
144
|
+
else
|
|
145
|
+
error "Bun installation failed"
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
install_tmux() {
|
|
151
|
+
if check_command tmux; then
|
|
152
|
+
success "tmux $(tmux -V | cut -d' ' -f2) already installed"
|
|
153
|
+
return 0
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
log "Installing tmux..."
|
|
157
|
+
|
|
158
|
+
# Detect package manager
|
|
159
|
+
if check_command apt; then
|
|
160
|
+
sudo apt update && sudo apt install -y tmux
|
|
161
|
+
elif check_command dnf; then
|
|
162
|
+
sudo dnf install -y tmux
|
|
163
|
+
elif check_command yum; then
|
|
164
|
+
sudo yum install -y tmux
|
|
165
|
+
elif check_command pacman; then
|
|
166
|
+
sudo pacman -S --noconfirm tmux
|
|
167
|
+
elif check_command brew; then
|
|
168
|
+
brew install tmux
|
|
169
|
+
else
|
|
170
|
+
warn "Could not detect package manager. Please install tmux manually."
|
|
171
|
+
warn "Visit: https://github.com/tmux/tmux/wiki/Installing"
|
|
172
|
+
return 1
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
if check_command tmux; then
|
|
176
|
+
success "tmux $(tmux -V | cut -d' ' -f2) installed"
|
|
177
|
+
else
|
|
178
|
+
error "tmux installation failed"
|
|
179
|
+
return 1
|
|
180
|
+
fi
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
install_claude_code() {
|
|
184
|
+
if check_command claude; then
|
|
185
|
+
success "Claude Code CLI already installed"
|
|
186
|
+
return 0
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
log "Installing Claude Code CLI..."
|
|
190
|
+
|
|
191
|
+
# Ensure npm is available (should be after nvm install)
|
|
192
|
+
if ! check_command npm; then
|
|
193
|
+
error "npm not found. Please ensure Node.js is installed."
|
|
194
|
+
return 1
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
npm install -g @anthropic-ai/claude-code
|
|
198
|
+
|
|
199
|
+
if check_command claude; then
|
|
200
|
+
success "Claude Code CLI installed"
|
|
201
|
+
else
|
|
202
|
+
warn "Claude Code installed but not in PATH yet"
|
|
203
|
+
warn "You may need to restart your shell"
|
|
204
|
+
fi
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
208
|
+
# Build & Install
|
|
209
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
clone_repo() {
|
|
212
|
+
log "Cloning genie-cli repository..."
|
|
213
|
+
mkdir -p "$GENIE_HOME"
|
|
214
|
+
git clone "$REPO_URL" "$GENIE_SRC"
|
|
215
|
+
success "Repository cloned to $GENIE_SRC"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
update_repo() {
|
|
219
|
+
log "Updating genie-cli..."
|
|
220
|
+
cd "$GENIE_SRC"
|
|
221
|
+
git fetch origin
|
|
222
|
+
git reset --hard origin/main
|
|
223
|
+
success "Repository updated to latest main"
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
build_project() {
|
|
227
|
+
log "Building genie-cli..."
|
|
228
|
+
cd "$GENIE_SRC"
|
|
229
|
+
|
|
230
|
+
# Install dependencies
|
|
231
|
+
bun install
|
|
232
|
+
|
|
233
|
+
# Build
|
|
234
|
+
bun run build
|
|
235
|
+
|
|
236
|
+
success "Build complete"
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
install_binaries() {
|
|
240
|
+
log "Installing binaries..."
|
|
241
|
+
|
|
242
|
+
# Create directories
|
|
243
|
+
mkdir -p "$GENIE_BIN"
|
|
244
|
+
mkdir -p "$LOCAL_BIN"
|
|
245
|
+
|
|
246
|
+
# Copy built files to ~/.genie/bin
|
|
247
|
+
cp "$GENIE_SRC/dist/genie.js" "$GENIE_BIN/"
|
|
248
|
+
cp "$GENIE_SRC/dist/term.js" "$GENIE_BIN/"
|
|
249
|
+
cp "$GENIE_SRC/dist/claudio.js" "$GENIE_BIN/"
|
|
250
|
+
chmod +x "$GENIE_BIN"/*.js
|
|
251
|
+
|
|
252
|
+
# Create symlinks in ~/.local/bin
|
|
253
|
+
ln -sf "$GENIE_BIN/genie.js" "$LOCAL_BIN/genie"
|
|
254
|
+
ln -sf "$GENIE_BIN/term.js" "$LOCAL_BIN/term"
|
|
255
|
+
ln -sf "$GENIE_BIN/claudio.js" "$LOCAL_BIN/claudio"
|
|
256
|
+
|
|
257
|
+
success "Binaries installed to $GENIE_BIN"
|
|
258
|
+
success "Symlinks created in $LOCAL_BIN"
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
ensure_path() {
|
|
262
|
+
# Check if ~/.local/bin is in PATH
|
|
263
|
+
if [[ ":$PATH:" != *":$LOCAL_BIN:"* ]]; then
|
|
264
|
+
warn "$LOCAL_BIN is not in your PATH"
|
|
265
|
+
echo
|
|
266
|
+
echo "Add this to your shell profile (~/.bashrc or ~/.zshrc):"
|
|
267
|
+
echo -e "${CYAN} export PATH=\"\$HOME/.local/bin:\$PATH\"${NC}"
|
|
268
|
+
echo
|
|
269
|
+
fi
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
run_setup() {
|
|
273
|
+
log "Running genie setup..."
|
|
274
|
+
echo
|
|
275
|
+
|
|
276
|
+
# Run quick setup
|
|
277
|
+
if check_command genie; then
|
|
278
|
+
genie setup --quick
|
|
279
|
+
else
|
|
280
|
+
# Fallback: run directly
|
|
281
|
+
"$GENIE_BIN/genie.js" setup --quick
|
|
282
|
+
fi
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
286
|
+
# Main
|
|
287
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
main() {
|
|
290
|
+
echo
|
|
291
|
+
echo -e "${BOLD}🧞 Genie CLI ${MODE^}er${NC}"
|
|
292
|
+
echo -e "${DIM}────────────────────────────────────${NC}"
|
|
293
|
+
echo
|
|
294
|
+
|
|
295
|
+
if [[ "$MODE" == "update" ]]; then
|
|
296
|
+
# Update mode: just pull and rebuild
|
|
297
|
+
header "Updating Genie CLI..."
|
|
298
|
+
|
|
299
|
+
update_repo
|
|
300
|
+
build_project
|
|
301
|
+
install_binaries
|
|
302
|
+
|
|
303
|
+
echo
|
|
304
|
+
echo -e "${DIM}────────────────────────────────────${NC}"
|
|
305
|
+
success "Genie CLI updated successfully!"
|
|
306
|
+
echo
|
|
307
|
+
echo "Commands available:"
|
|
308
|
+
echo -e " ${CYAN}genie${NC} - Setup and utilities"
|
|
309
|
+
echo -e " ${CYAN}term${NC} - Terminal orchestration"
|
|
310
|
+
echo -e " ${CYAN}claudio${NC} - Claude profile manager"
|
|
311
|
+
echo
|
|
312
|
+
|
|
313
|
+
else
|
|
314
|
+
# Fresh install mode
|
|
315
|
+
header "Checking prerequisites..."
|
|
316
|
+
|
|
317
|
+
check_prerequisites
|
|
318
|
+
install_nvm_and_node
|
|
319
|
+
install_bun
|
|
320
|
+
install_tmux || true # Don't fail if tmux fails
|
|
321
|
+
install_claude_code || true # Don't fail if claude fails
|
|
322
|
+
|
|
323
|
+
header "Installing Genie CLI..."
|
|
324
|
+
|
|
325
|
+
clone_repo
|
|
326
|
+
build_project
|
|
327
|
+
install_binaries
|
|
328
|
+
ensure_path
|
|
329
|
+
|
|
330
|
+
header "Setting up Genie..."
|
|
331
|
+
|
|
332
|
+
run_setup
|
|
333
|
+
|
|
334
|
+
echo
|
|
335
|
+
echo -e "${DIM}────────────────────────────────────${NC}"
|
|
336
|
+
success "Genie CLI installed successfully!"
|
|
337
|
+
echo
|
|
338
|
+
echo "Commands available:"
|
|
339
|
+
echo -e " ${CYAN}genie${NC} - Setup and utilities"
|
|
340
|
+
echo -e " ${CYAN}term${NC} - Terminal orchestration"
|
|
341
|
+
echo -e " ${CYAN}claudio${NC} - Claude profile manager"
|
|
342
|
+
echo
|
|
343
|
+
echo "Get started:"
|
|
344
|
+
echo -e " ${CYAN}genie --help${NC}"
|
|
345
|
+
echo -e " ${CYAN}term --help${NC}"
|
|
346
|
+
echo -e " ${CYAN}claudio --help${NC}"
|
|
347
|
+
echo
|
|
348
|
+
fi
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
main "$@"
|