@keepgoingdev/cli 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +209 -130
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2801,96 +2801,7 @@ function renderEnrichedBriefingQuiet(briefing) {
|
|
|
2801
2801
|
console.log(`KeepGoing \xB7 ${core.lastWorked} \xB7 Focus: ${core.currentFocus} \xB7 Next: ${core.smallNextStep}`);
|
|
2802
2802
|
}
|
|
2803
2803
|
|
|
2804
|
-
// src/updateCheck.ts
|
|
2805
|
-
import { spawn } from "child_process";
|
|
2806
|
-
import { readFileSync, existsSync } from "fs";
|
|
2807
|
-
import path11 from "path";
|
|
2808
|
-
import os5 from "os";
|
|
2809
|
-
var CLI_VERSION = "1.4.0";
|
|
2810
|
-
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
|
|
2811
|
-
var FETCH_TIMEOUT_MS = 5e3;
|
|
2812
|
-
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
2813
|
-
var CACHE_DIR = path11.join(os5.homedir(), ".keepgoing");
|
|
2814
|
-
var CACHE_PATH = path11.join(CACHE_DIR, "update-check.json");
|
|
2815
|
-
function isNewerVersion(current, latest) {
|
|
2816
|
-
const cur = current.split(".").map(Number);
|
|
2817
|
-
const lat = latest.split(".").map(Number);
|
|
2818
|
-
for (let i = 0; i < 3; i++) {
|
|
2819
|
-
if ((lat[i] ?? 0) > (cur[i] ?? 0)) return true;
|
|
2820
|
-
if ((lat[i] ?? 0) < (cur[i] ?? 0)) return false;
|
|
2821
|
-
}
|
|
2822
|
-
return false;
|
|
2823
|
-
}
|
|
2824
|
-
function getCachedUpdateInfo() {
|
|
2825
|
-
try {
|
|
2826
|
-
if (!existsSync(CACHE_PATH)) return null;
|
|
2827
|
-
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
2828
|
-
const cache = JSON.parse(raw);
|
|
2829
|
-
if (!cache.latest || !cache.checkedAt) return null;
|
|
2830
|
-
const age = Date.now() - new Date(cache.checkedAt).getTime();
|
|
2831
|
-
if (age > CHECK_INTERVAL_MS || cache.current !== CLI_VERSION) return null;
|
|
2832
|
-
return {
|
|
2833
|
-
current: CLI_VERSION,
|
|
2834
|
-
latest: cache.latest,
|
|
2835
|
-
updateAvailable: isNewerVersion(CLI_VERSION, cache.latest)
|
|
2836
|
-
};
|
|
2837
|
-
} catch {
|
|
2838
|
-
return null;
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
function spawnBackgroundCheck() {
|
|
2842
|
-
try {
|
|
2843
|
-
if (existsSync(CACHE_PATH)) {
|
|
2844
|
-
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
2845
|
-
const cache = JSON.parse(raw);
|
|
2846
|
-
const age = Date.now() - new Date(cache.checkedAt).getTime();
|
|
2847
|
-
if (age < CHECK_INTERVAL_MS && cache.current === CLI_VERSION) return;
|
|
2848
|
-
}
|
|
2849
|
-
} catch {
|
|
2850
|
-
}
|
|
2851
|
-
const script = `
|
|
2852
|
-
const https = require('https');
|
|
2853
|
-
const fs = require('fs');
|
|
2854
|
-
const path = require('path');
|
|
2855
|
-
const os = require('os');
|
|
2856
|
-
|
|
2857
|
-
const url = ${JSON.stringify(NPM_REGISTRY_URL)};
|
|
2858
|
-
const cacheDir = path.join(os.homedir(), '.keepgoing');
|
|
2859
|
-
const cachePath = path.join(cacheDir, 'update-check.json');
|
|
2860
|
-
const currentVersion = ${JSON.stringify(CLI_VERSION)};
|
|
2861
|
-
|
|
2862
|
-
const req = https.get(url, { timeout: ${FETCH_TIMEOUT_MS} }, (res) => {
|
|
2863
|
-
let data = '';
|
|
2864
|
-
res.on('data', (chunk) => { data += chunk; });
|
|
2865
|
-
res.on('end', () => {
|
|
2866
|
-
try {
|
|
2867
|
-
const latest = JSON.parse(data).version;
|
|
2868
|
-
if (!latest) process.exit(0);
|
|
2869
|
-
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
|
|
2870
|
-
fs.writeFileSync(cachePath, JSON.stringify({
|
|
2871
|
-
latest,
|
|
2872
|
-
current: currentVersion,
|
|
2873
|
-
checkedAt: new Date().toISOString(),
|
|
2874
|
-
}));
|
|
2875
|
-
} catch {}
|
|
2876
|
-
process.exit(0);
|
|
2877
|
-
});
|
|
2878
|
-
});
|
|
2879
|
-
req.on('error', () => process.exit(0));
|
|
2880
|
-
req.on('timeout', () => { req.destroy(); process.exit(0); });
|
|
2881
|
-
`;
|
|
2882
|
-
const child = spawn(process.execPath, ["-e", script], {
|
|
2883
|
-
detached: true,
|
|
2884
|
-
stdio: "ignore",
|
|
2885
|
-
env: { ...process.env }
|
|
2886
|
-
});
|
|
2887
|
-
child.unref();
|
|
2888
|
-
}
|
|
2889
|
-
|
|
2890
2804
|
// src/commands/status.ts
|
|
2891
|
-
var RESET2 = "\x1B[0m";
|
|
2892
|
-
var BOLD2 = "\x1B[1m";
|
|
2893
|
-
var DIM2 = "\x1B[2m";
|
|
2894
2805
|
async function statusCommand(opts) {
|
|
2895
2806
|
const reader = new KeepGoingReader(opts.cwd);
|
|
2896
2807
|
if (!reader.exists()) {
|
|
@@ -2918,15 +2829,10 @@ async function statusCommand(opts) {
|
|
|
2918
2829
|
(Date.now() - new Date(lastSession.timestamp).getTime()) / (1e3 * 60 * 60 * 24)
|
|
2919
2830
|
);
|
|
2920
2831
|
renderCheckpoint(lastSession, daysSince);
|
|
2921
|
-
const cached = getCachedUpdateInfo();
|
|
2922
|
-
if (cached?.updateAvailable) {
|
|
2923
|
-
console.log(`${DIM2}Update available: ${cached.current} \u2192 ${cached.latest}. Run: ${RESET2}${BOLD2}npm install -g @keepgoingdev/cli@latest${RESET2}`);
|
|
2924
|
-
}
|
|
2925
|
-
spawnBackgroundCheck();
|
|
2926
2832
|
}
|
|
2927
2833
|
|
|
2928
2834
|
// src/commands/save.ts
|
|
2929
|
-
import
|
|
2835
|
+
import path11 from "path";
|
|
2930
2836
|
async function saveCommand(opts) {
|
|
2931
2837
|
const { cwd, message, nextStepOverride, json, quiet, force } = opts;
|
|
2932
2838
|
const isManual = !!message;
|
|
@@ -2955,9 +2861,9 @@ async function saveCommand(opts) {
|
|
|
2955
2861
|
sessionStartTime: lastSession?.timestamp ?? now,
|
|
2956
2862
|
lastActivityTime: now
|
|
2957
2863
|
});
|
|
2958
|
-
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) =>
|
|
2864
|
+
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) => path11.basename(f)).join(", ")}`;
|
|
2959
2865
|
const nextStep = nextStepOverride ?? buildSmartNextStep(events);
|
|
2960
|
-
const projectName =
|
|
2866
|
+
const projectName = path11.basename(resolveStorageRoot(cwd));
|
|
2961
2867
|
const sessionId = generateSessionId({
|
|
2962
2868
|
workspaceRoot: cwd,
|
|
2963
2869
|
branch: gitBranch ?? void 0,
|
|
@@ -2991,16 +2897,16 @@ async function saveCommand(opts) {
|
|
|
2991
2897
|
|
|
2992
2898
|
// src/commands/hook.ts
|
|
2993
2899
|
import fs9 from "fs";
|
|
2994
|
-
import
|
|
2995
|
-
import
|
|
2900
|
+
import path12 from "path";
|
|
2901
|
+
import os5 from "os";
|
|
2996
2902
|
import { execSync as execSync2 } from "child_process";
|
|
2997
2903
|
var HOOK_MARKER_START = "# keepgoing-hook-start";
|
|
2998
2904
|
var HOOK_MARKER_END = "# keepgoing-hook-end";
|
|
2999
2905
|
var POST_COMMIT_MARKER_START = "# keepgoing-post-commit-start";
|
|
3000
2906
|
var POST_COMMIT_MARKER_END = "# keepgoing-post-commit-end";
|
|
3001
|
-
var KEEPGOING_HOOKS_DIR =
|
|
3002
|
-
var POST_COMMIT_HOOK_PATH =
|
|
3003
|
-
var KEEPGOING_MANAGED_MARKER =
|
|
2907
|
+
var KEEPGOING_HOOKS_DIR = path12.join(os5.homedir(), ".keepgoing", "hooks");
|
|
2908
|
+
var POST_COMMIT_HOOK_PATH = path12.join(KEEPGOING_HOOKS_DIR, "post-commit");
|
|
2909
|
+
var KEEPGOING_MANAGED_MARKER = path12.join(KEEPGOING_HOOKS_DIR, ".keepgoing-managed");
|
|
3004
2910
|
var POST_COMMIT_HOOK = `#!/bin/sh
|
|
3005
2911
|
${POST_COMMIT_MARKER_START}
|
|
3006
2912
|
# Runs after every git commit. Detects high-signal decisions.
|
|
@@ -3041,7 +2947,7 @@ if command -v keepgoing >/dev/null 2>&1
|
|
|
3041
2947
|
end
|
|
3042
2948
|
${HOOK_MARKER_END}`;
|
|
3043
2949
|
function detectShellInfo(shellOverride) {
|
|
3044
|
-
const home =
|
|
2950
|
+
const home = os5.homedir();
|
|
3045
2951
|
let shell;
|
|
3046
2952
|
if (shellOverride) {
|
|
3047
2953
|
shell = shellOverride.toLowerCase();
|
|
@@ -3064,14 +2970,14 @@ function detectShellInfo(shellOverride) {
|
|
|
3064
2970
|
}
|
|
3065
2971
|
}
|
|
3066
2972
|
if (shell === "zsh") {
|
|
3067
|
-
return { shell: "zsh", rcFile:
|
|
2973
|
+
return { shell: "zsh", rcFile: path12.join(home, ".zshrc") };
|
|
3068
2974
|
}
|
|
3069
2975
|
if (shell === "bash") {
|
|
3070
|
-
return { shell: "bash", rcFile:
|
|
2976
|
+
return { shell: "bash", rcFile: path12.join(home, ".bashrc") };
|
|
3071
2977
|
}
|
|
3072
2978
|
if (shell === "fish") {
|
|
3073
|
-
const xdgConfig = process.env["XDG_CONFIG_HOME"] ||
|
|
3074
|
-
return { shell: "fish", rcFile:
|
|
2979
|
+
const xdgConfig = process.env["XDG_CONFIG_HOME"] || path12.join(home, ".config");
|
|
2980
|
+
return { shell: "fish", rcFile: path12.join(xdgConfig, "fish", "config.fish") };
|
|
3075
2981
|
}
|
|
3076
2982
|
return void 0;
|
|
3077
2983
|
}
|
|
@@ -3102,11 +3008,11 @@ function resolveGlobalGitignorePath() {
|
|
|
3102
3008
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3103
3009
|
}).trim();
|
|
3104
3010
|
if (configured) {
|
|
3105
|
-
return configured.startsWith("~") ?
|
|
3011
|
+
return configured.startsWith("~") ? path12.join(os5.homedir(), configured.slice(1)) : configured;
|
|
3106
3012
|
}
|
|
3107
3013
|
} catch {
|
|
3108
3014
|
}
|
|
3109
|
-
return
|
|
3015
|
+
return path12.join(os5.homedir(), ".gitignore_global");
|
|
3110
3016
|
}
|
|
3111
3017
|
function performGlobalGitignore() {
|
|
3112
3018
|
const ignorePath = resolveGlobalGitignorePath();
|
|
@@ -3426,12 +3332,12 @@ async function briefingCommand(opts) {
|
|
|
3426
3332
|
}
|
|
3427
3333
|
|
|
3428
3334
|
// src/commands/init.ts
|
|
3429
|
-
var
|
|
3430
|
-
var
|
|
3335
|
+
var RESET2 = "\x1B[0m";
|
|
3336
|
+
var BOLD2 = "\x1B[1m";
|
|
3431
3337
|
var GREEN2 = "\x1B[32m";
|
|
3432
3338
|
var YELLOW2 = "\x1B[33m";
|
|
3433
3339
|
var CYAN2 = "\x1B[36m";
|
|
3434
|
-
var
|
|
3340
|
+
var DIM2 = "\x1B[2m";
|
|
3435
3341
|
function initCommand(options) {
|
|
3436
3342
|
const scope = options.scope === "user" ? "user" : "project";
|
|
3437
3343
|
const result = setupProject({
|
|
@@ -3439,7 +3345,7 @@ function initCommand(options) {
|
|
|
3439
3345
|
scope
|
|
3440
3346
|
});
|
|
3441
3347
|
console.log(`
|
|
3442
|
-
${
|
|
3348
|
+
${BOLD2}KeepGoing Init${RESET2} ${DIM2}(${scope} scope)${RESET2}
|
|
3443
3349
|
`);
|
|
3444
3350
|
for (const msg of result.messages) {
|
|
3445
3351
|
const colonIdx = msg.indexOf(":");
|
|
@@ -3450,16 +3356,16 @@ ${BOLD3}KeepGoing Init${RESET3} ${DIM3}(${scope} scope)${RESET3}
|
|
|
3450
3356
|
const label = msg.slice(0, colonIdx + 1);
|
|
3451
3357
|
const body = msg.slice(colonIdx + 1);
|
|
3452
3358
|
if (label.startsWith("Warning")) {
|
|
3453
|
-
console.log(` ${YELLOW2}${label}${
|
|
3359
|
+
console.log(` ${YELLOW2}${label}${RESET2}${body}`);
|
|
3454
3360
|
} else if (body.includes("Added")) {
|
|
3455
|
-
console.log(` ${GREEN2}${label}${
|
|
3361
|
+
console.log(` ${GREEN2}${label}${RESET2}${body}`);
|
|
3456
3362
|
} else {
|
|
3457
|
-
console.log(` ${CYAN2}${label}${
|
|
3363
|
+
console.log(` ${CYAN2}${label}${RESET2}${body}`);
|
|
3458
3364
|
}
|
|
3459
3365
|
}
|
|
3460
3366
|
if (result.changed) {
|
|
3461
3367
|
console.log(`
|
|
3462
|
-
${GREEN2}Done!${
|
|
3368
|
+
${GREEN2}Done!${RESET2} KeepGoing is set up for this project.
|
|
3463
3369
|
`);
|
|
3464
3370
|
} else {
|
|
3465
3371
|
console.log(`
|
|
@@ -3470,8 +3376,8 @@ Everything was already configured. No changes made.
|
|
|
3470
3376
|
|
|
3471
3377
|
// src/commands/setup.ts
|
|
3472
3378
|
import fs10 from "fs";
|
|
3473
|
-
import
|
|
3474
|
-
import
|
|
3379
|
+
import path13 from "path";
|
|
3380
|
+
import os6 from "os";
|
|
3475
3381
|
import { execSync as execSync3, exec as exec2 } from "child_process";
|
|
3476
3382
|
import { promisify as promisify2 } from "util";
|
|
3477
3383
|
|
|
@@ -5433,14 +5339,14 @@ function detectJetBrainsIdes() {
|
|
|
5433
5339
|
if (process.platform !== "darwin") return [];
|
|
5434
5340
|
return JETBRAINS_IDES.filter((ide) => {
|
|
5435
5341
|
try {
|
|
5436
|
-
return fs10.statSync(
|
|
5342
|
+
return fs10.statSync(path13.join("/Applications", ide.app)).isDirectory();
|
|
5437
5343
|
} catch {
|
|
5438
5344
|
return false;
|
|
5439
5345
|
}
|
|
5440
5346
|
});
|
|
5441
5347
|
}
|
|
5442
5348
|
async function setupCommand(options) {
|
|
5443
|
-
const displayPath = options.cwd.startsWith(
|
|
5349
|
+
const displayPath = options.cwd.startsWith(os6.homedir()) ? "~" + options.cwd.slice(os6.homedir().length) : options.cwd;
|
|
5444
5350
|
const presetDefaults = options.preset ? PRESET_DEFAULTS[options.preset] : void 0;
|
|
5445
5351
|
const presetLabel = options.preset ? PRESET_LABELS[options.preset] : void 0;
|
|
5446
5352
|
dist_exports.intro(presetLabel ? `KeepGoing Setup - ${presetLabel}` : "KeepGoing Setup Wizard");
|
|
@@ -5793,10 +5699,10 @@ async function setupCommand(options) {
|
|
|
5793
5699
|
claudePlugin,
|
|
5794
5700
|
licensed
|
|
5795
5701
|
};
|
|
5796
|
-
const keepgoingDir =
|
|
5702
|
+
const keepgoingDir = path13.join(os6.homedir(), ".keepgoing");
|
|
5797
5703
|
fs10.mkdirSync(keepgoingDir, { recursive: true });
|
|
5798
5704
|
fs10.writeFileSync(
|
|
5799
|
-
|
|
5705
|
+
path13.join(keepgoingDir, "setup-profile.json"),
|
|
5800
5706
|
JSON.stringify(profile, null, 2) + "\n",
|
|
5801
5707
|
"utf-8"
|
|
5802
5708
|
);
|
|
@@ -6007,8 +5913,8 @@ function filterDecisions(decisions, opts) {
|
|
|
6007
5913
|
}
|
|
6008
5914
|
|
|
6009
5915
|
// src/commands/log.ts
|
|
6010
|
-
var
|
|
6011
|
-
var
|
|
5916
|
+
var RESET3 = "\x1B[0m";
|
|
5917
|
+
var DIM3 = "\x1B[2m";
|
|
6012
5918
|
function logSessions(reader, opts) {
|
|
6013
5919
|
const { effectiveBranch } = reader.resolveBranchScope(opts.branch || void 0);
|
|
6014
5920
|
let sessions = reader.getSessions();
|
|
@@ -6019,7 +5925,7 @@ function logSessions(reader, opts) {
|
|
|
6019
5925
|
sessions = filterSessions(sessions, opts);
|
|
6020
5926
|
const totalFiltered = sessions.length;
|
|
6021
5927
|
if (totalFiltered === 0) {
|
|
6022
|
-
console.log(`${
|
|
5928
|
+
console.log(`${DIM3}No checkpoints match the given filters.${RESET3}`);
|
|
6023
5929
|
return;
|
|
6024
5930
|
}
|
|
6025
5931
|
const displayed = sessions.slice(0, opts.count);
|
|
@@ -6043,7 +5949,7 @@ function logSessions(reader, opts) {
|
|
|
6043
5949
|
}
|
|
6044
5950
|
}
|
|
6045
5951
|
if (totalFiltered > opts.count) {
|
|
6046
|
-
console.log(`${
|
|
5952
|
+
console.log(`${DIM3}(showing ${displayed.length} of ${totalFiltered} checkpoints)${RESET3}`);
|
|
6047
5953
|
}
|
|
6048
5954
|
}
|
|
6049
5955
|
function renderGrouped(sessions, showStat) {
|
|
@@ -6082,7 +5988,7 @@ async function logDecisions(reader, opts) {
|
|
|
6082
5988
|
decisions = filterDecisions(decisions, opts);
|
|
6083
5989
|
const totalFiltered = decisions.length;
|
|
6084
5990
|
if (totalFiltered === 0) {
|
|
6085
|
-
console.log(`${
|
|
5991
|
+
console.log(`${DIM3}No decisions match the given filters.${RESET3}`);
|
|
6086
5992
|
return;
|
|
6087
5993
|
}
|
|
6088
5994
|
const displayed = decisions.slice(0, opts.count);
|
|
@@ -6104,7 +6010,7 @@ async function logDecisions(reader, opts) {
|
|
|
6104
6010
|
}
|
|
6105
6011
|
}
|
|
6106
6012
|
if (totalFiltered > opts.count) {
|
|
6107
|
-
console.log(`${
|
|
6013
|
+
console.log(`${DIM3}(showing ${displayed.length} of ${totalFiltered} decisions)${RESET3}`);
|
|
6108
6014
|
}
|
|
6109
6015
|
}
|
|
6110
6016
|
async function logCommand(opts) {
|
|
@@ -6245,6 +6151,154 @@ function hotCommand(opts) {
|
|
|
6245
6151
|
}
|
|
6246
6152
|
}
|
|
6247
6153
|
|
|
6154
|
+
// src/commands/update.ts
|
|
6155
|
+
import { execSync as execSync5 } from "child_process";
|
|
6156
|
+
|
|
6157
|
+
// src/updateCheck.ts
|
|
6158
|
+
import { spawn } from "child_process";
|
|
6159
|
+
import { readFileSync, existsSync } from "fs";
|
|
6160
|
+
import path14 from "path";
|
|
6161
|
+
import os7 from "os";
|
|
6162
|
+
var CLI_VERSION = "1.5.0";
|
|
6163
|
+
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
|
|
6164
|
+
var FETCH_TIMEOUT_MS = 5e3;
|
|
6165
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
6166
|
+
var CACHE_DIR = path14.join(os7.homedir(), ".keepgoing");
|
|
6167
|
+
var CACHE_PATH = path14.join(CACHE_DIR, "update-check.json");
|
|
6168
|
+
function isNewerVersion(current, latest) {
|
|
6169
|
+
const cur = current.split(".").map(Number);
|
|
6170
|
+
const lat = latest.split(".").map(Number);
|
|
6171
|
+
for (let i = 0; i < 3; i++) {
|
|
6172
|
+
if ((lat[i] ?? 0) > (cur[i] ?? 0)) return true;
|
|
6173
|
+
if ((lat[i] ?? 0) < (cur[i] ?? 0)) return false;
|
|
6174
|
+
}
|
|
6175
|
+
return false;
|
|
6176
|
+
}
|
|
6177
|
+
function getCachedUpdateInfo() {
|
|
6178
|
+
try {
|
|
6179
|
+
if (!existsSync(CACHE_PATH)) return null;
|
|
6180
|
+
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
6181
|
+
const cache = JSON.parse(raw);
|
|
6182
|
+
if (!cache.latest || !cache.checkedAt) return null;
|
|
6183
|
+
const age = Date.now() - new Date(cache.checkedAt).getTime();
|
|
6184
|
+
if (age > CHECK_INTERVAL_MS || cache.current !== CLI_VERSION) return null;
|
|
6185
|
+
return {
|
|
6186
|
+
current: CLI_VERSION,
|
|
6187
|
+
latest: cache.latest,
|
|
6188
|
+
updateAvailable: isNewerVersion(CLI_VERSION, cache.latest)
|
|
6189
|
+
};
|
|
6190
|
+
} catch {
|
|
6191
|
+
return null;
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
function spawnBackgroundCheck() {
|
|
6195
|
+
try {
|
|
6196
|
+
if (existsSync(CACHE_PATH)) {
|
|
6197
|
+
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
6198
|
+
const cache = JSON.parse(raw);
|
|
6199
|
+
const age = Date.now() - new Date(cache.checkedAt).getTime();
|
|
6200
|
+
if (age < CHECK_INTERVAL_MS && cache.current === CLI_VERSION) return;
|
|
6201
|
+
}
|
|
6202
|
+
} catch {
|
|
6203
|
+
}
|
|
6204
|
+
const script = `
|
|
6205
|
+
const https = require('https');
|
|
6206
|
+
const fs = require('fs');
|
|
6207
|
+
const path = require('path');
|
|
6208
|
+
const os = require('os');
|
|
6209
|
+
|
|
6210
|
+
const url = ${JSON.stringify(NPM_REGISTRY_URL)};
|
|
6211
|
+
const cacheDir = path.join(os.homedir(), '.keepgoing');
|
|
6212
|
+
const cachePath = path.join(cacheDir, 'update-check.json');
|
|
6213
|
+
const currentVersion = ${JSON.stringify(CLI_VERSION)};
|
|
6214
|
+
|
|
6215
|
+
const req = https.get(url, { timeout: ${FETCH_TIMEOUT_MS} }, (res) => {
|
|
6216
|
+
let data = '';
|
|
6217
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
6218
|
+
res.on('end', () => {
|
|
6219
|
+
try {
|
|
6220
|
+
const latest = JSON.parse(data).version;
|
|
6221
|
+
if (!latest) process.exit(0);
|
|
6222
|
+
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
|
|
6223
|
+
fs.writeFileSync(cachePath, JSON.stringify({
|
|
6224
|
+
latest,
|
|
6225
|
+
current: currentVersion,
|
|
6226
|
+
checkedAt: new Date().toISOString(),
|
|
6227
|
+
}));
|
|
6228
|
+
} catch {}
|
|
6229
|
+
process.exit(0);
|
|
6230
|
+
});
|
|
6231
|
+
});
|
|
6232
|
+
req.on('error', () => process.exit(0));
|
|
6233
|
+
req.on('timeout', () => { req.destroy(); process.exit(0); });
|
|
6234
|
+
`;
|
|
6235
|
+
const child = spawn(process.execPath, ["-e", script], {
|
|
6236
|
+
detached: true,
|
|
6237
|
+
stdio: "ignore",
|
|
6238
|
+
env: { ...process.env }
|
|
6239
|
+
});
|
|
6240
|
+
child.unref();
|
|
6241
|
+
}
|
|
6242
|
+
|
|
6243
|
+
// src/commands/update.ts
|
|
6244
|
+
var RESET4 = "\x1B[0m";
|
|
6245
|
+
var BOLD3 = "\x1B[1m";
|
|
6246
|
+
var DIM4 = "\x1B[2m";
|
|
6247
|
+
var GREEN3 = "\x1B[32m";
|
|
6248
|
+
var YELLOW3 = "\x1B[33m";
|
|
6249
|
+
var CLI_VERSION2 = "1.5.0";
|
|
6250
|
+
async function updateCommand() {
|
|
6251
|
+
console.log(`
|
|
6252
|
+
${BOLD3}KeepGoing CLI${RESET4} ${DIM4}v${CLI_VERSION2}${RESET4}
|
|
6253
|
+
`);
|
|
6254
|
+
console.log(`${DIM4}Checking for updates...${RESET4}`);
|
|
6255
|
+
let latest;
|
|
6256
|
+
try {
|
|
6257
|
+
latest = execSync5("npm view @keepgoingdev/cli version", {
|
|
6258
|
+
encoding: "utf-8",
|
|
6259
|
+
timeout: 1e4,
|
|
6260
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6261
|
+
}).trim();
|
|
6262
|
+
} catch {
|
|
6263
|
+
console.error(`${YELLOW3}Could not reach the npm registry. Check your network connection.${RESET4}
|
|
6264
|
+
`);
|
|
6265
|
+
process.exit(1);
|
|
6266
|
+
}
|
|
6267
|
+
if (!latest) {
|
|
6268
|
+
console.error(`${YELLOW3}Could not determine the latest version.${RESET4}
|
|
6269
|
+
`);
|
|
6270
|
+
process.exit(1);
|
|
6271
|
+
}
|
|
6272
|
+
const current = CLI_VERSION2;
|
|
6273
|
+
const updateAvailable = isNewerVersion(current, latest);
|
|
6274
|
+
if (!updateAvailable) {
|
|
6275
|
+
console.log(`${GREEN3}Already up to date.${RESET4}
|
|
6276
|
+
`);
|
|
6277
|
+
return;
|
|
6278
|
+
}
|
|
6279
|
+
console.log(`${YELLOW3}Update available:${RESET4} ${DIM4}${current}${RESET4} -> ${BOLD3}${latest}${RESET4}
|
|
6280
|
+
`);
|
|
6281
|
+
console.log(`${DIM4}Installing @keepgoingdev/cli@${latest}...${RESET4}
|
|
6282
|
+
`);
|
|
6283
|
+
try {
|
|
6284
|
+
execSync5(`npm install -g @keepgoingdev/cli@${latest}`, {
|
|
6285
|
+
encoding: "utf-8",
|
|
6286
|
+
timeout: 6e4,
|
|
6287
|
+
stdio: "inherit"
|
|
6288
|
+
});
|
|
6289
|
+
console.log(`
|
|
6290
|
+
${GREEN3}Updated to v${latest}${RESET4}
|
|
6291
|
+
`);
|
|
6292
|
+
} catch {
|
|
6293
|
+
console.error(`
|
|
6294
|
+
${YELLOW3}Update failed.${RESET4} Try manually:
|
|
6295
|
+
`);
|
|
6296
|
+
console.error(` ${BOLD3}npm install -g @keepgoingdev/cli@latest${RESET4}
|
|
6297
|
+
`);
|
|
6298
|
+
process.exit(1);
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
|
|
6248
6302
|
// src/index.ts
|
|
6249
6303
|
var HELP_TEXT = `
|
|
6250
6304
|
keepgoing: resume side projects without the mental friction
|
|
@@ -6264,6 +6318,7 @@ Commands:
|
|
|
6264
6318
|
continue Export context for use in another AI tool
|
|
6265
6319
|
save Save a checkpoint (auto-generates from git)
|
|
6266
6320
|
hook Manage the shell hook (zsh, bash, fish)
|
|
6321
|
+
update Update the CLI to the latest version
|
|
6267
6322
|
activate <key> Activate a Pro license on this device
|
|
6268
6323
|
deactivate Deactivate the Pro license from this device
|
|
6269
6324
|
|
|
@@ -6428,6 +6483,13 @@ Usage: keepgoing activate <key>
|
|
|
6428
6483
|
|
|
6429
6484
|
Example:
|
|
6430
6485
|
keepgoing activate XXXX-XXXX-XXXX-XXXX
|
|
6486
|
+
`,
|
|
6487
|
+
update: `
|
|
6488
|
+
keepgoing update: Update the CLI to the latest version
|
|
6489
|
+
|
|
6490
|
+
Usage: keepgoing update
|
|
6491
|
+
|
|
6492
|
+
Checks the npm registry for a newer version and installs it globally.
|
|
6431
6493
|
`,
|
|
6432
6494
|
deactivate: `
|
|
6433
6495
|
keepgoing deactivate: Deactivate the Pro license from this device
|
|
@@ -6709,8 +6771,11 @@ async function main() {
|
|
|
6709
6771
|
console.log(COMMAND_HELP.hook);
|
|
6710
6772
|
}
|
|
6711
6773
|
break;
|
|
6774
|
+
case "update":
|
|
6775
|
+
await updateCommand();
|
|
6776
|
+
break;
|
|
6712
6777
|
case "version":
|
|
6713
|
-
console.log(`keepgoing v${"1.
|
|
6778
|
+
console.log(`keepgoing v${"1.5.0"}`);
|
|
6714
6779
|
break;
|
|
6715
6780
|
case "activate":
|
|
6716
6781
|
await activateCommand({ licenseKey: subcommand });
|
|
@@ -6725,6 +6790,20 @@ async function main() {
|
|
|
6725
6790
|
console.error(`Unknown command: "${command}". Run "keepgoing --help" for usage.`);
|
|
6726
6791
|
process.exit(1);
|
|
6727
6792
|
}
|
|
6793
|
+
if (command && command !== "update" && command !== "version" && command !== "help" && !json && !quiet && !parsed.help) {
|
|
6794
|
+
showUpdateHint();
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6797
|
+
function showUpdateHint() {
|
|
6798
|
+
const cached = getCachedUpdateInfo();
|
|
6799
|
+
if (cached?.updateAvailable) {
|
|
6800
|
+
const DIM5 = "\x1B[2m";
|
|
6801
|
+
const BOLD4 = "\x1B[1m";
|
|
6802
|
+
const RESET5 = "\x1B[0m";
|
|
6803
|
+
console.log(`
|
|
6804
|
+
${DIM5}Update available: ${cached.current} -> ${cached.latest}. Run:${RESET5} ${BOLD4}keepgoing update${RESET5}`);
|
|
6805
|
+
}
|
|
6806
|
+
spawnBackgroundCheck();
|
|
6728
6807
|
}
|
|
6729
6808
|
main().catch((err) => {
|
|
6730
6809
|
console.error(err instanceof Error ? err.message : String(err));
|