@keepgoingdev/cli 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +524 -75
- 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
|
}
|
|
@@ -1281,7 +1506,7 @@ function setupProject(options) {
|
|
|
1281
1506
|
messages.push(`CLAUDE.md: KeepGoing section already present in ${mdLabel}, skipped`);
|
|
1282
1507
|
} else {
|
|
1283
1508
|
const updated = existing + CLAUDE_MD_SECTION;
|
|
1284
|
-
const mdDir =
|
|
1509
|
+
const mdDir = path7.dirname(claudeMdPath);
|
|
1285
1510
|
if (!fs5.existsSync(mdDir)) {
|
|
1286
1511
|
fs5.mkdirSync(mdDir, { recursive: true });
|
|
1287
1512
|
}
|
|
@@ -1430,29 +1655,6 @@ function renderNoData() {
|
|
|
1430
1655
|
`No KeepGoing data found. Run ${BOLD}keepgoing save${RESET} to save your first checkpoint.`
|
|
1431
1656
|
);
|
|
1432
1657
|
}
|
|
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
1658
|
function renderMomentum(checkpoint, ctx) {
|
|
1457
1659
|
const relTime = formatRelativeTime(checkpoint.timestamp);
|
|
1458
1660
|
const label = (s) => `${CYAN}${s}${RESET}`;
|
|
@@ -1602,18 +1804,130 @@ function renderSessionGroupHeader(sessionId, count) {
|
|
|
1602
1804
|
const shortId = sessionId.slice(0, 8);
|
|
1603
1805
|
console.log(`${BOLD}Session ${shortId}${RESET} ${DIM}(${count} checkpoint${count !== 1 ? "s" : ""})${RESET}`);
|
|
1604
1806
|
}
|
|
1807
|
+
function renderContinueOn(prompt, copied, target) {
|
|
1808
|
+
console.log(`
|
|
1809
|
+
${BOLD}KeepGoing Continue On${RESET}
|
|
1810
|
+
`);
|
|
1811
|
+
if (copied) {
|
|
1812
|
+
console.log(`${GREEN}\u2714 Context copied to clipboard${RESET}`);
|
|
1813
|
+
} else {
|
|
1814
|
+
console.log(`${YELLOW}\u26A0 Could not copy to clipboard. Prompt printed below.${RESET}`);
|
|
1815
|
+
}
|
|
1816
|
+
if (target) {
|
|
1817
|
+
console.log(`${DIM}Target: ${target}${RESET}`);
|
|
1818
|
+
}
|
|
1819
|
+
console.log("");
|
|
1820
|
+
console.log(`${DIM}--- prompt start ---${RESET}`);
|
|
1821
|
+
console.log(prompt);
|
|
1822
|
+
console.log(`${DIM}--- prompt end ---${RESET}`);
|
|
1823
|
+
console.log("");
|
|
1824
|
+
}
|
|
1825
|
+
function renderContinueOnQuiet(copied, target) {
|
|
1826
|
+
const targetStr = target ? ` (${target})` : "";
|
|
1827
|
+
if (copied) {
|
|
1828
|
+
console.log(`KeepGoing \xB7 Context copied to clipboard${targetStr}`);
|
|
1829
|
+
} else {
|
|
1830
|
+
console.log(`KeepGoing \xB7 Failed to copy context to clipboard${targetStr}`);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
function renderEnrichedBriefing(briefing) {
|
|
1834
|
+
const { tier, core } = briefing;
|
|
1835
|
+
const label = (s) => `${CYAN}${s}${RESET}`;
|
|
1836
|
+
console.log(`
|
|
1837
|
+
${BOLD}KeepGoing Re-entry Briefing${RESET} ${DIM}(${tier})${RESET}
|
|
1838
|
+
`);
|
|
1839
|
+
if (briefing.isWorktree && briefing.gitBranch) {
|
|
1840
|
+
console.log(` ${DIM}Worktree: scoped to ${briefing.gitBranch}${RESET}
|
|
1841
|
+
`);
|
|
1842
|
+
}
|
|
1843
|
+
if (tier === "compact") {
|
|
1844
|
+
console.log(` ${label("Last worked:")} ${core.lastWorked}`);
|
|
1845
|
+
console.log(` ${label("Focus:")} ${core.currentFocus}`);
|
|
1846
|
+
console.log(` ${label("Quick start:")} ${core.smallNextStep}`);
|
|
1847
|
+
console.log("");
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
console.log(` ${label("Last worked:")} ${core.lastWorked}`);
|
|
1851
|
+
console.log(` ${label("Focus:")} ${core.currentFocus}`);
|
|
1852
|
+
console.log(` ${label("Activity:")} ${core.recentActivity}`);
|
|
1853
|
+
console.log(` ${label("Next:")} ${core.suggestedNext}`);
|
|
1854
|
+
console.log(` ${label("Quick start:")} ${core.smallNextStep}`);
|
|
1855
|
+
if (briefing.blocker) {
|
|
1856
|
+
console.log(` ${label("Blocker:")} ${YELLOW}${briefing.blocker}${RESET}`);
|
|
1857
|
+
}
|
|
1858
|
+
if (briefing.decisions && briefing.decisions.length > 0) {
|
|
1859
|
+
console.log(`
|
|
1860
|
+
${label("Recent decisions:")}`);
|
|
1861
|
+
for (const d of briefing.decisions) {
|
|
1862
|
+
const relTime = formatRelativeTime(d.timestamp);
|
|
1863
|
+
console.log(` ${d.classification.category}: ${d.commitMessage} ${DIM}(${relTime})${RESET}`);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
if (briefing.touchedFiles && briefing.touchedFiles.length > 0) {
|
|
1867
|
+
console.log(`
|
|
1868
|
+
${label(`Files touched (${briefing.touchedFiles.length}):`)}`);
|
|
1869
|
+
const MAX_FILES = tier === "full" ? 20 : 10;
|
|
1870
|
+
const shown = briefing.touchedFiles.slice(0, MAX_FILES);
|
|
1871
|
+
for (const f of shown) {
|
|
1872
|
+
console.log(` ${DIM}${f}${RESET}`);
|
|
1873
|
+
}
|
|
1874
|
+
if (briefing.touchedFiles.length > MAX_FILES) {
|
|
1875
|
+
console.log(` ${DIM}...and ${briefing.touchedFiles.length - MAX_FILES} more${RESET}`);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
if (briefing.sessionHistory && briefing.sessionHistory.length > 0) {
|
|
1879
|
+
console.log(`
|
|
1880
|
+
${label("Session history:")}`);
|
|
1881
|
+
for (const s of briefing.sessionHistory) {
|
|
1882
|
+
const relTime = formatRelativeTime(s.timestamp);
|
|
1883
|
+
const branch = s.branch ? ` ${GREEN}(${s.branch})${RESET}` : "";
|
|
1884
|
+
console.log(` ${DIM}${relTime}${branch}${RESET} ${s.summary || "No summary"}`);
|
|
1885
|
+
if (s.nextStep) {
|
|
1886
|
+
console.log(` ${CYAN}\u2192${RESET} ${s.nextStep}`);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
if (briefing.recentCommits && briefing.recentCommits.length > 0) {
|
|
1891
|
+
console.log(`
|
|
1892
|
+
${label("Recent commits:")}`);
|
|
1893
|
+
for (const msg of briefing.recentCommits.slice(0, 10)) {
|
|
1894
|
+
console.log(` ${DIM}${msg}${RESET}`);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
if (briefing.fileConflicts && briefing.fileConflicts.length > 0) {
|
|
1898
|
+
console.log(`
|
|
1899
|
+
${YELLOW}File conflicts:${RESET}`);
|
|
1900
|
+
for (const c of briefing.fileConflicts) {
|
|
1901
|
+
const labels = c.sessions.map((s) => s.agentLabel || s.sessionId).join(", ");
|
|
1902
|
+
console.log(` ${c.file}: ${labels}`);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
if (briefing.branchOverlaps && briefing.branchOverlaps.length > 0) {
|
|
1906
|
+
console.log(`
|
|
1907
|
+
${YELLOW}Branch overlaps:${RESET}`);
|
|
1908
|
+
for (const o of briefing.branchOverlaps) {
|
|
1909
|
+
const labels = o.sessions.map((s) => s.agentLabel || s.sessionId).join(", ");
|
|
1910
|
+
console.log(` ${o.branch}: ${labels}`);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
console.log("");
|
|
1914
|
+
}
|
|
1915
|
+
function renderEnrichedBriefingQuiet(briefing) {
|
|
1916
|
+
const { core } = briefing;
|
|
1917
|
+
console.log(`KeepGoing \xB7 ${core.lastWorked} \xB7 Focus: ${core.currentFocus} \xB7 Next: ${core.smallNextStep}`);
|
|
1918
|
+
}
|
|
1605
1919
|
|
|
1606
1920
|
// src/updateCheck.ts
|
|
1607
1921
|
import { spawn } from "child_process";
|
|
1608
1922
|
import { readFileSync, existsSync } from "fs";
|
|
1609
|
-
import
|
|
1923
|
+
import path8 from "path";
|
|
1610
1924
|
import os3 from "os";
|
|
1611
|
-
var CLI_VERSION = "1.
|
|
1925
|
+
var CLI_VERSION = "1.1.0";
|
|
1612
1926
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
|
|
1613
1927
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
1614
1928
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
1615
|
-
var CACHE_DIR =
|
|
1616
|
-
var CACHE_PATH =
|
|
1929
|
+
var CACHE_DIR = path8.join(os3.homedir(), ".keepgoing");
|
|
1930
|
+
var CACHE_PATH = path8.join(CACHE_DIR, "update-check.json");
|
|
1617
1931
|
function isNewerVersion(current, latest) {
|
|
1618
1932
|
const cur = current.split(".").map(Number);
|
|
1619
1933
|
const lat = latest.split(".").map(Number);
|
|
@@ -1728,7 +2042,7 @@ async function statusCommand(opts) {
|
|
|
1728
2042
|
}
|
|
1729
2043
|
|
|
1730
2044
|
// src/commands/save.ts
|
|
1731
|
-
import
|
|
2045
|
+
import path9 from "path";
|
|
1732
2046
|
async function saveCommand(opts) {
|
|
1733
2047
|
const { cwd, message, nextStepOverride, json, quiet, force } = opts;
|
|
1734
2048
|
const isManual = !!message;
|
|
@@ -1757,9 +2071,9 @@ async function saveCommand(opts) {
|
|
|
1757
2071
|
sessionStartTime: lastSession?.timestamp ?? now,
|
|
1758
2072
|
lastActivityTime: now
|
|
1759
2073
|
});
|
|
1760
|
-
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) =>
|
|
2074
|
+
const summary = message ?? buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) => path9.basename(f)).join(", ")}`;
|
|
1761
2075
|
const nextStep = nextStepOverride ?? buildSmartNextStep(events);
|
|
1762
|
-
const projectName =
|
|
2076
|
+
const projectName = path9.basename(resolveStorageRoot(cwd));
|
|
1763
2077
|
const sessionId = generateSessionId({
|
|
1764
2078
|
workspaceRoot: cwd,
|
|
1765
2079
|
branch: gitBranch ?? void 0,
|
|
@@ -1793,7 +2107,7 @@ async function saveCommand(opts) {
|
|
|
1793
2107
|
|
|
1794
2108
|
// src/commands/hook.ts
|
|
1795
2109
|
import fs6 from "fs";
|
|
1796
|
-
import
|
|
2110
|
+
import path10 from "path";
|
|
1797
2111
|
import os4 from "os";
|
|
1798
2112
|
import { execSync } from "child_process";
|
|
1799
2113
|
var HOOK_MARKER_START = "# keepgoing-hook-start";
|
|
@@ -1853,14 +2167,14 @@ function detectShellRcFile(shellOverride) {
|
|
|
1853
2167
|
}
|
|
1854
2168
|
}
|
|
1855
2169
|
if (shell === "zsh") {
|
|
1856
|
-
return { shell: "zsh", rcFile:
|
|
2170
|
+
return { shell: "zsh", rcFile: path10.join(home, ".zshrc") };
|
|
1857
2171
|
}
|
|
1858
2172
|
if (shell === "bash") {
|
|
1859
|
-
return { shell: "bash", rcFile:
|
|
2173
|
+
return { shell: "bash", rcFile: path10.join(home, ".bashrc") };
|
|
1860
2174
|
}
|
|
1861
2175
|
if (shell === "fish") {
|
|
1862
|
-
const xdgConfig = process.env["XDG_CONFIG_HOME"] ||
|
|
1863
|
-
return { shell: "fish", rcFile:
|
|
2176
|
+
const xdgConfig = process.env["XDG_CONFIG_HOME"] || path10.join(home, ".config");
|
|
2177
|
+
return { shell: "fish", rcFile: path10.join(xdgConfig, "fish", "config.fish") };
|
|
1864
2178
|
}
|
|
1865
2179
|
return void 0;
|
|
1866
2180
|
}
|
|
@@ -2030,30 +2344,43 @@ async function briefingCommand(opts) {
|
|
|
2030
2344
|
const state = reader.getState() ?? {};
|
|
2031
2345
|
const sinceTimestamp = lastSession?.timestamp;
|
|
2032
2346
|
const recentCommits = sinceTimestamp ? getCommitMessagesSince(opts.cwd, sinceTimestamp) : [];
|
|
2033
|
-
const
|
|
2347
|
+
const decisions = reader.getScopedRecentDecisions(10);
|
|
2348
|
+
const allSessions = reader.getSessions();
|
|
2349
|
+
const fileConflicts = reader.detectFileConflicts();
|
|
2350
|
+
const branchOverlaps = reader.detectBranchOverlap();
|
|
2351
|
+
const effectiveTier = opts.quiet ? "compact" : opts.tier;
|
|
2352
|
+
const validTiers = ["compact", "standard", "detailed", "full"];
|
|
2353
|
+
const tier = effectiveTier && validTiers.includes(effectiveTier) ? effectiveTier : void 0;
|
|
2354
|
+
const briefing = generateEnrichedBriefing({
|
|
2355
|
+
tier,
|
|
2356
|
+
model: opts.model,
|
|
2034
2357
|
lastSession,
|
|
2035
2358
|
recentSessions,
|
|
2036
|
-
state,
|
|
2359
|
+
projectState: state,
|
|
2037
2360
|
gitBranch,
|
|
2038
|
-
recentCommits
|
|
2039
|
-
|
|
2361
|
+
recentCommits,
|
|
2362
|
+
decisions,
|
|
2363
|
+
allTouchedFiles: lastSession?.touchedFiles,
|
|
2364
|
+
allSessions,
|
|
2365
|
+
fileConflicts,
|
|
2366
|
+
branchOverlaps,
|
|
2367
|
+
isWorktree: reader.isWorktree
|
|
2368
|
+
});
|
|
2040
2369
|
if (!briefing) {
|
|
2041
2370
|
if (!opts.quiet) {
|
|
2042
2371
|
console.log("No session data available to generate a briefing.");
|
|
2043
2372
|
}
|
|
2044
2373
|
return;
|
|
2045
2374
|
}
|
|
2046
|
-
const decisions = reader.getScopedRecentDecisions(3);
|
|
2047
2375
|
if (opts.json) {
|
|
2048
|
-
|
|
2049
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2376
|
+
console.log(JSON.stringify(briefing, null, 2));
|
|
2050
2377
|
return;
|
|
2051
2378
|
}
|
|
2052
2379
|
if (opts.quiet) {
|
|
2053
|
-
|
|
2380
|
+
renderEnrichedBriefingQuiet(briefing);
|
|
2054
2381
|
return;
|
|
2055
2382
|
}
|
|
2056
|
-
|
|
2383
|
+
renderEnrichedBriefing(briefing);
|
|
2057
2384
|
}
|
|
2058
2385
|
|
|
2059
2386
|
// src/commands/init.ts
|
|
@@ -2415,6 +2742,83 @@ async function logCommand(opts) {
|
|
|
2415
2742
|
}
|
|
2416
2743
|
}
|
|
2417
2744
|
|
|
2745
|
+
// src/platform.ts
|
|
2746
|
+
import { execSync as execSync2, spawnSync } from "child_process";
|
|
2747
|
+
function copyToClipboard(text) {
|
|
2748
|
+
try {
|
|
2749
|
+
const platform = process.platform;
|
|
2750
|
+
if (platform === "darwin") {
|
|
2751
|
+
execSync2("pbcopy", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2752
|
+
} else if (platform === "win32") {
|
|
2753
|
+
execSync2("clip.exe", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2754
|
+
} else {
|
|
2755
|
+
try {
|
|
2756
|
+
execSync2("xclip -selection clipboard", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2757
|
+
} catch {
|
|
2758
|
+
execSync2("xsel --clipboard --input", { input: text, stdio: ["pipe", "ignore", "ignore"] });
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
return true;
|
|
2762
|
+
} catch {
|
|
2763
|
+
return false;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
function openUrl(url) {
|
|
2767
|
+
try {
|
|
2768
|
+
const platform = process.platform;
|
|
2769
|
+
if (platform === "darwin") {
|
|
2770
|
+
spawnSync("open", [url], { stdio: "ignore" });
|
|
2771
|
+
} else if (platform === "win32") {
|
|
2772
|
+
spawnSync("cmd", ["/c", "start", "", url], { stdio: "ignore" });
|
|
2773
|
+
} else {
|
|
2774
|
+
spawnSync("xdg-open", [url], { stdio: "ignore" });
|
|
2775
|
+
}
|
|
2776
|
+
} catch {
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
// src/commands/continue.ts
|
|
2781
|
+
var TARGET_URLS = {
|
|
2782
|
+
chatgpt: "https://chat.openai.com",
|
|
2783
|
+
gemini: "https://gemini.google.com/app",
|
|
2784
|
+
copilot: "https://github.com/copilot",
|
|
2785
|
+
claude: "https://claude.ai/new"
|
|
2786
|
+
};
|
|
2787
|
+
async function continueCommand(opts) {
|
|
2788
|
+
const reader = new KeepGoingReader(opts.cwd);
|
|
2789
|
+
if (!reader.exists()) {
|
|
2790
|
+
if (!opts.quiet) {
|
|
2791
|
+
renderNoData();
|
|
2792
|
+
}
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
const context = gatherContinueOnContext(reader, opts.cwd);
|
|
2796
|
+
if (!context.lastCheckpoint && !context.briefing) {
|
|
2797
|
+
if (!opts.quiet) {
|
|
2798
|
+
console.log("No session data available. Save a checkpoint first.");
|
|
2799
|
+
}
|
|
2800
|
+
return;
|
|
2801
|
+
}
|
|
2802
|
+
const formatOpts = {};
|
|
2803
|
+
if (opts.target && opts.target in TARGET_URLS) {
|
|
2804
|
+
formatOpts.target = opts.target;
|
|
2805
|
+
}
|
|
2806
|
+
const prompt = formatContinueOnPrompt(context, formatOpts);
|
|
2807
|
+
if (opts.json) {
|
|
2808
|
+
console.log(JSON.stringify({ prompt, context }, null, 2));
|
|
2809
|
+
return;
|
|
2810
|
+
}
|
|
2811
|
+
const copied = copyToClipboard(prompt);
|
|
2812
|
+
if (opts.quiet) {
|
|
2813
|
+
renderContinueOnQuiet(copied, opts.target);
|
|
2814
|
+
return;
|
|
2815
|
+
}
|
|
2816
|
+
renderContinueOn(prompt, copied, opts.target);
|
|
2817
|
+
if (opts.open && opts.target && TARGET_URLS[opts.target]) {
|
|
2818
|
+
openUrl(TARGET_URLS[opts.target]);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2418
2822
|
// src/index.ts
|
|
2419
2823
|
var HELP_TEXT = `
|
|
2420
2824
|
keepgoing: resume side projects without the mental friction
|
|
@@ -2428,6 +2832,7 @@ Commands:
|
|
|
2428
2832
|
briefing Get a re-entry briefing for this project
|
|
2429
2833
|
decisions View decision history (Pro)
|
|
2430
2834
|
log Browse session checkpoints
|
|
2835
|
+
continue Export context for use in another AI tool
|
|
2431
2836
|
save Save a checkpoint (auto-generates from git)
|
|
2432
2837
|
hook Manage the shell hook (zsh, bash, fish)
|
|
2433
2838
|
activate <key> Activate a Pro license on this device
|
|
@@ -2487,6 +2892,8 @@ keepgoing briefing: Get a re-entry briefing for this project
|
|
|
2487
2892
|
Usage: keepgoing briefing [options]
|
|
2488
2893
|
|
|
2489
2894
|
Options:
|
|
2895
|
+
--tier <tier> Detail level: compact, standard (default), detailed, full
|
|
2896
|
+
--model <name> Auto-resolve tier from model name (e.g. "claude-opus-4")
|
|
2490
2897
|
--json Output raw JSON
|
|
2491
2898
|
--quiet Suppress output
|
|
2492
2899
|
--cwd <path> Override the working directory
|
|
@@ -2582,6 +2989,23 @@ Example:
|
|
|
2582
2989
|
keepgoing deactivate: Deactivate the Pro license from this device
|
|
2583
2990
|
|
|
2584
2991
|
Usage: keepgoing deactivate [<key>]
|
|
2992
|
+
`,
|
|
2993
|
+
continue: `
|
|
2994
|
+
keepgoing continue: Export context for use in another AI tool
|
|
2995
|
+
|
|
2996
|
+
Usage: keepgoing continue [options]
|
|
2997
|
+
|
|
2998
|
+
Options:
|
|
2999
|
+
--target <tool> Target AI tool (chatgpt, gemini, copilot, claude, general)
|
|
3000
|
+
--open Auto-open the target tool's URL in your browser
|
|
3001
|
+
--json Output raw JSON (prompt + context)
|
|
3002
|
+
--quiet Suppress output (just copy to clipboard)
|
|
3003
|
+
--cwd <path> Override the working directory
|
|
3004
|
+
|
|
3005
|
+
Examples:
|
|
3006
|
+
keepgoing continue Copy context to clipboard
|
|
3007
|
+
keepgoing continue --target chatgpt --open Copy and open ChatGPT
|
|
3008
|
+
keepgoing continue --json Output as JSON
|
|
2585
3009
|
`
|
|
2586
3010
|
};
|
|
2587
3011
|
function parseArgs(argv) {
|
|
@@ -2611,6 +3035,10 @@ function parseArgs(argv) {
|
|
|
2611
3035
|
let today = false;
|
|
2612
3036
|
let week = false;
|
|
2613
3037
|
let sessions = false;
|
|
3038
|
+
let target = "";
|
|
3039
|
+
let open = false;
|
|
3040
|
+
let tier = "";
|
|
3041
|
+
let model = "";
|
|
2614
3042
|
for (let i = 0; i < args.length; i++) {
|
|
2615
3043
|
const arg = args[i];
|
|
2616
3044
|
if (arg === "--cwd" && i + 1 < args.length) {
|
|
@@ -2633,6 +3061,10 @@ function parseArgs(argv) {
|
|
|
2633
3061
|
branch = args[++i];
|
|
2634
3062
|
} else if (arg === "--limit" && i + 1 < args.length) {
|
|
2635
3063
|
limit = parseInt(args[++i], 10) || 10;
|
|
3064
|
+
} else if (arg === "--target" && i + 1 < args.length) {
|
|
3065
|
+
target = args[++i];
|
|
3066
|
+
} else if (arg === "--open") {
|
|
3067
|
+
open = true;
|
|
2636
3068
|
} else if (arg === "--json") {
|
|
2637
3069
|
json = true;
|
|
2638
3070
|
} else if (arg === "--quiet") {
|
|
@@ -2661,6 +3093,10 @@ function parseArgs(argv) {
|
|
|
2661
3093
|
week = true;
|
|
2662
3094
|
} else if (arg === "--sessions") {
|
|
2663
3095
|
sessions = true;
|
|
3096
|
+
} else if (arg === "--tier" && i + 1 < args.length) {
|
|
3097
|
+
tier = args[++i];
|
|
3098
|
+
} else if (arg === "--model" && i + 1 < args.length) {
|
|
3099
|
+
model = args[++i];
|
|
2664
3100
|
} else if (arg === "-v" || arg === "--version") {
|
|
2665
3101
|
command = "version";
|
|
2666
3102
|
} else if (arg === "-h" || arg === "--help") {
|
|
@@ -2697,7 +3133,11 @@ function parseArgs(argv) {
|
|
|
2697
3133
|
blockerOnly,
|
|
2698
3134
|
today,
|
|
2699
3135
|
week,
|
|
2700
|
-
sessions
|
|
3136
|
+
sessions,
|
|
3137
|
+
target,
|
|
3138
|
+
open,
|
|
3139
|
+
tier,
|
|
3140
|
+
model
|
|
2701
3141
|
};
|
|
2702
3142
|
}
|
|
2703
3143
|
async function main() {
|
|
@@ -2724,7 +3164,13 @@ async function main() {
|
|
|
2724
3164
|
await momentumCommand({ cwd, json, quiet });
|
|
2725
3165
|
break;
|
|
2726
3166
|
case "briefing":
|
|
2727
|
-
await briefingCommand({
|
|
3167
|
+
await briefingCommand({
|
|
3168
|
+
cwd,
|
|
3169
|
+
json,
|
|
3170
|
+
quiet,
|
|
3171
|
+
tier: parsed.tier || void 0,
|
|
3172
|
+
model: parsed.model || void 0
|
|
3173
|
+
});
|
|
2728
3174
|
break;
|
|
2729
3175
|
case "decisions":
|
|
2730
3176
|
await decisionsCommand({ cwd, json, quiet, branch, limit });
|
|
@@ -2750,6 +3196,9 @@ async function main() {
|
|
|
2750
3196
|
sessions: parsed.sessions
|
|
2751
3197
|
});
|
|
2752
3198
|
break;
|
|
3199
|
+
case "continue":
|
|
3200
|
+
await continueCommand({ cwd, json, quiet, target: parsed.target, open: parsed.open });
|
|
3201
|
+
break;
|
|
2753
3202
|
case "save":
|
|
2754
3203
|
await saveCommand({
|
|
2755
3204
|
cwd,
|
|
@@ -2770,7 +3219,7 @@ async function main() {
|
|
|
2770
3219
|
}
|
|
2771
3220
|
break;
|
|
2772
3221
|
case "version":
|
|
2773
|
-
console.log(`keepgoing v${"1.
|
|
3222
|
+
console.log(`keepgoing v${"1.1.0"}`);
|
|
2774
3223
|
break;
|
|
2775
3224
|
case "activate":
|
|
2776
3225
|
await activateCommand({ licenseKey: subcommand });
|