skillo 0.2.6 → 0.2.8
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 +198 -198
- package/dist/api-client-BF6GDR7Q.js +12 -0
- package/dist/{chunk-WJKZWKER.js → chunk-63FVALWX.js} +1 -1
- package/dist/chunk-63FVALWX.js.map +1 -0
- package/dist/chunk-6GOJPFZ7.js +113 -0
- package/dist/chunk-6GOJPFZ7.js.map +1 -0
- package/dist/chunk-6UGTWBUW.js +89 -0
- package/dist/chunk-6UGTWBUW.js.map +1 -0
- package/dist/{chunk-2CVEPT6U.js → chunk-73NUWYUO.js} +2 -2
- package/dist/chunk-73NUWYUO.js.map +1 -0
- package/dist/chunk-QIV4VIXA.js +221 -0
- package/dist/chunk-QIV4VIXA.js.map +1 -0
- package/dist/{chunk-CPL3P2OF.js → chunk-QUXHHRRK.js} +2 -2
- package/dist/chunk-QUXHHRRK.js.map +1 -0
- package/dist/{chunk-ODOZM4QV.js → chunk-RQ2SC5HW.js} +72 -10
- package/dist/chunk-RQ2SC5HW.js.map +1 -0
- package/dist/chunk-U53QWUOR.js +727 -0
- package/dist/chunk-U53QWUOR.js.map +1 -0
- package/dist/chunk-VAQ73XPE.js +68 -0
- package/dist/chunk-VAQ73XPE.js.map +1 -0
- package/dist/chunk-XLJGCOVT.js +975 -0
- package/dist/chunk-XLJGCOVT.js.map +1 -0
- package/dist/{claude-watcher-N6GN6WHJ.js → claude-watcher-WKGBJYKN.js} +65 -3
- package/dist/claude-watcher-WKGBJYKN.js.map +1 -0
- package/dist/cli.js +495 -1846
- package/dist/cli.js.map +1 -1
- package/dist/{config-P5EM5L7N.js → config-ZOKAP2LJ.js} +3 -3
- package/dist/daemon-6DTCMOJB.js +28 -0
- package/dist/daemon-runner.js +338 -71
- package/dist/daemon-runner.js.map +1 -1
- package/dist/database-KQY5OSCS.js +9 -0
- package/dist/git-OGUSYBJS.js +16 -0
- package/dist/git-OGUSYBJS.js.map +1 -0
- package/dist/git-OUAHIOY2.js +110 -0
- package/dist/git-OUAHIOY2.js.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/{paths-INOKEM66.js → paths-MPOZBOKE.js} +2 -2
- package/dist/paths-MPOZBOKE.js.map +1 -0
- package/dist/project-OFU2W6MH.js +19 -0
- package/dist/project-OFU2W6MH.js.map +1 -0
- package/dist/shell-NZABRJLA.js +16 -0
- package/dist/shell-NZABRJLA.js.map +1 -0
- package/dist/skill-installer-F67OAOQN.js +121 -0
- package/dist/skill-installer-F67OAOQN.js.map +1 -0
- package/dist/{skill-usage-detector-EO26MRYV.js → skill-usage-detector-MSW5VWQZ.js} +2 -2
- package/dist/skill-usage-detector-MSW5VWQZ.js.map +1 -0
- package/dist/tray-WKFGUUTO.js +346 -0
- package/dist/tray-WKFGUUTO.js.map +1 -0
- package/package.json +62 -63
- package/scripts/postinstall.mjs +415 -364
- package/scripts/tray-helper-darwin +0 -0
- package/scripts/tray-helper-darwin.swift +180 -180
- package/scripts/tray-helper-linux.py +322 -0
- package/scripts/tray-helper-windows.cs +322 -0
- package/dist/api-client-KUQW7FSC.js +0 -12
- package/dist/chunk-2CVEPT6U.js.map +0 -1
- package/dist/chunk-CPL3P2OF.js.map +0 -1
- package/dist/chunk-ODOZM4QV.js.map +0 -1
- package/dist/chunk-WJKZWKER.js.map +0 -1
- package/dist/claude-watcher-N6GN6WHJ.js.map +0 -1
- package/dist/database-F3BFFZKG.js +0 -9
- package/dist/skill-usage-detector-EO26MRYV.js.map +0 -1
- package/dist/tray-UCAI2U2C.js +0 -408
- package/dist/tray-UCAI2U2C.js.map +0 -1
- /package/dist/{api-client-KUQW7FSC.js.map → api-client-BF6GDR7Q.js.map} +0 -0
- /package/dist/{config-P5EM5L7N.js.map → config-ZOKAP2LJ.js.map} +0 -0
- /package/dist/{database-F3BFFZKG.js.map → daemon-6DTCMOJB.js.map} +0 -0
- /package/dist/{paths-INOKEM66.js.map → database-KQY5OSCS.js.map} +0 -0
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
logger_default
|
|
4
|
+
} from "./chunk-VAQ73XPE.js";
|
|
5
|
+
import {
|
|
6
|
+
SkilloDatabase
|
|
7
|
+
} from "./chunk-73NUWYUO.js";
|
|
8
|
+
import {
|
|
9
|
+
loadConfig
|
|
10
|
+
} from "./chunk-QUXHHRRK.js";
|
|
11
|
+
import {
|
|
12
|
+
ensureDirectory,
|
|
13
|
+
getConfigFile,
|
|
14
|
+
getDataDir
|
|
15
|
+
} from "./chunk-63FVALWX.js";
|
|
16
|
+
|
|
17
|
+
// src/commands/shell.ts
|
|
18
|
+
import { existsSync, writeFileSync, readFileSync, appendFileSync } from "fs";
|
|
19
|
+
import { spawn } from "child_process";
|
|
20
|
+
import { homedir } from "os";
|
|
21
|
+
import { join } from "path";
|
|
22
|
+
import { Command } from "commander";
|
|
23
|
+
var UNSYNCED_REMINDER_THRESHOLD = 50;
|
|
24
|
+
async function checkLoginStatus() {
|
|
25
|
+
try {
|
|
26
|
+
const { getApiClient } = await import("./api-client-BF6GDR7Q.js");
|
|
27
|
+
const client = getApiClient();
|
|
28
|
+
return client.hasApiKey();
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function getUnsyncedCounterPath() {
|
|
34
|
+
return join(getDataDir(), "unsynced-count");
|
|
35
|
+
}
|
|
36
|
+
function incrementUnsyncedCounter() {
|
|
37
|
+
const counterPath = getUnsyncedCounterPath();
|
|
38
|
+
let count = 0;
|
|
39
|
+
try {
|
|
40
|
+
if (existsSync(counterPath)) {
|
|
41
|
+
const parsed = parseInt(readFileSync(counterPath, "utf-8").trim(), 10);
|
|
42
|
+
count = Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
count++;
|
|
47
|
+
try {
|
|
48
|
+
writeFileSync(counterPath, String(count), "utf-8");
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return count;
|
|
52
|
+
}
|
|
53
|
+
function resetUnsyncedCounter() {
|
|
54
|
+
try {
|
|
55
|
+
writeFileSync(getUnsyncedCounterPath(), "0", "utf-8");
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function normalizeCommand(cmd) {
|
|
60
|
+
const variables = {};
|
|
61
|
+
let normalized = cmd;
|
|
62
|
+
let varIndex = 0;
|
|
63
|
+
normalized = normalized.replace(/(?:^|\s)(\/[\w\-.\/]+)/g, (match, path) => {
|
|
64
|
+
const key = `$PATH${varIndex++}`;
|
|
65
|
+
variables[key] = path;
|
|
66
|
+
return match.replace(path, key);
|
|
67
|
+
});
|
|
68
|
+
normalized = normalized.replace(
|
|
69
|
+
/https?:\/\/[^\s]+/g,
|
|
70
|
+
(match) => {
|
|
71
|
+
const key = `$URL${varIndex++}`;
|
|
72
|
+
variables[key] = match;
|
|
73
|
+
return key;
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
normalized = normalized.replace(/\b\d{4,}\b/g, (match) => {
|
|
77
|
+
const key = `$NUM${varIndex++}`;
|
|
78
|
+
variables[key] = match;
|
|
79
|
+
return key;
|
|
80
|
+
});
|
|
81
|
+
normalized = normalized.replace(/"[^"]+"/g, (match) => {
|
|
82
|
+
const key = `$STR${varIndex++}`;
|
|
83
|
+
variables[key] = match;
|
|
84
|
+
return key;
|
|
85
|
+
});
|
|
86
|
+
normalized = normalized.replace(/'[^']+'/g, (match) => {
|
|
87
|
+
const key = `$STR${varIndex++}`;
|
|
88
|
+
variables[key] = match;
|
|
89
|
+
return key;
|
|
90
|
+
});
|
|
91
|
+
return { normalized: normalized.trim(), variables };
|
|
92
|
+
}
|
|
93
|
+
var shellCommand = new Command("shell").description("Start a tracked terminal session").option("-s, --shell <shell>", "Shell to use (default: $SHELL or cmd on Windows)").option("-p, --project <path>", "Project path to track").action(async (options) => {
|
|
94
|
+
if (!existsSync(getConfigFile())) {
|
|
95
|
+
logger_default.error("Skillo not initialized. Run 'skillo init' first.");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
const config = loadConfig();
|
|
99
|
+
let shell = options.shell || config.defaultShell;
|
|
100
|
+
if (!shell) {
|
|
101
|
+
if (process.platform === "win32") {
|
|
102
|
+
shell = process.env.COMSPEC || "cmd.exe";
|
|
103
|
+
} else {
|
|
104
|
+
shell = process.env.SHELL || "/bin/bash";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const projectPath = options.project || process.cwd();
|
|
108
|
+
logger_default.blank();
|
|
109
|
+
logger_default.info("Starting tracked shell session...");
|
|
110
|
+
logger_default.dim(`Shell: ${shell}`);
|
|
111
|
+
logger_default.dim(`Project: ${projectPath}`);
|
|
112
|
+
logger_default.blank();
|
|
113
|
+
logger_default.dim("All commands will be tracked. Type 'exit' to end the session.");
|
|
114
|
+
logger_default.blank();
|
|
115
|
+
const db = new SkilloDatabase();
|
|
116
|
+
await db.initialize();
|
|
117
|
+
const sessionId = await db.createSession(shell, projectPath);
|
|
118
|
+
let commandCount = 0;
|
|
119
|
+
let currentCommand = "";
|
|
120
|
+
let commandStartTime = null;
|
|
121
|
+
const shellArgs = process.platform === "win32" ? [] : ["-i"];
|
|
122
|
+
const child = spawn(shell, shellArgs, {
|
|
123
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
124
|
+
shell: false,
|
|
125
|
+
cwd: projectPath,
|
|
126
|
+
env: {
|
|
127
|
+
...process.env,
|
|
128
|
+
SKILLO_SESSION: sessionId,
|
|
129
|
+
SKILLO_TRACKING: "1"
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
child.on("exit", async (code) => {
|
|
133
|
+
await db.endSession(sessionId);
|
|
134
|
+
db.close();
|
|
135
|
+
logger_default.blank();
|
|
136
|
+
logger_default.success(`Session ended. Tracked ${commandCount} command(s).`);
|
|
137
|
+
logger_default.dim(`Session ID: ${sessionId.slice(0, 8)}`);
|
|
138
|
+
logger_default.blank();
|
|
139
|
+
process.exit(code || 0);
|
|
140
|
+
});
|
|
141
|
+
child.on("error", async (error) => {
|
|
142
|
+
logger_default.error(`Failed to start shell: ${error.message}`);
|
|
143
|
+
await db.endSession(sessionId);
|
|
144
|
+
db.close();
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
var recordCommand = new Command("record").description("Record a command (used by shell integration)").argument("<command>", "Command that was executed").option("--session <id>", "Session ID").option("--cwd <path>", "Working directory").option("--exit-code <code>", "Exit code").option("--duration <ms>", "Duration in milliseconds").option("--no-sync", "Don't sync to platform").action(
|
|
149
|
+
async (command, options) => {
|
|
150
|
+
const cwd = options.cwd || process.cwd();
|
|
151
|
+
const exitCode = options.exitCode ? parseInt(options.exitCode, 10) : null;
|
|
152
|
+
const durationMs = options.duration ? parseInt(options.duration, 10) : null;
|
|
153
|
+
const sessionId = options.session || process.env.SKILLO_SESSION || "default";
|
|
154
|
+
const { normalized, variables } = normalizeCommand(command);
|
|
155
|
+
const db = new SkilloDatabase();
|
|
156
|
+
await db.initialize();
|
|
157
|
+
await db.addCommand({
|
|
158
|
+
command,
|
|
159
|
+
normalized,
|
|
160
|
+
cwd,
|
|
161
|
+
sessionId,
|
|
162
|
+
exitCode,
|
|
163
|
+
durationMs,
|
|
164
|
+
variables: Object.keys(variables).length > 0 ? variables : null
|
|
165
|
+
});
|
|
166
|
+
db.close();
|
|
167
|
+
if (options.sync !== false) {
|
|
168
|
+
try {
|
|
169
|
+
const isLoggedIn = await checkLoginStatus();
|
|
170
|
+
if (isLoggedIn) {
|
|
171
|
+
const { getApiClient } = await import("./api-client-BF6GDR7Q.js");
|
|
172
|
+
const client = getApiClient();
|
|
173
|
+
await client.syncCommands([{
|
|
174
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
175
|
+
command,
|
|
176
|
+
normalized,
|
|
177
|
+
cwd,
|
|
178
|
+
exitCode,
|
|
179
|
+
durationMs,
|
|
180
|
+
sessionId: sessionId !== "default" ? sessionId : void 0,
|
|
181
|
+
variables: Object.keys(variables).length > 0 ? variables : null
|
|
182
|
+
}]);
|
|
183
|
+
resetUnsyncedCounter();
|
|
184
|
+
} else {
|
|
185
|
+
const count = incrementUnsyncedCounter();
|
|
186
|
+
if (count === UNSYNCED_REMINDER_THRESHOLD) {
|
|
187
|
+
process.stderr.write(
|
|
188
|
+
`\x1B[33m[!] You have ${UNSYNCED_REMINDER_THRESHOLD}+ commands tracked locally but not synced. Run 'skillo login' to enable cloud sync.\x1B[0m
|
|
189
|
+
`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
var setupShellCommand = new Command("setup-shell").description("Set up shell integration for automatic command tracking").option("--bash", "Set up Bash integration").option("--zsh", "Set up Zsh integration").option("--powershell", "Set up PowerShell integration").option("--fish", "Set up Fish integration").option("--uninstall", "Remove shell integration").action(async (options) => {
|
|
199
|
+
logger_default.blank();
|
|
200
|
+
const home = homedir();
|
|
201
|
+
const dataDir = getDataDir();
|
|
202
|
+
ensureDirectory(dataDir);
|
|
203
|
+
let shell = null;
|
|
204
|
+
if (options.bash) shell = "bash";
|
|
205
|
+
else if (options.zsh) shell = "zsh";
|
|
206
|
+
else if (options.powershell) shell = "powershell";
|
|
207
|
+
else if (options.fish) shell = "fish";
|
|
208
|
+
else {
|
|
209
|
+
if (process.platform === "win32") {
|
|
210
|
+
if (process.env.MSYSTEM || process.env.SHELL?.includes("bash") || process.env.TERM === "mintty") {
|
|
211
|
+
shell = "bash";
|
|
212
|
+
} else {
|
|
213
|
+
shell = "powershell";
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
const currentShell = process.env.SHELL || "";
|
|
217
|
+
if (currentShell.includes("zsh")) shell = "zsh";
|
|
218
|
+
else if (currentShell.includes("fish")) shell = "fish";
|
|
219
|
+
else shell = "bash";
|
|
220
|
+
}
|
|
221
|
+
logger_default.info(`Detected shell: ${shell}`);
|
|
222
|
+
}
|
|
223
|
+
if (options.uninstall) {
|
|
224
|
+
logger_default.info(`Removing ${shell} integration...`);
|
|
225
|
+
await uninstallShellIntegration(shell, home);
|
|
226
|
+
logger_default.success("Shell integration removed.");
|
|
227
|
+
logger_default.dim("Restart your terminal for changes to take effect.");
|
|
228
|
+
logger_default.blank();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const isLoggedIn = await checkLoginStatus();
|
|
232
|
+
logger_default.info(`Setting up ${shell} integration...`);
|
|
233
|
+
logger_default.blank();
|
|
234
|
+
await installShellIntegration(shell, home, dataDir);
|
|
235
|
+
logger_default.blank();
|
|
236
|
+
logger_default.success("Shell integration installed!");
|
|
237
|
+
logger_default.blank();
|
|
238
|
+
if (!isLoggedIn) {
|
|
239
|
+
logger_default.warn("You're not logged in. Commands will be tracked locally only.");
|
|
240
|
+
logger_default.dim("Run 'skillo login' to enable cloud sync.");
|
|
241
|
+
logger_default.blank();
|
|
242
|
+
}
|
|
243
|
+
logger_default.dim("Restart your terminal or run:");
|
|
244
|
+
if (shell === "powershell") {
|
|
245
|
+
logger_default.highlight(" . $PROFILE");
|
|
246
|
+
} else if (shell === "bash") {
|
|
247
|
+
logger_default.highlight(" source ~/.bashrc");
|
|
248
|
+
} else if (shell === "zsh") {
|
|
249
|
+
logger_default.highlight(" source ~/.zshrc");
|
|
250
|
+
} else if (shell === "fish") {
|
|
251
|
+
logger_default.highlight(" source ~/.config/fish/config.fish");
|
|
252
|
+
}
|
|
253
|
+
logger_default.blank();
|
|
254
|
+
if (isLoggedIn) {
|
|
255
|
+
logger_default.dim("All commands you run will now be tracked and synced to Skillo.");
|
|
256
|
+
} else {
|
|
257
|
+
logger_default.dim("All commands will be tracked locally. Login to sync to Skillo.");
|
|
258
|
+
}
|
|
259
|
+
logger_default.blank();
|
|
260
|
+
});
|
|
261
|
+
function generatePosixSyncStatusLines() {
|
|
262
|
+
return [
|
|
263
|
+
"# Show sync status on startup (respects SKILLO_CONFIG_DIR and XDG_CONFIG_HOME)",
|
|
264
|
+
'if [ -n "$SKILLO_CONFIG_DIR" ]; then',
|
|
265
|
+
' _skillo_config="$SKILLO_CONFIG_DIR/config.yaml"',
|
|
266
|
+
'elif [ -n "$XDG_CONFIG_HOME" ]; then',
|
|
267
|
+
' _skillo_config="$XDG_CONFIG_HOME/skillo/config.yaml"',
|
|
268
|
+
"else",
|
|
269
|
+
' _skillo_config="$HOME/.config/skillo/config.yaml"',
|
|
270
|
+
"fi",
|
|
271
|
+
'if [ -f "$_skillo_config" ] && grep -q "api_key:" "$_skillo_config" 2>/dev/null; then',
|
|
272
|
+
' echo -e "\\033[90mSkillo: Command tracking enabled (syncing to platform)\\033[0m"',
|
|
273
|
+
"else",
|
|
274
|
+
` echo -e "\\033[33mSkillo: Command tracking enabled (local only \u2014 run 'skillo login' to sync)\\033[0m"`,
|
|
275
|
+
"fi"
|
|
276
|
+
];
|
|
277
|
+
}
|
|
278
|
+
async function installShellIntegration(shell, home, dataDir) {
|
|
279
|
+
const scriptPath = join(dataDir, "shell-integration");
|
|
280
|
+
ensureDirectory(scriptPath);
|
|
281
|
+
if (shell === "powershell") {
|
|
282
|
+
const psScript = `# Skillo CLI Integration
|
|
283
|
+
# Records commands to Skillo platform
|
|
284
|
+
# Works in two modes:
|
|
285
|
+
# 1. Platform mode: Uses SKILLO_SESSION and SKILLO_USER_ID env vars (set by platform launch)
|
|
286
|
+
# 2. Standalone mode: Uses skillo CLI which handles auth via API key
|
|
287
|
+
|
|
288
|
+
$Global:SkilloLastHistoryId = 0
|
|
289
|
+
$Global:SkilloStandaloneSessionId = $null
|
|
290
|
+
$Global:SkilloSessionStartTime = $null
|
|
291
|
+
|
|
292
|
+
# Check if launched from platform (has session/user env vars) or standalone
|
|
293
|
+
$Global:SkilloPlatformMode = $false
|
|
294
|
+
if ($env:SKILLO_SESSION -and $env:SKILLO_USER_ID) {
|
|
295
|
+
$Global:SkilloPlatformMode = $true
|
|
296
|
+
$Global:SkilloSessionId = $env:SKILLO_SESSION
|
|
297
|
+
$Global:SkilloUserId = $env:SKILLO_USER_ID
|
|
298
|
+
$Global:SkilloBaseUrl = if ($env:SKILLO_API_URL) { $env:SKILLO_API_URL } else { 'http://localhost:3000' }
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function Send-SkilloCommandPlatform {
|
|
302
|
+
param($Command, $Duration, $ExitCode, $Cwd)
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
$body = @{
|
|
306
|
+
type = 'commands'
|
|
307
|
+
data = @(@{
|
|
308
|
+
timestamp = (Get-Date).ToString('o')
|
|
309
|
+
command = $Command
|
|
310
|
+
normalized = $Command
|
|
311
|
+
cwd = $Cwd
|
|
312
|
+
exitCode = $ExitCode
|
|
313
|
+
durationMs = $Duration
|
|
314
|
+
sessionId = $Global:SkilloSessionId
|
|
315
|
+
})
|
|
316
|
+
} | ConvertTo-Json -Depth 3 -Compress
|
|
317
|
+
|
|
318
|
+
$uri = "$($Global:SkilloBaseUrl)/api/cli/sync"
|
|
319
|
+
|
|
320
|
+
$webRequest = [System.Net.HttpWebRequest]::Create($uri)
|
|
321
|
+
$webRequest.Method = 'POST'
|
|
322
|
+
$webRequest.ContentType = 'application/json'
|
|
323
|
+
$webRequest.Headers.Add('x-skillo-session', $Global:SkilloSessionId)
|
|
324
|
+
$webRequest.Headers.Add('x-skillo-user-id', $Global:SkilloUserId)
|
|
325
|
+
$webRequest.Timeout = 5000
|
|
326
|
+
|
|
327
|
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
|
|
328
|
+
$webRequest.ContentLength = $bytes.Length
|
|
329
|
+
$stream = $webRequest.GetRequestStream()
|
|
330
|
+
$stream.Write($bytes, 0, $bytes.Length)
|
|
331
|
+
$stream.Close()
|
|
332
|
+
|
|
333
|
+
$response = $webRequest.GetResponse()
|
|
334
|
+
$response.Close()
|
|
335
|
+
} catch {
|
|
336
|
+
# Silently ignore errors
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function Send-SkilloCommandCLI {
|
|
341
|
+
param($Command, $Duration, $ExitCode, $Cwd)
|
|
342
|
+
|
|
343
|
+
# Create session on first command if not exists
|
|
344
|
+
if (-not $Global:SkilloStandaloneSessionId) {
|
|
345
|
+
$Global:SkilloSessionStartTime = (Get-Date).ToString('o')
|
|
346
|
+
try {
|
|
347
|
+
$result = & skillo session start --shell "PowerShell" 2>$null
|
|
348
|
+
if ($result -match 'Session ID: ([a-f0-9-]+)') {
|
|
349
|
+
$Global:SkilloStandaloneSessionId = $Matches[1]
|
|
350
|
+
# Write PID file for session cleanup
|
|
351
|
+
$_pidDir = Join-Path (Join-Path $env:USERPROFILE '.skillo') 'active-sessions'
|
|
352
|
+
if (-not (Test-Path $_pidDir)) { New-Item -ItemType Directory -Path $_pidDir -Force | Out-Null }
|
|
353
|
+
$_json = '{"sessionId":"' + $Global:SkilloStandaloneSessionId + '","pid":' + $PID + '}'
|
|
354
|
+
[IO.File]::WriteAllText((Join-Path $_pidDir "$PID.json"), $_json)
|
|
355
|
+
}
|
|
356
|
+
} catch {
|
|
357
|
+
# If session command doesn't exist, generate a local ID
|
|
358
|
+
$Global:SkilloStandaloneSessionId = [guid]::NewGuid().ToString()
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
# Run skillo record in background with session ID
|
|
363
|
+
Start-Job -ScriptBlock {
|
|
364
|
+
param($cmd, $cwd, $exit, $dur, $sessionId)
|
|
365
|
+
& skillo record $cmd --cwd $cwd --exit-code $exit --duration $dur --session $sessionId 2>$null
|
|
366
|
+
} -ArgumentList $Command, $Cwd, $ExitCode, $Duration, $Global:SkilloStandaloneSessionId | Out-Null
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# Override prompt to capture commands after execution
|
|
370
|
+
$Global:SkilloOriginalPrompt = $function:prompt
|
|
371
|
+
function Global:prompt {
|
|
372
|
+
$lastCmd = Get-History -Count 1 -ErrorAction SilentlyContinue
|
|
373
|
+
|
|
374
|
+
if ($lastCmd -and $lastCmd.Id -gt $Global:SkilloLastHistoryId) {
|
|
375
|
+
$Global:SkilloLastHistoryId = $lastCmd.Id
|
|
376
|
+
|
|
377
|
+
$duration = 0
|
|
378
|
+
if ($lastCmd.EndExecutionTime -and $lastCmd.StartExecutionTime) {
|
|
379
|
+
$duration = [int]($lastCmd.EndExecutionTime - $lastCmd.StartExecutionTime).TotalMilliseconds
|
|
380
|
+
}
|
|
381
|
+
$exit = if ($null -eq $LASTEXITCODE) { 0 } else { $LASTEXITCODE }
|
|
382
|
+
$cwd = (Get-Location).Path
|
|
383
|
+
|
|
384
|
+
if ($Global:SkilloPlatformMode) {
|
|
385
|
+
Send-SkilloCommandPlatform -Command $lastCmd.CommandLine -Duration $duration -ExitCode $exit -Cwd $cwd
|
|
386
|
+
} else {
|
|
387
|
+
Send-SkilloCommandCLI -Command $lastCmd.CommandLine -Duration $duration -ExitCode $exit -Cwd $cwd
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
& $Global:SkilloOriginalPrompt
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
# Register exit handler to end session when terminal closes
|
|
395
|
+
$null = Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
|
|
396
|
+
if ($Global:SkilloPlatformMode -and $Global:SkilloSessionId) {
|
|
397
|
+
# End platform session
|
|
398
|
+
try {
|
|
399
|
+
$body = @{ sessionId = $Global:SkilloSessionId } | ConvertTo-Json -Compress
|
|
400
|
+
$uri = "$($Global:SkilloBaseUrl)/api/sessions"
|
|
401
|
+
|
|
402
|
+
$webRequest = [System.Net.HttpWebRequest]::Create($uri)
|
|
403
|
+
$webRequest.Method = 'PATCH'
|
|
404
|
+
$webRequest.ContentType = 'application/json'
|
|
405
|
+
$webRequest.Headers.Add('x-skillo-session', $Global:SkilloSessionId)
|
|
406
|
+
$webRequest.Headers.Add('x-skillo-user-id', $Global:SkilloUserId)
|
|
407
|
+
$webRequest.Timeout = 3000
|
|
408
|
+
|
|
409
|
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
|
|
410
|
+
$webRequest.ContentLength = $bytes.Length
|
|
411
|
+
$stream = $webRequest.GetRequestStream()
|
|
412
|
+
$stream.Write($bytes, 0, $bytes.Length)
|
|
413
|
+
$stream.Close()
|
|
414
|
+
|
|
415
|
+
$response = $webRequest.GetResponse()
|
|
416
|
+
$response.Close()
|
|
417
|
+
} catch {
|
|
418
|
+
# Ignore errors on exit
|
|
419
|
+
}
|
|
420
|
+
} elseif ($Global:SkilloStandaloneSessionId) {
|
|
421
|
+
# End standalone session via CLI
|
|
422
|
+
try {
|
|
423
|
+
& skillo session end --session $Global:SkilloStandaloneSessionId 2>$null
|
|
424
|
+
} catch {
|
|
425
|
+
# Ignore errors on exit
|
|
426
|
+
}
|
|
427
|
+
# Clean up PID file
|
|
428
|
+
$_pidFile = Join-Path (Join-Path (Join-Path $env:USERPROFILE '.skillo') 'active-sessions') "$PID.json"
|
|
429
|
+
if (Test-Path $_pidFile) { Remove-Item $_pidFile -Force -ErrorAction SilentlyContinue }
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
# Show sync status on startup
|
|
434
|
+
if ($Global:SkilloPlatformMode) {
|
|
435
|
+
Write-Host "Skillo: Command tracking enabled (syncing to platform)" -ForegroundColor DarkGray
|
|
436
|
+
} else {
|
|
437
|
+
# Check if logged in by looking for api_key in config (respects SKILLO_CONFIG_DIR and XDG_CONFIG_HOME)
|
|
438
|
+
if ($env:SKILLO_CONFIG_DIR) {
|
|
439
|
+
$skilloConfigPath = Join-Path $env:SKILLO_CONFIG_DIR "config.yaml"
|
|
440
|
+
} elseif ($env:XDG_CONFIG_HOME) {
|
|
441
|
+
$skilloConfigPath = Join-Path $env:XDG_CONFIG_HOME "skillo" "config.yaml"
|
|
442
|
+
} else {
|
|
443
|
+
$skilloConfigPath = Join-Path $HOME ".config" "skillo" "config.yaml"
|
|
444
|
+
}
|
|
445
|
+
$skilloLoggedIn = $false
|
|
446
|
+
if (Test-Path $skilloConfigPath) {
|
|
447
|
+
$skilloLoggedIn = (Select-String -Path $skilloConfigPath -Pattern "api_key:" -Quiet) -eq $true
|
|
448
|
+
}
|
|
449
|
+
if ($skilloLoggedIn) {
|
|
450
|
+
Write-Host "Skillo: Command tracking enabled (syncing to platform)" -ForegroundColor DarkGray
|
|
451
|
+
} else {
|
|
452
|
+
Write-Host "Skillo: Command tracking enabled (local only - run 'skillo login' to sync)" -ForegroundColor Yellow
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
`;
|
|
456
|
+
const psScriptFile = join(scriptPath, "skillo.ps1");
|
|
457
|
+
writeFileSync(psScriptFile, psScript, "utf-8");
|
|
458
|
+
logger_default.success(`Created ${psScriptFile}`);
|
|
459
|
+
const profilePath = join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
460
|
+
const profileDir = join(home, "Documents", "WindowsPowerShell");
|
|
461
|
+
ensureDirectory(profileDir);
|
|
462
|
+
const sourceLine = `
|
|
463
|
+
# Skillo CLI Integration
|
|
464
|
+
. "${psScriptFile}"
|
|
465
|
+
`;
|
|
466
|
+
if (existsSync(profilePath)) {
|
|
467
|
+
const content = readFileSync(profilePath, "utf-8");
|
|
468
|
+
if (!content.includes("Skillo CLI Integration")) {
|
|
469
|
+
appendFileSync(profilePath, sourceLine);
|
|
470
|
+
logger_default.success("Added to PowerShell profile");
|
|
471
|
+
} else {
|
|
472
|
+
logger_default.dim("Already in PowerShell profile");
|
|
473
|
+
}
|
|
474
|
+
} else {
|
|
475
|
+
writeFileSync(profilePath, sourceLine, "utf-8");
|
|
476
|
+
logger_default.success("Created PowerShell profile");
|
|
477
|
+
}
|
|
478
|
+
} else if (shell === "bash") {
|
|
479
|
+
const bashScript = [
|
|
480
|
+
"# Skillo CLI Integration",
|
|
481
|
+
"# Records commands and auto-detects tracked projects",
|
|
482
|
+
"",
|
|
483
|
+
'_skillo_session="${SKILLO_SESSION:-default}"',
|
|
484
|
+
"_skillo_last_cwd=",
|
|
485
|
+
"",
|
|
486
|
+
"_skillo_preexec() {",
|
|
487
|
+
' _skillo_cmd="$1"',
|
|
488
|
+
" _skillo_start_time=$(date +%s)",
|
|
489
|
+
"}",
|
|
490
|
+
"",
|
|
491
|
+
"_skillo_check_project() {",
|
|
492
|
+
" # Fast path: skip if CWD unchanged",
|
|
493
|
+
' if [ "$PWD" = "$_skillo_last_cwd" ]; then',
|
|
494
|
+
" return",
|
|
495
|
+
" fi",
|
|
496
|
+
' _skillo_last_cwd="$PWD"',
|
|
497
|
+
"",
|
|
498
|
+
" # Run session-auto (handles create/end via cache file)",
|
|
499
|
+
" local result _pid",
|
|
500
|
+
" _pid=$(cat /proc/$$/winpid 2>/dev/null || echo $$)",
|
|
501
|
+
' result=$(skillo session-auto "$PWD" --pid $_pid --shell bash 2>/dev/null)',
|
|
502
|
+
' if [ -n "$result" ]; then',
|
|
503
|
+
' export SKILLO_SESSION="$result"',
|
|
504
|
+
' _skillo_session="$result"',
|
|
505
|
+
" fi",
|
|
506
|
+
"}",
|
|
507
|
+
"",
|
|
508
|
+
"_skillo_precmd() {",
|
|
509
|
+
" local exit_code=$?",
|
|
510
|
+
"",
|
|
511
|
+
" # Check for project change",
|
|
512
|
+
" _skillo_check_project",
|
|
513
|
+
"",
|
|
514
|
+
' if [ -n "$_skillo_cmd" ]; then',
|
|
515
|
+
" local duration=0",
|
|
516
|
+
' if [ -n "$_skillo_start_time" ]; then',
|
|
517
|
+
" local end_time=$(date +%s)",
|
|
518
|
+
" duration=$(( (end_time - _skillo_start_time) * 1000 ))",
|
|
519
|
+
" fi",
|
|
520
|
+
' (skillo record "$_skillo_cmd" --cwd "$PWD" --exit-code "$exit_code" --duration "$duration" --session "$_skillo_session" >/dev/null &)',
|
|
521
|
+
' _skillo_cmd=""',
|
|
522
|
+
" fi",
|
|
523
|
+
"}",
|
|
524
|
+
"",
|
|
525
|
+
"# Clean up session on terminal exit",
|
|
526
|
+
"_skillo_cleanup() {",
|
|
527
|
+
' if [ -n "$SKILLO_SESSION" ] && [ "$SKILLO_SESSION" != "default" ]; then',
|
|
528
|
+
' skillo session end --session "$SKILLO_SESSION" >/dev/null 2>&1',
|
|
529
|
+
" fi",
|
|
530
|
+
"}",
|
|
531
|
+
"trap _skillo_cleanup EXIT",
|
|
532
|
+
"",
|
|
533
|
+
"# Use DEBUG trap for preexec",
|
|
534
|
+
`trap '_skillo_preexec "$BASH_COMMAND"' DEBUG`,
|
|
535
|
+
"",
|
|
536
|
+
"# Add precmd to PROMPT_COMMAND",
|
|
537
|
+
'if [[ ! "$PROMPT_COMMAND" =~ _skillo_precmd ]]; then',
|
|
538
|
+
' PROMPT_COMMAND="_skillo_precmd${PROMPT_COMMAND:+;$PROMPT_COMMAND}"',
|
|
539
|
+
"fi",
|
|
540
|
+
"",
|
|
541
|
+
"# Initial project check",
|
|
542
|
+
"_skillo_check_project",
|
|
543
|
+
"",
|
|
544
|
+
...generatePosixSyncStatusLines()
|
|
545
|
+
].join("\n");
|
|
546
|
+
const bashScriptFile = join(scriptPath, "skillo.bash");
|
|
547
|
+
writeFileSync(bashScriptFile, bashScript, "utf-8");
|
|
548
|
+
logger_default.success(`Created ${bashScriptFile}`);
|
|
549
|
+
const bashrcPath = join(home, ".bashrc");
|
|
550
|
+
const sourceLine = `
|
|
551
|
+
# Skillo CLI Integration
|
|
552
|
+
[ -f "${bashScriptFile}" ] && source "${bashScriptFile}"
|
|
553
|
+
`;
|
|
554
|
+
if (existsSync(bashrcPath)) {
|
|
555
|
+
const content = readFileSync(bashrcPath, "utf-8");
|
|
556
|
+
if (!content.includes("Skillo CLI Integration")) {
|
|
557
|
+
appendFileSync(bashrcPath, sourceLine);
|
|
558
|
+
logger_default.success("Added to ~/.bashrc");
|
|
559
|
+
} else {
|
|
560
|
+
logger_default.dim("Already in ~/.bashrc");
|
|
561
|
+
}
|
|
562
|
+
} else {
|
|
563
|
+
writeFileSync(bashrcPath, sourceLine, "utf-8");
|
|
564
|
+
logger_default.success("Created ~/.bashrc");
|
|
565
|
+
}
|
|
566
|
+
} else if (shell === "zsh") {
|
|
567
|
+
const zshScript = [
|
|
568
|
+
"# Skillo CLI Integration",
|
|
569
|
+
"# Records commands and auto-detects tracked projects",
|
|
570
|
+
"",
|
|
571
|
+
'_skillo_session="${SKILLO_SESSION:-default}"',
|
|
572
|
+
"_skillo_last_cwd=",
|
|
573
|
+
"",
|
|
574
|
+
"_skillo_preexec() {",
|
|
575
|
+
' _skillo_cmd="$1"',
|
|
576
|
+
" _skillo_start_time=$(date +%s)",
|
|
577
|
+
"}",
|
|
578
|
+
"",
|
|
579
|
+
"_skillo_check_project() {",
|
|
580
|
+
" # Fast path: skip if CWD unchanged",
|
|
581
|
+
' if [[ "$PWD" == "$_skillo_last_cwd" ]]; then',
|
|
582
|
+
" return",
|
|
583
|
+
" fi",
|
|
584
|
+
' _skillo_last_cwd="$PWD"',
|
|
585
|
+
"",
|
|
586
|
+
" # Run session-auto (handles create/end via cache file)",
|
|
587
|
+
" local result _pid",
|
|
588
|
+
" _pid=$(cat /proc/$$/winpid 2>/dev/null || echo $$)",
|
|
589
|
+
' result=$(skillo session-auto "$PWD" --pid $_pid --shell zsh 2>/dev/null)',
|
|
590
|
+
' if [[ -n "$result" ]]; then',
|
|
591
|
+
' export SKILLO_SESSION="$result"',
|
|
592
|
+
' _skillo_session="$result"',
|
|
593
|
+
" fi",
|
|
594
|
+
"}",
|
|
595
|
+
"",
|
|
596
|
+
"_skillo_precmd() {",
|
|
597
|
+
" local exit_code=$?",
|
|
598
|
+
"",
|
|
599
|
+
" # Check for project change",
|
|
600
|
+
" _skillo_check_project",
|
|
601
|
+
"",
|
|
602
|
+
' if [[ -n "$_skillo_cmd" ]]; then',
|
|
603
|
+
" local duration=0",
|
|
604
|
+
' if [[ -n "$_skillo_start_time" ]]; then',
|
|
605
|
+
" local end_time=$(date +%s)",
|
|
606
|
+
" duration=$(( (end_time - _skillo_start_time) * 1000 ))",
|
|
607
|
+
" fi",
|
|
608
|
+
' (skillo record "$_skillo_cmd" --cwd "$PWD" --exit-code "$exit_code" --duration "$duration" --session "$_skillo_session" >/dev/null &)',
|
|
609
|
+
' _skillo_cmd=""',
|
|
610
|
+
" fi",
|
|
611
|
+
"}",
|
|
612
|
+
"",
|
|
613
|
+
"# Clean up session on terminal exit",
|
|
614
|
+
"_skillo_cleanup() {",
|
|
615
|
+
' if [[ -n "$SKILLO_SESSION" ]] && [[ "$SKILLO_SESSION" != "default" ]]; then',
|
|
616
|
+
' skillo session end --session "$SKILLO_SESSION" >/dev/null 2>&1',
|
|
617
|
+
" fi",
|
|
618
|
+
"}",
|
|
619
|
+
"trap _skillo_cleanup EXIT",
|
|
620
|
+
"",
|
|
621
|
+
"autoload -Uz add-zsh-hook",
|
|
622
|
+
"add-zsh-hook preexec _skillo_preexec",
|
|
623
|
+
"add-zsh-hook precmd _skillo_precmd",
|
|
624
|
+
"",
|
|
625
|
+
"# Initial project check",
|
|
626
|
+
"_skillo_check_project",
|
|
627
|
+
"",
|
|
628
|
+
...generatePosixSyncStatusLines()
|
|
629
|
+
].join("\n");
|
|
630
|
+
const zshScriptFile = join(scriptPath, "skillo.zsh");
|
|
631
|
+
writeFileSync(zshScriptFile, zshScript, "utf-8");
|
|
632
|
+
logger_default.success(`Created ${zshScriptFile}`);
|
|
633
|
+
const zshrcPath = join(home, ".zshrc");
|
|
634
|
+
const sourceLine = `
|
|
635
|
+
# Skillo CLI Integration
|
|
636
|
+
[ -f "${zshScriptFile}" ] && source "${zshScriptFile}"
|
|
637
|
+
`;
|
|
638
|
+
if (existsSync(zshrcPath)) {
|
|
639
|
+
const content = readFileSync(zshrcPath, "utf-8");
|
|
640
|
+
if (!content.includes("Skillo CLI Integration")) {
|
|
641
|
+
appendFileSync(zshrcPath, sourceLine);
|
|
642
|
+
logger_default.success("Added to ~/.zshrc");
|
|
643
|
+
} else {
|
|
644
|
+
logger_default.dim("Already in ~/.zshrc");
|
|
645
|
+
}
|
|
646
|
+
} else {
|
|
647
|
+
writeFileSync(zshrcPath, sourceLine, "utf-8");
|
|
648
|
+
logger_default.success("Created ~/.zshrc");
|
|
649
|
+
}
|
|
650
|
+
} else if (shell === "fish") {
|
|
651
|
+
const fishScript = [
|
|
652
|
+
"# Skillo CLI Integration",
|
|
653
|
+
"# Records commands to Skillo platform",
|
|
654
|
+
"",
|
|
655
|
+
'set -q SKILLO_SESSION; or set -g SKILLO_SESSION "default"',
|
|
656
|
+
"",
|
|
657
|
+
"function _skillo_postexec --on-event fish_postexec",
|
|
658
|
+
" set -l cmd $argv[1]",
|
|
659
|
+
" set -l exit_code $status",
|
|
660
|
+
' skillo record "$cmd" --cwd (pwd) --exit-code $exit_code --session $SKILLO_SESSION >/dev/null &',
|
|
661
|
+
"end",
|
|
662
|
+
"",
|
|
663
|
+
"# Show sync status on startup (respects SKILLO_CONFIG_DIR and XDG_CONFIG_HOME)",
|
|
664
|
+
"if set -q SKILLO_CONFIG_DIR",
|
|
665
|
+
' set _skillo_config "$SKILLO_CONFIG_DIR/config.yaml"',
|
|
666
|
+
"else if set -q XDG_CONFIG_HOME",
|
|
667
|
+
' set _skillo_config "$XDG_CONFIG_HOME/skillo/config.yaml"',
|
|
668
|
+
"else",
|
|
669
|
+
' set _skillo_config "$HOME/.config/skillo/config.yaml"',
|
|
670
|
+
"end",
|
|
671
|
+
'if test -f "$_skillo_config"; and grep -q "api_key:" "$_skillo_config" 2>/dev/null',
|
|
672
|
+
' echo -e "\\033[90mSkillo: Command tracking enabled (syncing to platform)\\033[0m"',
|
|
673
|
+
"else",
|
|
674
|
+
` echo -e "\\033[33mSkillo: Command tracking enabled (local only \u2014 run 'skillo login' to sync)\\033[0m"`,
|
|
675
|
+
"end"
|
|
676
|
+
].join("\n");
|
|
677
|
+
const fishScriptFile = join(scriptPath, "skillo.fish");
|
|
678
|
+
writeFileSync(fishScriptFile, fishScript, "utf-8");
|
|
679
|
+
logger_default.success(`Created ${fishScriptFile}`);
|
|
680
|
+
const fishConfigDir = join(home, ".config", "fish");
|
|
681
|
+
ensureDirectory(fishConfigDir);
|
|
682
|
+
const fishConfigPath = join(fishConfigDir, "config.fish");
|
|
683
|
+
const sourceLine = `
|
|
684
|
+
# Skillo CLI Integration
|
|
685
|
+
if test -f "${fishScriptFile}"
|
|
686
|
+
source "${fishScriptFile}"
|
|
687
|
+
end
|
|
688
|
+
`;
|
|
689
|
+
if (existsSync(fishConfigPath)) {
|
|
690
|
+
const content = readFileSync(fishConfigPath, "utf-8");
|
|
691
|
+
if (!content.includes("Skillo CLI Integration")) {
|
|
692
|
+
appendFileSync(fishConfigPath, sourceLine);
|
|
693
|
+
logger_default.success("Added to ~/.config/fish/config.fish");
|
|
694
|
+
} else {
|
|
695
|
+
logger_default.dim("Already in fish config");
|
|
696
|
+
}
|
|
697
|
+
} else {
|
|
698
|
+
writeFileSync(fishConfigPath, sourceLine, "utf-8");
|
|
699
|
+
logger_default.success("Created fish config");
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async function uninstallShellIntegration(shell, home) {
|
|
704
|
+
const removeFromFile = (filePath) => {
|
|
705
|
+
if (!existsSync(filePath)) return;
|
|
706
|
+
let content = readFileSync(filePath, "utf-8");
|
|
707
|
+
content = content.replace(/\n# Skillo CLI Integration\n[^\n]*\n/g, "\n");
|
|
708
|
+
writeFileSync(filePath, content, "utf-8");
|
|
709
|
+
};
|
|
710
|
+
if (shell === "powershell") {
|
|
711
|
+
const profilePath = join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
712
|
+
removeFromFile(profilePath);
|
|
713
|
+
} else if (shell === "bash") {
|
|
714
|
+
removeFromFile(join(home, ".bashrc"));
|
|
715
|
+
} else if (shell === "zsh") {
|
|
716
|
+
removeFromFile(join(home, ".zshrc"));
|
|
717
|
+
} else if (shell === "fish") {
|
|
718
|
+
removeFromFile(join(home, ".config", "fish", "config.fish"));
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export {
|
|
723
|
+
shellCommand,
|
|
724
|
+
recordCommand,
|
|
725
|
+
setupShellCommand
|
|
726
|
+
};
|
|
727
|
+
//# sourceMappingURL=chunk-U53QWUOR.js.map
|