@keepgoingdev/cli 1.0.0 → 1.1.1
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 +526 -80
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -159,6 +159,62 @@ function getTouchedFiles(workspacePath) {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// ../../packages/shared/src/briefingTier.ts
|
|
163
|
+
var MODEL_TIERS = {
|
|
164
|
+
// Standard: small/fast models (compact is only reachable via explicit tier or context window)
|
|
165
|
+
"claude-3-haiku": "standard",
|
|
166
|
+
"claude-3.5-haiku": "standard",
|
|
167
|
+
"claude-haiku-4-5": "standard",
|
|
168
|
+
"gpt-4o-mini": "standard",
|
|
169
|
+
"gemini-flash": "standard",
|
|
170
|
+
// Detailed: mid-tier models
|
|
171
|
+
"claude-3.5-sonnet": "detailed",
|
|
172
|
+
"claude-sonnet-4": "detailed",
|
|
173
|
+
"claude-sonnet-4-5": "detailed",
|
|
174
|
+
"claude-sonnet-4-6": "detailed",
|
|
175
|
+
"gpt-4o": "detailed",
|
|
176
|
+
"gemini-pro": "detailed",
|
|
177
|
+
// Full: large context models
|
|
178
|
+
"claude-opus-4": "full",
|
|
179
|
+
"claude-opus-4-5": "full",
|
|
180
|
+
"claude-opus-4-6": "full",
|
|
181
|
+
"o1": "full",
|
|
182
|
+
"o3": "full",
|
|
183
|
+
"gemini-ultra": "full"
|
|
184
|
+
};
|
|
185
|
+
function resolveTier(opts) {
|
|
186
|
+
if (opts?.tier) {
|
|
187
|
+
return opts.tier;
|
|
188
|
+
}
|
|
189
|
+
if (opts?.model) {
|
|
190
|
+
const fromModel = tierFromModelName(opts.model);
|
|
191
|
+
if (fromModel) return fromModel;
|
|
192
|
+
}
|
|
193
|
+
if (opts?.contextWindow !== void 0) {
|
|
194
|
+
return tierFromContextWindow(opts.contextWindow);
|
|
195
|
+
}
|
|
196
|
+
return "standard";
|
|
197
|
+
}
|
|
198
|
+
function tierFromModelName(model) {
|
|
199
|
+
const normalized = model.toLowerCase().trim();
|
|
200
|
+
if (MODEL_TIERS[normalized]) {
|
|
201
|
+
return MODEL_TIERS[normalized];
|
|
202
|
+
}
|
|
203
|
+
const entries = Object.entries(MODEL_TIERS).sort((a, b) => b[0].length - a[0].length);
|
|
204
|
+
for (const [key, tier] of entries) {
|
|
205
|
+
if (normalized.startsWith(key)) {
|
|
206
|
+
return tier;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
function tierFromContextWindow(tokens) {
|
|
212
|
+
if (tokens < 16e3) return "compact";
|
|
213
|
+
if (tokens < 64e3) return "standard";
|
|
214
|
+
if (tokens < 2e5) return "detailed";
|
|
215
|
+
return "full";
|
|
216
|
+
}
|
|
217
|
+
|
|
162
218
|
// ../../packages/shared/src/reentry.ts
|
|
163
219
|
var RECENT_SESSION_COUNT = 5;
|
|
164
220
|
function generateBriefing(lastSession, recentSessions, projectState, gitBranch, recentCommitMessages) {
|
|
@@ -184,6 +240,61 @@ function generateBriefing(lastSession, recentSessions, projectState, gitBranch,
|
|
|
184
240
|
function getRecentSessions(allSessions, count = RECENT_SESSION_COUNT) {
|
|
185
241
|
return allSessions.slice(-count).reverse();
|
|
186
242
|
}
|
|
243
|
+
function generateEnrichedBriefing(opts) {
|
|
244
|
+
const tier = resolveTier({
|
|
245
|
+
tier: opts.tier,
|
|
246
|
+
model: opts.model,
|
|
247
|
+
contextWindow: opts.contextWindow
|
|
248
|
+
});
|
|
249
|
+
const core = generateBriefing(
|
|
250
|
+
opts.lastSession,
|
|
251
|
+
opts.recentSessions,
|
|
252
|
+
opts.projectState,
|
|
253
|
+
opts.gitBranch,
|
|
254
|
+
opts.recentCommits
|
|
255
|
+
);
|
|
256
|
+
if (!core) return void 0;
|
|
257
|
+
const enriched = { tier, core };
|
|
258
|
+
if (tier === "compact") {
|
|
259
|
+
return enriched;
|
|
260
|
+
}
|
|
261
|
+
enriched.blocker = opts.lastSession?.blocker;
|
|
262
|
+
enriched.gitBranch = opts.gitBranch;
|
|
263
|
+
enriched.isWorktree = opts.isWorktree;
|
|
264
|
+
if (tier === "standard") {
|
|
265
|
+
return enriched;
|
|
266
|
+
}
|
|
267
|
+
if (opts.decisions && opts.decisions.length > 0) {
|
|
268
|
+
enriched.decisions = opts.decisions.slice(0, tier === "detailed" ? 3 : 10);
|
|
269
|
+
}
|
|
270
|
+
if (opts.allTouchedFiles && opts.allTouchedFiles.length > 0) {
|
|
271
|
+
enriched.touchedFiles = tier === "detailed" ? opts.allTouchedFiles.slice(0, 10) : opts.allTouchedFiles;
|
|
272
|
+
} else if (opts.lastSession?.touchedFiles && opts.lastSession.touchedFiles.length > 0) {
|
|
273
|
+
enriched.touchedFiles = tier === "detailed" ? opts.lastSession.touchedFiles.slice(0, 10) : opts.lastSession.touchedFiles;
|
|
274
|
+
}
|
|
275
|
+
if (tier === "detailed") {
|
|
276
|
+
return enriched;
|
|
277
|
+
}
|
|
278
|
+
if (opts.allSessions && opts.allSessions.length > 0) {
|
|
279
|
+
const recent = opts.allSessions.slice(-5).reverse();
|
|
280
|
+
enriched.sessionHistory = recent.map((s) => ({
|
|
281
|
+
timestamp: s.timestamp,
|
|
282
|
+
summary: s.summary || "",
|
|
283
|
+
nextStep: s.nextStep || "",
|
|
284
|
+
branch: s.gitBranch
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
if (opts.recentCommits && opts.recentCommits.length > 0) {
|
|
288
|
+
enriched.recentCommits = opts.recentCommits;
|
|
289
|
+
}
|
|
290
|
+
if (opts.fileConflicts && opts.fileConflicts.length > 0) {
|
|
291
|
+
enriched.fileConflicts = opts.fileConflicts;
|
|
292
|
+
}
|
|
293
|
+
if (opts.branchOverlaps && opts.branchOverlaps.length > 0) {
|
|
294
|
+
enriched.branchOverlaps = opts.branchOverlaps;
|
|
295
|
+
}
|
|
296
|
+
return enriched;
|
|
297
|
+
}
|
|
187
298
|
function buildCurrentFocus(lastSession, projectState, gitBranch) {
|
|
188
299
|
if (projectState.derivedCurrentFocus) {
|
|
189
300
|
return projectState.derivedCurrentFocus;
|
|
@@ -359,9 +470,123 @@ function inferFocusFromFiles(files) {
|
|
|
359
470
|
return names.join(", ");
|
|
360
471
|
}
|
|
361
472
|
|
|
473
|
+
// ../../packages/shared/src/continueOn.ts
|
|
474
|
+
import path2 from "path";
|
|
475
|
+
function gatherContinueOnContext(reader, workspacePath) {
|
|
476
|
+
const projectName = path2.basename(workspacePath);
|
|
477
|
+
const gitBranch = reader.getCurrentBranch();
|
|
478
|
+
if (!reader.exists()) {
|
|
479
|
+
return {
|
|
480
|
+
projectName,
|
|
481
|
+
gitBranch,
|
|
482
|
+
recentCheckpoints: [],
|
|
483
|
+
recentDecisions: [],
|
|
484
|
+
currentTasks: [],
|
|
485
|
+
recentCommitMessages: []
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
const { session: lastCheckpoint } = reader.getScopedLastSession();
|
|
489
|
+
const recentCheckpoints = reader.getScopedRecentSessions(5);
|
|
490
|
+
const recentDecisions = reader.getScopedRecentDecisions(3);
|
|
491
|
+
const currentTasks = reader.getCurrentTasks();
|
|
492
|
+
const state = reader.getState() ?? {};
|
|
493
|
+
const sinceTimestamp = lastCheckpoint?.timestamp;
|
|
494
|
+
const recentCommitMessages = sinceTimestamp ? getCommitMessagesSince(workspacePath, sinceTimestamp) : [];
|
|
495
|
+
const briefing = generateBriefing(
|
|
496
|
+
lastCheckpoint,
|
|
497
|
+
recentCheckpoints,
|
|
498
|
+
state,
|
|
499
|
+
gitBranch,
|
|
500
|
+
recentCommitMessages
|
|
501
|
+
);
|
|
502
|
+
return {
|
|
503
|
+
projectName,
|
|
504
|
+
gitBranch,
|
|
505
|
+
briefing,
|
|
506
|
+
lastCheckpoint,
|
|
507
|
+
recentCheckpoints,
|
|
508
|
+
recentDecisions,
|
|
509
|
+
currentTasks,
|
|
510
|
+
recentCommitMessages
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function formatContinueOnPrompt(context, options) {
|
|
514
|
+
const opts = { includeCommits: true, includeFiles: true, ...options };
|
|
515
|
+
const lines = [];
|
|
516
|
+
lines.push(`# Project Context: ${context.projectName}`);
|
|
517
|
+
lines.push("");
|
|
518
|
+
lines.push("I'm continuing work on a project. Here is my development context from KeepGoing.");
|
|
519
|
+
lines.push("");
|
|
520
|
+
lines.push("## Current Status");
|
|
521
|
+
if (context.gitBranch) {
|
|
522
|
+
lines.push(`- **Branch:** ${context.gitBranch}`);
|
|
523
|
+
}
|
|
524
|
+
if (context.briefing) {
|
|
525
|
+
lines.push(`- **Last worked:** ${context.briefing.lastWorked}`);
|
|
526
|
+
lines.push(`- **Focus:** ${context.briefing.currentFocus}`);
|
|
527
|
+
} else if (context.lastCheckpoint) {
|
|
528
|
+
lines.push(`- **Last worked:** ${formatRelativeTime(context.lastCheckpoint.timestamp)}`);
|
|
529
|
+
if (context.lastCheckpoint.summary) {
|
|
530
|
+
lines.push(`- **Focus:** ${context.lastCheckpoint.summary}`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (context.lastCheckpoint) {
|
|
534
|
+
lines.push("");
|
|
535
|
+
lines.push("## Last Session");
|
|
536
|
+
if (context.lastCheckpoint.summary) {
|
|
537
|
+
lines.push(`- **Summary:** ${context.lastCheckpoint.summary}`);
|
|
538
|
+
}
|
|
539
|
+
if (context.lastCheckpoint.nextStep) {
|
|
540
|
+
lines.push(`- **Next step:** ${context.lastCheckpoint.nextStep}`);
|
|
541
|
+
}
|
|
542
|
+
if (context.lastCheckpoint.blocker) {
|
|
543
|
+
lines.push(`- **Blocker:** ${context.lastCheckpoint.blocker}`);
|
|
544
|
+
}
|
|
545
|
+
if (opts.includeFiles && context.lastCheckpoint.touchedFiles.length > 0) {
|
|
546
|
+
const files = context.lastCheckpoint.touchedFiles.slice(0, 10).join(", ");
|
|
547
|
+
const extra = context.lastCheckpoint.touchedFiles.length > 10 ? ` (+${context.lastCheckpoint.touchedFiles.length - 10} more)` : "";
|
|
548
|
+
lines.push(`- **Files touched:** ${files}${extra}`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const activeTasks = context.currentTasks.filter((t) => t.sessionActive);
|
|
552
|
+
if (activeTasks.length > 0) {
|
|
553
|
+
lines.push("");
|
|
554
|
+
lines.push("## Active Sessions");
|
|
555
|
+
for (const task of activeTasks) {
|
|
556
|
+
const label = task.agentLabel || "Unknown agent";
|
|
557
|
+
const branch = task.branch ? ` on \`${task.branch}\`` : "";
|
|
558
|
+
lines.push(`- **${label}**${branch}: ${task.taskSummary || "Working"}`);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (context.recentDecisions.length > 0) {
|
|
562
|
+
lines.push("");
|
|
563
|
+
lines.push("## Recent Decisions");
|
|
564
|
+
for (const d of context.recentDecisions) {
|
|
565
|
+
lines.push(`- ${d.classification.category}: ${d.commitMessage}`);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (opts.includeCommits && context.recentCommitMessages.length > 0) {
|
|
569
|
+
lines.push("");
|
|
570
|
+
lines.push("## Recent Commits");
|
|
571
|
+
const commits = context.recentCommitMessages.slice(0, 10);
|
|
572
|
+
for (const msg of commits) {
|
|
573
|
+
lines.push(`- ${msg}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
lines.push("");
|
|
577
|
+
lines.push("---");
|
|
578
|
+
const nextStep = context.lastCheckpoint?.nextStep || context.briefing?.suggestedNext || "continue where I left off";
|
|
579
|
+
lines.push(`Please help me continue this work. My next step is: ${nextStep}.`);
|
|
580
|
+
let result = lines.join("\n");
|
|
581
|
+
if (opts.maxLength && result.length > opts.maxLength) {
|
|
582
|
+
result = result.slice(0, opts.maxLength - 3) + "...";
|
|
583
|
+
}
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
|
|
362
587
|
// ../../packages/shared/src/storage.ts
|
|
363
588
|
import fs from "fs";
|
|
364
|
-
import
|
|
589
|
+
import path3 from "path";
|
|
365
590
|
import { randomUUID as randomUUID2, createHash } from "crypto";
|
|
366
591
|
var STORAGE_DIR = ".keepgoing";
|
|
367
592
|
var META_FILE = "meta.json";
|
|
@@ -384,11 +609,11 @@ var KeepGoingWriter = class {
|
|
|
384
609
|
currentTasksFilePath;
|
|
385
610
|
constructor(workspacePath) {
|
|
386
611
|
const mainRoot = resolveStorageRoot(workspacePath);
|
|
387
|
-
this.storagePath =
|
|
388
|
-
this.sessionsFilePath =
|
|
389
|
-
this.stateFilePath =
|
|
390
|
-
this.metaFilePath =
|
|
391
|
-
this.currentTasksFilePath =
|
|
612
|
+
this.storagePath = path3.join(mainRoot, STORAGE_DIR);
|
|
613
|
+
this.sessionsFilePath = path3.join(this.storagePath, SESSIONS_FILE);
|
|
614
|
+
this.stateFilePath = path3.join(this.storagePath, STATE_FILE);
|
|
615
|
+
this.metaFilePath = path3.join(this.storagePath, META_FILE);
|
|
616
|
+
this.currentTasksFilePath = path3.join(this.storagePath, CURRENT_TASKS_FILE);
|
|
392
617
|
}
|
|
393
618
|
ensureDir() {
|
|
394
619
|
if (!fs.existsSync(this.storagePath)) {
|
|
@@ -702,24 +927,24 @@ function capitalize(s) {
|
|
|
702
927
|
|
|
703
928
|
// ../../packages/shared/src/decisionStorage.ts
|
|
704
929
|
import fs3 from "fs";
|
|
705
|
-
import
|
|
930
|
+
import path5 from "path";
|
|
706
931
|
|
|
707
932
|
// ../../packages/shared/src/license.ts
|
|
708
933
|
import crypto from "crypto";
|
|
709
934
|
import fs2 from "fs";
|
|
710
935
|
import os from "os";
|
|
711
|
-
import
|
|
936
|
+
import path4 from "path";
|
|
712
937
|
var LICENSE_FILE = "license.json";
|
|
713
938
|
var DEVICE_ID_FILE = "device-id";
|
|
714
939
|
function getGlobalLicenseDir() {
|
|
715
|
-
return
|
|
940
|
+
return path4.join(os.homedir(), ".keepgoing");
|
|
716
941
|
}
|
|
717
942
|
function getGlobalLicensePath() {
|
|
718
|
-
return
|
|
943
|
+
return path4.join(getGlobalLicenseDir(), LICENSE_FILE);
|
|
719
944
|
}
|
|
720
945
|
function getDeviceId() {
|
|
721
946
|
const dir = getGlobalLicenseDir();
|
|
722
|
-
const filePath =
|
|
947
|
+
const filePath = path4.join(dir, DEVICE_ID_FILE);
|
|
723
948
|
try {
|
|
724
949
|
const existing = fs2.readFileSync(filePath, "utf-8").trim();
|
|
725
950
|
if (existing) return existing;
|
|
@@ -786,7 +1011,7 @@ function writeLicenseStore(store) {
|
|
|
786
1011
|
if (!fs2.existsSync(dirPath)) {
|
|
787
1012
|
fs2.mkdirSync(dirPath, { recursive: true });
|
|
788
1013
|
}
|
|
789
|
-
const licensePath =
|
|
1014
|
+
const licensePath = path4.join(dirPath, LICENSE_FILE);
|
|
790
1015
|
fs2.writeFileSync(licensePath, JSON.stringify(store, null, 2), "utf-8");
|
|
791
1016
|
_cachedStore = store;
|
|
792
1017
|
_cacheTimestamp = Date.now();
|
|
@@ -828,7 +1053,7 @@ var currentGate = new DefaultFeatureGate();
|
|
|
828
1053
|
|
|
829
1054
|
// ../../packages/shared/src/reader.ts
|
|
830
1055
|
import fs4 from "fs";
|
|
831
|
-
import
|
|
1056
|
+
import path6 from "path";
|
|
832
1057
|
var STORAGE_DIR2 = ".keepgoing";
|
|
833
1058
|
var META_FILE2 = "meta.json";
|
|
834
1059
|
var SESSIONS_FILE2 = "sessions.json";
|
|
@@ -850,12 +1075,12 @@ var KeepGoingReader = class {
|
|
|
850
1075
|
this.workspacePath = workspacePath;
|
|
851
1076
|
const mainRoot = resolveStorageRoot(workspacePath);
|
|
852
1077
|
this._isWorktree = mainRoot !== workspacePath;
|
|
853
|
-
this.storagePath =
|
|
854
|
-
this.metaFilePath =
|
|
855
|
-
this.sessionsFilePath =
|
|
856
|
-
this.decisionsFilePath =
|
|
857
|
-
this.stateFilePath =
|
|
858
|
-
this.currentTasksFilePath =
|
|
1078
|
+
this.storagePath = path6.join(mainRoot, STORAGE_DIR2);
|
|
1079
|
+
this.metaFilePath = path6.join(this.storagePath, META_FILE2);
|
|
1080
|
+
this.sessionsFilePath = path6.join(this.storagePath, SESSIONS_FILE2);
|
|
1081
|
+
this.decisionsFilePath = path6.join(this.storagePath, DECISIONS_FILE);
|
|
1082
|
+
this.stateFilePath = path6.join(this.storagePath, STATE_FILE2);
|
|
1083
|
+
this.currentTasksFilePath = path6.join(this.storagePath, CURRENT_TASKS_FILE2);
|
|
859
1084
|
}
|
|
860
1085
|
/** Check if .keepgoing/ directory exists. */
|
|
861
1086
|
exists() {
|
|
@@ -1111,7 +1336,7 @@ var KeepGoingReader = class {
|
|
|
1111
1336
|
// ../../packages/shared/src/setup.ts
|
|
1112
1337
|
import fs5 from "fs";
|
|
1113
1338
|
import os2 from "os";
|
|
1114
|
-
import
|
|
1339
|
+
import path7 from "path";
|
|
1115
1340
|
var KEEPGOING_MARKER = "@keepgoingdev/mcp-server";
|
|
1116
1341
|
var SESSION_START_HOOK = {
|
|
1117
1342
|
matcher: "",
|
|
@@ -1156,19 +1381,19 @@ function hasKeepGoingHook(hookEntries) {
|
|
|
1156
1381
|
}
|
|
1157
1382
|
function resolveScopePaths(scope, workspacePath) {
|
|
1158
1383
|
if (scope === "user") {
|
|
1159
|
-
const claudeDir2 =
|
|
1384
|
+
const claudeDir2 = path7.join(os2.homedir(), ".claude");
|
|
1160
1385
|
return {
|
|
1161
1386
|
claudeDir: claudeDir2,
|
|
1162
|
-
settingsPath:
|
|
1163
|
-
claudeMdPath:
|
|
1387
|
+
settingsPath: path7.join(claudeDir2, "settings.json"),
|
|
1388
|
+
claudeMdPath: path7.join(claudeDir2, "CLAUDE.md")
|
|
1164
1389
|
};
|
|
1165
1390
|
}
|
|
1166
|
-
const claudeDir =
|
|
1167
|
-
const dotClaudeMdPath =
|
|
1168
|
-
const rootClaudeMdPath =
|
|
1391
|
+
const claudeDir = path7.join(workspacePath, ".claude");
|
|
1392
|
+
const dotClaudeMdPath = path7.join(workspacePath, ".claude", "CLAUDE.md");
|
|
1393
|
+
const rootClaudeMdPath = path7.join(workspacePath, "CLAUDE.md");
|
|
1169
1394
|
return {
|
|
1170
1395
|
claudeDir,
|
|
1171
|
-
settingsPath:
|
|
1396
|
+
settingsPath: path7.join(claudeDir, "settings.json"),
|
|
1172
1397
|
claudeMdPath: fs5.existsSync(dotClaudeMdPath) ? dotClaudeMdPath : rootClaudeMdPath
|
|
1173
1398
|
};
|
|
1174
1399
|
}
|
|
@@ -1225,7 +1450,6 @@ function setupProject(options) {
|
|
|
1225
1450
|
scope = "project",
|
|
1226
1451
|
sessionHooks = true,
|
|
1227
1452
|
claudeMd = true,
|
|
1228
|
-
hasProLicense = false,
|
|
1229
1453
|
statusline
|
|
1230
1454
|
} = options;
|
|
1231
1455
|
const messages = [];
|
|
@@ -1250,7 +1474,7 @@ function setupProject(options) {
|
|
|
1250
1474
|
messages.push(`Warning: ${conflict}`);
|
|
1251
1475
|
}
|
|
1252
1476
|
}
|
|
1253
|
-
if (scope === "project"
|
|
1477
|
+
if (scope === "project") {
|
|
1254
1478
|
const needsUpdate = settings.statusLine?.command && statusline?.isLegacy?.(settings.statusLine.command);
|
|
1255
1479
|
if (!settings.statusLine || needsUpdate) {
|
|
1256
1480
|
settings.statusLine = {
|
|
@@ -1281,7 +1505,7 @@ function setupProject(options) {
|
|
|
1281
1505
|
messages.push(`CLAUDE.md: KeepGoing section already present in ${mdLabel}, skipped`);
|
|
1282
1506
|
} else {
|
|
1283
1507
|
const updated = existing + CLAUDE_MD_SECTION;
|
|
1284
|
-
const mdDir =
|
|
1508
|
+
const mdDir = path7.dirname(claudeMdPath);
|
|
1285
1509
|
if (!fs5.existsSync(mdDir)) {
|
|
1286
1510
|
fs5.mkdirSync(mdDir, { recursive: true });
|
|
1287
1511
|
}
|
|
@@ -1430,29 +1654,6 @@ function renderNoData() {
|
|
|
1430
1654
|
`No KeepGoing data found. Run ${BOLD}keepgoing save${RESET} to save your first checkpoint.`
|
|
1431
1655
|
);
|
|
1432
1656
|
}
|
|
1433
|
-
function renderBriefing(briefing, decisions) {
|
|
1434
|
-
const label = (s) => `${CYAN}${s}${RESET}`;
|
|
1435
|
-
console.log(`
|
|
1436
|
-
${BOLD}KeepGoing Re-entry Briefing${RESET}
|
|
1437
|
-
`);
|
|
1438
|
-
console.log(` ${label("Last worked:")} ${briefing.lastWorked}`);
|
|
1439
|
-
console.log(` ${label("Focus:")} ${briefing.currentFocus}`);
|
|
1440
|
-
console.log(` ${label("Activity:")} ${briefing.recentActivity}`);
|
|
1441
|
-
console.log(` ${label("Next:")} ${briefing.suggestedNext}`);
|
|
1442
|
-
console.log(` ${label("Quick start:")} ${briefing.smallNextStep}`);
|
|
1443
|
-
if (decisions && decisions.length > 0) {
|
|
1444
|
-
console.log(`
|
|
1445
|
-
${label("Recent decisions:")}`);
|
|
1446
|
-
for (const d of decisions) {
|
|
1447
|
-
const relTime = formatRelativeTime(d.timestamp);
|
|
1448
|
-
console.log(` ${d.classification.category}: ${d.commitMessage} ${DIM}(${relTime})${RESET}`);
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
console.log("");
|
|
1452
|
-
}
|
|
1453
|
-
function renderBriefingQuiet(briefing) {
|
|
1454
|
-
console.log(`KeepGoing \xB7 ${briefing.lastWorked} \xB7 Focus: ${briefing.currentFocus} \xB7 Next: ${briefing.suggestedNext}`);
|
|
1455
|
-
}
|
|
1456
1657
|
function renderMomentum(checkpoint, ctx) {
|
|
1457
1658
|
const relTime = formatRelativeTime(checkpoint.timestamp);
|
|
1458
1659
|
const label = (s) => `${CYAN}${s}${RESET}`;
|
|
@@ -1602,18 +1803,130 @@ function renderSessionGroupHeader(sessionId, count) {
|
|
|
1602
1803
|
const shortId = sessionId.slice(0, 8);
|
|
1603
1804
|
console.log(`${BOLD}Session ${shortId}${RESET} ${DIM}(${count} checkpoint${count !== 1 ? "s" : ""})${RESET}`);
|
|
1604
1805
|
}
|
|
1806
|
+
function renderContinueOn(prompt, copied, target) {
|
|
1807
|
+
console.log(`
|
|
1808
|
+
${BOLD}KeepGoing Continue On${RESET}
|
|
1809
|
+
`);
|
|
1810
|
+
if (copied) {
|
|
1811
|
+
console.log(`${GREEN}\u2714 Context copied to clipboard${RESET}`);
|
|
1812
|
+
} else {
|
|
1813
|
+
console.log(`${YELLOW}\u26A0 Could not copy to clipboard. Prompt printed below.${RESET}`);
|
|
1814
|
+
}
|
|
1815
|
+
if (target) {
|
|
1816
|
+
console.log(`${DIM}Target: ${target}${RESET}`);
|
|
1817
|
+
}
|
|
1818
|
+
console.log("");
|
|
1819
|
+
console.log(`${DIM}--- prompt start ---${RESET}`);
|
|
1820
|
+
console.log(prompt);
|
|
1821
|
+
console.log(`${DIM}--- prompt end ---${RESET}`);
|
|
1822
|
+
console.log("");
|
|
1823
|
+
}
|
|
1824
|
+
function renderContinueOnQuiet(copied, target) {
|
|
1825
|
+
const targetStr = target ? ` (${target})` : "";
|
|
1826
|
+
if (copied) {
|
|
1827
|
+
console.log(`KeepGoing \xB7 Context copied to clipboard${targetStr}`);
|
|
1828
|
+
} else {
|
|
1829
|
+
console.log(`KeepGoing \xB7 Failed to copy context to clipboard${targetStr}`);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
function renderEnrichedBriefing(briefing) {
|
|
1833
|
+
const { tier, core } = briefing;
|
|
1834
|
+
const label = (s) => `${CYAN}${s}${RESET}`;
|
|
1835
|
+
console.log(`
|
|
1836
|
+
${BOLD}KeepGoing Re-entry Briefing${RESET} ${DIM}(${tier})${RESET}
|
|
1837
|
+
`);
|
|
1838
|
+
if (briefing.isWorktree && briefing.gitBranch) {
|
|
1839
|
+
console.log(` ${DIM}Worktree: scoped to ${briefing.gitBranch}${RESET}
|
|
1840
|
+
`);
|
|
1841
|
+
}
|
|
1842
|
+
if (tier === "compact") {
|
|
1843
|
+
console.log(` ${label("Last worked:")} ${core.lastWorked}`);
|
|
1844
|
+
console.log(` ${label("Focus:")} ${core.currentFocus}`);
|
|
1845
|
+
console.log(` ${label("Quick start:")} ${core.smallNextStep}`);
|
|
1846
|
+
console.log("");
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
console.log(` ${label("Last worked:")} ${core.lastWorked}`);
|
|
1850
|
+
console.log(` ${label("Focus:")} ${core.currentFocus}`);
|
|
1851
|
+
console.log(` ${label("Activity:")} ${core.recentActivity}`);
|
|
1852
|
+
console.log(` ${label("Next:")} ${core.suggestedNext}`);
|
|
1853
|
+
console.log(` ${label("Quick start:")} ${core.smallNextStep}`);
|
|
1854
|
+
if (briefing.blocker) {
|
|
1855
|
+
console.log(` ${label("Blocker:")} ${YELLOW}${briefing.blocker}${RESET}`);
|
|
1856
|
+
}
|
|
1857
|
+
if (briefing.decisions && briefing.decisions.length > 0) {
|
|
1858
|
+
console.log(`
|
|
1859
|
+
${label("Recent decisions:")}`);
|
|
1860
|
+
for (const d of briefing.decisions) {
|
|
1861
|
+
const relTime = formatRelativeTime(d.timestamp);
|
|
1862
|
+
console.log(` ${d.classification.category}: ${d.commitMessage} ${DIM}(${relTime})${RESET}`);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (briefing.touchedFiles && briefing.touchedFiles.length > 0) {
|
|
1866
|
+
console.log(`
|
|
1867
|
+
${label(`Files touched (${briefing.touchedFiles.length}):`)}`);
|
|
1868
|
+
const MAX_FILES = tier === "full" ? 20 : 10;
|
|
1869
|
+
const shown = briefing.touchedFiles.slice(0, MAX_FILES);
|
|
1870
|
+
for (const f of shown) {
|
|
1871
|
+
console.log(` ${DIM}${f}${RESET}`);
|
|
1872
|
+
}
|
|
1873
|
+
if (briefing.touchedFiles.length > MAX_FILES) {
|
|
1874
|
+
console.log(` ${DIM}...and ${briefing.touchedFiles.length - MAX_FILES} more${RESET}`);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
if (briefing.sessionHistory && briefing.sessionHistory.length > 0) {
|
|
1878
|
+
console.log(`
|
|
1879
|
+
${label("Session history:")}`);
|
|
1880
|
+
for (const s of briefing.sessionHistory) {
|
|
1881
|
+
const relTime = formatRelativeTime(s.timestamp);
|
|
1882
|
+
const branch = s.branch ? ` ${GREEN}(${s.branch})${RESET}` : "";
|
|
1883
|
+
console.log(` ${DIM}${relTime}${branch}${RESET} ${s.summary || "No summary"}`);
|
|
1884
|
+
if (s.nextStep) {
|
|
1885
|
+
console.log(` ${CYAN}\u2192${RESET} ${s.nextStep}`);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
if (briefing.recentCommits && briefing.recentCommits.length > 0) {
|
|
1890
|
+
console.log(`
|
|
1891
|
+
${label("Recent commits:")}`);
|
|
1892
|
+
for (const msg of briefing.recentCommits.slice(0, 10)) {
|
|
1893
|
+
console.log(` ${DIM}${msg}${RESET}`);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
if (briefing.fileConflicts && briefing.fileConflicts.length > 0) {
|
|
1897
|
+
console.log(`
|
|
1898
|
+
${YELLOW}File conflicts:${RESET}`);
|
|
1899
|
+
for (const c of briefing.fileConflicts) {
|
|
1900
|
+
const labels = c.sessions.map((s) => s.agentLabel || s.sessionId).join(", ");
|
|
1901
|
+
console.log(` ${c.file}: ${labels}`);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
if (briefing.branchOverlaps && briefing.branchOverlaps.length > 0) {
|
|
1905
|
+
console.log(`
|
|
1906
|
+
${YELLOW}Branch overlaps:${RESET}`);
|
|
1907
|
+
for (const o of briefing.branchOverlaps) {
|
|
1908
|
+
const labels = o.sessions.map((s) => s.agentLabel || s.sessionId).join(", ");
|
|
1909
|
+
console.log(` ${o.branch}: ${labels}`);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
console.log("");
|
|
1913
|
+
}
|
|
1914
|
+
function renderEnrichedBriefingQuiet(briefing) {
|
|
1915
|
+
const { core } = briefing;
|
|
1916
|
+
console.log(`KeepGoing \xB7 ${core.lastWorked} \xB7 Focus: ${core.currentFocus} \xB7 Next: ${core.smallNextStep}`);
|
|
1917
|
+
}
|
|
1605
1918
|
|
|
1606
1919
|
// src/updateCheck.ts
|
|
1607
1920
|
import { spawn } from "child_process";
|
|
1608
1921
|
import { readFileSync, existsSync } from "fs";
|
|
1609
|
-
import
|
|
1922
|
+
import path8 from "path";
|
|
1610
1923
|
import os3 from "os";
|
|
1611
|
-
var CLI_VERSION = "1.
|
|
1924
|
+
var CLI_VERSION = "1.1.1";
|
|
1612
1925
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
|
|
1613
1926
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
1614
1927
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
1615
|
-
var CACHE_DIR =
|
|
1616
|
-
var CACHE_PATH =
|
|
1928
|
+
var CACHE_DIR = path8.join(os3.homedir(), ".keepgoing");
|
|
1929
|
+
var CACHE_PATH = path8.join(CACHE_DIR, "update-check.json");
|
|
1617
1930
|
function isNewerVersion(current, latest) {
|
|
1618
1931
|
const cur = current.split(".").map(Number);
|
|
1619
1932
|
const lat = latest.split(".").map(Number);
|
|
@@ -1728,7 +2041,7 @@ async function statusCommand(opts) {
|
|
|
1728
2041
|
}
|
|
1729
2042
|
|
|
1730
2043
|
// src/commands/save.ts
|
|
1731
|
-
import
|
|
2044
|
+
import path9 from "path";
|
|
1732
2045
|
async function saveCommand(opts) {
|
|
1733
2046
|
const { cwd, message, nextStepOverride, json, quiet, force } = opts;
|
|
1734
2047
|
const isManual = !!message;
|
|
@@ -1757,9 +2070,9 @@ async function saveCommand(opts) {
|
|
|
1757
2070
|
sessionStartTime: lastSession?.timestamp ?? now,
|
|
1758
2071
|
lastActivityTime: now
|
|
1759
2072
|
});
|
|
1760
|
-
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) =>
|
|
2073
|
+
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) => path9.basename(f)).join(", ")}`;
|
|
1761
2074
|
const nextStep = nextStepOverride ?? buildSmartNextStep(events);
|
|
1762
|
-
const projectName =
|
|
2075
|
+
const projectName = path9.basename(resolveStorageRoot(cwd));
|
|
1763
2076
|
const sessionId = generateSessionId({
|
|
1764
2077
|
workspaceRoot: cwd,
|
|
1765
2078
|
branch: gitBranch ?? void 0,
|
|
@@ -1793,7 +2106,7 @@ async function saveCommand(opts) {
|
|
|
1793
2106
|
|
|
1794
2107
|
// src/commands/hook.ts
|
|
1795
2108
|
import fs6 from "fs";
|
|
1796
|
-
import
|
|
2109
|
+
import path10 from "path";
|
|
1797
2110
|
import os4 from "os";
|
|
1798
2111
|
import { execSync } from "child_process";
|
|
1799
2112
|
var HOOK_MARKER_START = "# keepgoing-hook-start";
|
|
@@ -1853,14 +2166,14 @@ function detectShellRcFile(shellOverride) {
|
|
|
1853
2166
|
}
|
|
1854
2167
|
}
|
|
1855
2168
|
if (shell === "zsh") {
|
|
1856
|
-
return { shell: "zsh", rcFile:
|
|
2169
|
+
return { shell: "zsh", rcFile: path10.join(home, ".zshrc") };
|
|
1857
2170
|
}
|
|
1858
2171
|
if (shell === "bash") {
|
|
1859
|
-
return { shell: "bash", rcFile:
|
|
2172
|
+
return { shell: "bash", rcFile: path10.join(home, ".bashrc") };
|
|
1860
2173
|
}
|
|
1861
2174
|
if (shell === "fish") {
|
|
1862
|
-
const xdgConfig = process.env["XDG_CONFIG_HOME"] ||
|
|
1863
|
-
return { shell: "fish", rcFile:
|
|
2175
|
+
const xdgConfig = process.env["XDG_CONFIG_HOME"] || path10.join(home, ".config");
|
|
2176
|
+
return { shell: "fish", rcFile: path10.join(xdgConfig, "fish", "config.fish") };
|
|
1864
2177
|
}
|
|
1865
2178
|
return void 0;
|
|
1866
2179
|
}
|
|
@@ -2030,30 +2343,43 @@ async function briefingCommand(opts) {
|
|
|
2030
2343
|
const state = reader.getState() ?? {};
|
|
2031
2344
|
const sinceTimestamp = lastSession?.timestamp;
|
|
2032
2345
|
const recentCommits = sinceTimestamp ? getCommitMessagesSince(opts.cwd, sinceTimestamp) : [];
|
|
2033
|
-
const
|
|
2346
|
+
const decisions = reader.getScopedRecentDecisions(10);
|
|
2347
|
+
const allSessions = reader.getSessions();
|
|
2348
|
+
const fileConflicts = reader.detectFileConflicts();
|
|
2349
|
+
const branchOverlaps = reader.detectBranchOverlap();
|
|
2350
|
+
const effectiveTier = opts.quiet ? "compact" : opts.tier;
|
|
2351
|
+
const validTiers = ["compact", "standard", "detailed", "full"];
|
|
2352
|
+
const tier = effectiveTier && validTiers.includes(effectiveTier) ? effectiveTier : void 0;
|
|
2353
|
+
const briefing = generateEnrichedBriefing({
|
|
2354
|
+
tier,
|
|
2355
|
+
model: opts.model,
|
|
2034
2356
|
lastSession,
|
|
2035
2357
|
recentSessions,
|
|
2036
|
-
state,
|
|
2358
|
+
projectState: state,
|
|
2037
2359
|
gitBranch,
|
|
2038
|
-
recentCommits
|
|
2039
|
-
|
|
2360
|
+
recentCommits,
|
|
2361
|
+
decisions,
|
|
2362
|
+
allTouchedFiles: lastSession?.touchedFiles,
|
|
2363
|
+
allSessions,
|
|
2364
|
+
fileConflicts,
|
|
2365
|
+
branchOverlaps,
|
|
2366
|
+
isWorktree: reader.isWorktree
|
|
2367
|
+
});
|
|
2040
2368
|
if (!briefing) {
|
|
2041
2369
|
if (!opts.quiet) {
|
|
2042
2370
|
console.log("No session data available to generate a briefing.");
|
|
2043
2371
|
}
|
|
2044
2372
|
return;
|
|
2045
2373
|
}
|
|
2046
|
-
const decisions = reader.getScopedRecentDecisions(3);
|
|
2047
2374
|
if (opts.json) {
|
|
2048
|
-
|
|
2049
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2375
|
+
console.log(JSON.stringify(briefing, null, 2));
|
|
2050
2376
|
return;
|
|
2051
2377
|
}
|
|
2052
2378
|
if (opts.quiet) {
|
|
2053
|
-
|
|
2379
|
+
renderEnrichedBriefingQuiet(briefing);
|
|
2054
2380
|
return;
|
|
2055
2381
|
}
|
|
2056
|
-
|
|
2382
|
+
renderEnrichedBriefing(briefing);
|
|
2057
2383
|
}
|
|
2058
2384
|
|
|
2059
2385
|
// src/commands/init.ts
|
|
@@ -2065,11 +2391,9 @@ var CYAN2 = "\x1B[36m";
|
|
|
2065
2391
|
var DIM3 = "\x1B[2m";
|
|
2066
2392
|
function initCommand(options) {
|
|
2067
2393
|
const scope = options.scope === "user" ? "user" : "project";
|
|
2068
|
-
const hasProLicense = process.env.KEEPGOING_PRO_BYPASS === "1" || !!getLicenseForFeature("session-awareness");
|
|
2069
2394
|
const result = setupProject({
|
|
2070
2395
|
workspacePath: options.cwd,
|
|
2071
|
-
scope
|
|
2072
|
-
hasProLicense
|
|
2396
|
+
scope
|
|
2073
2397
|
});
|
|
2074
2398
|
console.log(`
|
|
2075
2399
|
${BOLD3}KeepGoing Init${RESET3} ${DIM3}(${scope} scope)${RESET3}
|
|
@@ -2415,6 +2739,83 @@ async function logCommand(opts) {
|
|
|
2415
2739
|
}
|
|
2416
2740
|
}
|
|
2417
2741
|
|
|
2742
|
+
// src/platform.ts
|
|
2743
|
+
import { execSync as execSync2, spawnSync } from "child_process";
|
|
2744
|
+
function copyToClipboard(text) {
|
|
2745
|
+
try {
|
|
2746
|
+
const platform = process.platform;
|
|
2747
|
+
if (platform === "darwin") {
|
|
2748
|
+
execSync2("pbcopy", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2749
|
+
} else if (platform === "win32") {
|
|
2750
|
+
execSync2("clip.exe", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2751
|
+
} else {
|
|
2752
|
+
try {
|
|
2753
|
+
execSync2("xclip -selection clipboard", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2754
|
+
} catch {
|
|
2755
|
+
execSync2("xsel --clipboard --input", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
return true;
|
|
2759
|
+
} catch {
|
|
2760
|
+
return false;
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
function openUrl(url) {
|
|
2764
|
+
try {
|
|
2765
|
+
const platform = process.platform;
|
|
2766
|
+
if (platform === "darwin") {
|
|
2767
|
+
spawnSync("open", [url], { stdio: "ignore" });
|
|
2768
|
+
} else if (platform === "win32") {
|
|
2769
|
+
spawnSync("cmd", ["/c", "start", "", url], { stdio: "ignore" });
|
|
2770
|
+
} else {
|
|
2771
|
+
spawnSync("xdg-open", [url], { stdio: "ignore" });
|
|
2772
|
+
}
|
|
2773
|
+
} catch {
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
// src/commands/continue.ts
|
|
2778
|
+
var TARGET_URLS = {
|
|
2779
|
+
chatgpt: "https://chat.openai.com",
|
|
2780
|
+
gemini: "https://gemini.google.com/app",
|
|
2781
|
+
copilot: "https://github.com/copilot",
|
|
2782
|
+
claude: "https://claude.ai/new"
|
|
2783
|
+
};
|
|
2784
|
+
async function continueCommand(opts) {
|
|
2785
|
+
const reader = new KeepGoingReader(opts.cwd);
|
|
2786
|
+
if (!reader.exists()) {
|
|
2787
|
+
if (!opts.quiet) {
|
|
2788
|
+
renderNoData();
|
|
2789
|
+
}
|
|
2790
|
+
return;
|
|
2791
|
+
}
|
|
2792
|
+
const context = gatherContinueOnContext(reader, opts.cwd);
|
|
2793
|
+
if (!context.lastCheckpoint && !context.briefing) {
|
|
2794
|
+
if (!opts.quiet) {
|
|
2795
|
+
console.log("No session data available. Save a checkpoint first.");
|
|
2796
|
+
}
|
|
2797
|
+
return;
|
|
2798
|
+
}
|
|
2799
|
+
const formatOpts = {};
|
|
2800
|
+
if (opts.target && opts.target in TARGET_URLS) {
|
|
2801
|
+
formatOpts.target = opts.target;
|
|
2802
|
+
}
|
|
2803
|
+
const prompt = formatContinueOnPrompt(context, formatOpts);
|
|
2804
|
+
if (opts.json) {
|
|
2805
|
+
console.log(JSON.stringify({ prompt, context }, null, 2));
|
|
2806
|
+
return;
|
|
2807
|
+
}
|
|
2808
|
+
const copied = copyToClipboard(prompt);
|
|
2809
|
+
if (opts.quiet) {
|
|
2810
|
+
renderContinueOnQuiet(copied, opts.target);
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
renderContinueOn(prompt, copied, opts.target);
|
|
2814
|
+
if (opts.open && opts.target && TARGET_URLS[opts.target]) {
|
|
2815
|
+
openUrl(TARGET_URLS[opts.target]);
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2418
2819
|
// src/index.ts
|
|
2419
2820
|
var HELP_TEXT = `
|
|
2420
2821
|
keepgoing: resume side projects without the mental friction
|
|
@@ -2428,6 +2829,7 @@ Commands:
|
|
|
2428
2829
|
briefing Get a re-entry briefing for this project
|
|
2429
2830
|
decisions View decision history (Pro)
|
|
2430
2831
|
log Browse session checkpoints
|
|
2832
|
+
continue Export context for use in another AI tool
|
|
2431
2833
|
save Save a checkpoint (auto-generates from git)
|
|
2432
2834
|
hook Manage the shell hook (zsh, bash, fish)
|
|
2433
2835
|
activate <key> Activate a Pro license on this device
|
|
@@ -2487,6 +2889,8 @@ keepgoing briefing: Get a re-entry briefing for this project
|
|
|
2487
2889
|
Usage: keepgoing briefing [options]
|
|
2488
2890
|
|
|
2489
2891
|
Options:
|
|
2892
|
+
--tier <tier> Detail level: compact, standard (default), detailed, full
|
|
2893
|
+
--model <name> Auto-resolve tier from model name (e.g. "claude-opus-4")
|
|
2490
2894
|
--json Output raw JSON
|
|
2491
2895
|
--quiet Suppress output
|
|
2492
2896
|
--cwd <path> Override the working directory
|
|
@@ -2582,6 +2986,23 @@ Example:
|
|
|
2582
2986
|
keepgoing deactivate: Deactivate the Pro license from this device
|
|
2583
2987
|
|
|
2584
2988
|
Usage: keepgoing deactivate [<key>]
|
|
2989
|
+
`,
|
|
2990
|
+
continue: `
|
|
2991
|
+
keepgoing continue: Export context for use in another AI tool
|
|
2992
|
+
|
|
2993
|
+
Usage: keepgoing continue [options]
|
|
2994
|
+
|
|
2995
|
+
Options:
|
|
2996
|
+
--target <tool> Target AI tool (chatgpt, gemini, copilot, claude, general)
|
|
2997
|
+
--open Auto-open the target tool's URL in your browser
|
|
2998
|
+
--json Output raw JSON (prompt + context)
|
|
2999
|
+
--quiet Suppress output (just copy to clipboard)
|
|
3000
|
+
--cwd <path> Override the working directory
|
|
3001
|
+
|
|
3002
|
+
Examples:
|
|
3003
|
+
keepgoing continue Copy context to clipboard
|
|
3004
|
+
keepgoing continue --target chatgpt --open Copy and open ChatGPT
|
|
3005
|
+
keepgoing continue --json Output as JSON
|
|
2585
3006
|
`
|
|
2586
3007
|
};
|
|
2587
3008
|
function parseArgs(argv) {
|
|
@@ -2611,6 +3032,10 @@ function parseArgs(argv) {
|
|
|
2611
3032
|
let today = false;
|
|
2612
3033
|
let week = false;
|
|
2613
3034
|
let sessions = false;
|
|
3035
|
+
let target = "";
|
|
3036
|
+
let open = false;
|
|
3037
|
+
let tier = "";
|
|
3038
|
+
let model = "";
|
|
2614
3039
|
for (let i = 0; i < args.length; i++) {
|
|
2615
3040
|
const arg = args[i];
|
|
2616
3041
|
if (arg === "--cwd" && i + 1 < args.length) {
|
|
@@ -2633,6 +3058,10 @@ function parseArgs(argv) {
|
|
|
2633
3058
|
branch = args[++i];
|
|
2634
3059
|
} else if (arg === "--limit" && i + 1 < args.length) {
|
|
2635
3060
|
limit = parseInt(args[++i], 10) || 10;
|
|
3061
|
+
} else if (arg === "--target" && i + 1 < args.length) {
|
|
3062
|
+
target = args[++i];
|
|
3063
|
+
} else if (arg === "--open") {
|
|
3064
|
+
open = true;
|
|
2636
3065
|
} else if (arg === "--json") {
|
|
2637
3066
|
json = true;
|
|
2638
3067
|
} else if (arg === "--quiet") {
|
|
@@ -2661,6 +3090,10 @@ function parseArgs(argv) {
|
|
|
2661
3090
|
week = true;
|
|
2662
3091
|
} else if (arg === "--sessions") {
|
|
2663
3092
|
sessions = true;
|
|
3093
|
+
} else if (arg === "--tier" && i + 1 < args.length) {
|
|
3094
|
+
tier = args[++i];
|
|
3095
|
+
} else if (arg === "--model" && i + 1 < args.length) {
|
|
3096
|
+
model = args[++i];
|
|
2664
3097
|
} else if (arg === "-v" || arg === "--version") {
|
|
2665
3098
|
command = "version";
|
|
2666
3099
|
} else if (arg === "-h" || arg === "--help") {
|
|
@@ -2697,7 +3130,11 @@ function parseArgs(argv) {
|
|
|
2697
3130
|
blockerOnly,
|
|
2698
3131
|
today,
|
|
2699
3132
|
week,
|
|
2700
|
-
sessions
|
|
3133
|
+
sessions,
|
|
3134
|
+
target,
|
|
3135
|
+
open,
|
|
3136
|
+
tier,
|
|
3137
|
+
model
|
|
2701
3138
|
};
|
|
2702
3139
|
}
|
|
2703
3140
|
async function main() {
|
|
@@ -2724,7 +3161,13 @@ async function main() {
|
|
|
2724
3161
|
await momentumCommand({ cwd, json, quiet });
|
|
2725
3162
|
break;
|
|
2726
3163
|
case "briefing":
|
|
2727
|
-
await briefingCommand({
|
|
3164
|
+
await briefingCommand({
|
|
3165
|
+
cwd,
|
|
3166
|
+
json,
|
|
3167
|
+
quiet,
|
|
3168
|
+
tier: parsed.tier || void 0,
|
|
3169
|
+
model: parsed.model || void 0
|
|
3170
|
+
});
|
|
2728
3171
|
break;
|
|
2729
3172
|
case "decisions":
|
|
2730
3173
|
await decisionsCommand({ cwd, json, quiet, branch, limit });
|
|
@@ -2750,6 +3193,9 @@ async function main() {
|
|
|
2750
3193
|
sessions: parsed.sessions
|
|
2751
3194
|
});
|
|
2752
3195
|
break;
|
|
3196
|
+
case "continue":
|
|
3197
|
+
await continueCommand({ cwd, json, quiet, target: parsed.target, open: parsed.open });
|
|
3198
|
+
break;
|
|
2753
3199
|
case "save":
|
|
2754
3200
|
await saveCommand({
|
|
2755
3201
|
cwd,
|
|
@@ -2770,7 +3216,7 @@ async function main() {
|
|
|
2770
3216
|
}
|
|
2771
3217
|
break;
|
|
2772
3218
|
case "version":
|
|
2773
|
-
console.log(`keepgoing v${"1.
|
|
3219
|
+
console.log(`keepgoing v${"1.1.1"}`);
|
|
2774
3220
|
break;
|
|
2775
3221
|
case "activate":
|
|
2776
3222
|
await activateCommand({ licenseKey: subcommand });
|