@keepgoingdev/mcp-server 0.5.4 → 0.5.5
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/LICENSE +21 -0
- package/dist/index.js +127 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/statusline.sh +0 -51
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 KeepGoing.dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -1960,10 +1960,47 @@ function registerGetCurrentTask(server, reader) {
|
|
|
1960
1960
|
}
|
|
1961
1961
|
|
|
1962
1962
|
// src/tools/setupProject.ts
|
|
1963
|
+
import fs6 from "fs";
|
|
1964
|
+
import path8 from "path";
|
|
1965
|
+
import { z as z4 } from "zod";
|
|
1966
|
+
|
|
1967
|
+
// src/cli/migrate.ts
|
|
1963
1968
|
import fs5 from "fs";
|
|
1964
1969
|
import os2 from "os";
|
|
1965
1970
|
import path7 from "path";
|
|
1966
|
-
|
|
1971
|
+
var STATUSLINE_CMD = "npx -y @keepgoingdev/mcp-server --statusline";
|
|
1972
|
+
function isLegacyStatusline(command) {
|
|
1973
|
+
return !command.includes("--statusline") && command.includes("keepgoing-statusline");
|
|
1974
|
+
}
|
|
1975
|
+
function migrateStatusline(wsPath) {
|
|
1976
|
+
const settingsPath = path7.join(wsPath, ".claude", "settings.json");
|
|
1977
|
+
if (!fs5.existsSync(settingsPath)) return void 0;
|
|
1978
|
+
try {
|
|
1979
|
+
const settings = JSON.parse(fs5.readFileSync(settingsPath, "utf-8"));
|
|
1980
|
+
const cmd = settings.statusLine?.command;
|
|
1981
|
+
if (!cmd || !isLegacyStatusline(cmd)) return void 0;
|
|
1982
|
+
settings.statusLine = {
|
|
1983
|
+
type: "command",
|
|
1984
|
+
command: STATUSLINE_CMD
|
|
1985
|
+
};
|
|
1986
|
+
fs5.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1987
|
+
cleanupLegacyScript();
|
|
1988
|
+
return "[KeepGoing] Migrated statusline to auto-updating command (restart Claude Code to apply)";
|
|
1989
|
+
} catch {
|
|
1990
|
+
return void 0;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
function cleanupLegacyScript() {
|
|
1994
|
+
const legacyScript = path7.join(os2.homedir(), ".claude", "keepgoing-statusline.sh");
|
|
1995
|
+
if (fs5.existsSync(legacyScript)) {
|
|
1996
|
+
try {
|
|
1997
|
+
fs5.unlinkSync(legacyScript);
|
|
1998
|
+
} catch {
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
// src/tools/setupProject.ts
|
|
1967
2004
|
var KEEPGOING_MARKER = "@keepgoingdev/mcp-server";
|
|
1968
2005
|
var SESSION_START_HOOK = {
|
|
1969
2006
|
matcher: "",
|
|
@@ -2015,11 +2052,11 @@ function registerSetupProject(server, workspacePath) {
|
|
|
2015
2052
|
},
|
|
2016
2053
|
async ({ sessionHooks, claudeMd }) => {
|
|
2017
2054
|
const results = [];
|
|
2018
|
-
const claudeDir =
|
|
2019
|
-
const settingsPath =
|
|
2055
|
+
const claudeDir = path8.join(workspacePath, ".claude");
|
|
2056
|
+
const settingsPath = path8.join(claudeDir, "settings.json");
|
|
2020
2057
|
let settings = {};
|
|
2021
|
-
if (
|
|
2022
|
-
settings = JSON.parse(
|
|
2058
|
+
if (fs6.existsSync(settingsPath)) {
|
|
2059
|
+
settings = JSON.parse(fs6.readFileSync(settingsPath, "utf-8"));
|
|
2023
2060
|
}
|
|
2024
2061
|
let settingsChanged = false;
|
|
2025
2062
|
if (sessionHooks) {
|
|
@@ -2054,51 +2091,38 @@ function registerSetupProject(server, workspacePath) {
|
|
|
2054
2091
|
}
|
|
2055
2092
|
}
|
|
2056
2093
|
if (process.env.KEEPGOING_PRO_BYPASS === "1" || getLicenseForFeature("session-awareness")) {
|
|
2057
|
-
const
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
fs5.mkdirSync(claudeHome, { recursive: true });
|
|
2066
|
-
}
|
|
2067
|
-
fs5.copyFileSync(statuslineSrc, statuslineDest);
|
|
2068
|
-
fs5.chmodSync(statuslineDest, 493);
|
|
2069
|
-
if (!settings.statusLine) {
|
|
2070
|
-
settings.statusLine = {
|
|
2071
|
-
type: "command",
|
|
2072
|
-
command: statuslineDest
|
|
2073
|
-
};
|
|
2074
|
-
settingsChanged = true;
|
|
2075
|
-
results.push("**Statusline:** Installed `keepgoing-statusline.sh` and added to `.claude/settings.json`");
|
|
2076
|
-
} else {
|
|
2077
|
-
results.push("**Statusline:** `statusLine` already configured in settings, skipped");
|
|
2078
|
-
}
|
|
2094
|
+
const needsUpdate = settings.statusLine?.command && isLegacyStatusline(settings.statusLine.command);
|
|
2095
|
+
if (!settings.statusLine || needsUpdate) {
|
|
2096
|
+
settings.statusLine = {
|
|
2097
|
+
type: "command",
|
|
2098
|
+
command: STATUSLINE_CMD
|
|
2099
|
+
};
|
|
2100
|
+
settingsChanged = true;
|
|
2101
|
+
results.push(needsUpdate ? "**Statusline:** Migrated to auto-updating `npx` command" : "**Statusline:** Added to `.claude/settings.json`");
|
|
2079
2102
|
} else {
|
|
2080
|
-
results.push("**Statusline:**
|
|
2103
|
+
results.push("**Statusline:** `statusLine` already configured in settings, skipped");
|
|
2081
2104
|
}
|
|
2105
|
+
cleanupLegacyScript();
|
|
2082
2106
|
}
|
|
2083
2107
|
if (settingsChanged) {
|
|
2084
|
-
if (!
|
|
2085
|
-
|
|
2108
|
+
if (!fs6.existsSync(claudeDir)) {
|
|
2109
|
+
fs6.mkdirSync(claudeDir, { recursive: true });
|
|
2086
2110
|
}
|
|
2087
|
-
|
|
2111
|
+
fs6.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
2088
2112
|
}
|
|
2089
2113
|
if (claudeMd) {
|
|
2090
|
-
const dotClaudeMdPath =
|
|
2091
|
-
const rootClaudeMdPath =
|
|
2092
|
-
const claudeMdPath =
|
|
2114
|
+
const dotClaudeMdPath = path8.join(workspacePath, ".claude", "CLAUDE.md");
|
|
2115
|
+
const rootClaudeMdPath = path8.join(workspacePath, "CLAUDE.md");
|
|
2116
|
+
const claudeMdPath = fs6.existsSync(dotClaudeMdPath) ? dotClaudeMdPath : rootClaudeMdPath;
|
|
2093
2117
|
let existing = "";
|
|
2094
|
-
if (
|
|
2095
|
-
existing =
|
|
2118
|
+
if (fs6.existsSync(claudeMdPath)) {
|
|
2119
|
+
existing = fs6.readFileSync(claudeMdPath, "utf-8");
|
|
2096
2120
|
}
|
|
2097
2121
|
if (existing.includes("## KeepGoing")) {
|
|
2098
2122
|
results.push("**CLAUDE.md:** KeepGoing section already present, skipped");
|
|
2099
2123
|
} else {
|
|
2100
2124
|
const updated = existing + CLAUDE_MD_SECTION;
|
|
2101
|
-
|
|
2125
|
+
fs6.writeFileSync(claudeMdPath, updated);
|
|
2102
2126
|
results.push("**CLAUDE.md:** Added KeepGoing section");
|
|
2103
2127
|
}
|
|
2104
2128
|
}
|
|
@@ -2381,6 +2405,10 @@ async function handlePrintMomentum() {
|
|
|
2381
2405
|
lines.push(` Worked on ${touchedCount} files on ${lastSession.gitBranch ?? "unknown branch"}`);
|
|
2382
2406
|
}
|
|
2383
2407
|
lines.push(" Tip: Use the get_reentry_briefing tool for a full briefing");
|
|
2408
|
+
const migrationMsg = migrateStatusline(wsPath);
|
|
2409
|
+
if (migrationMsg) {
|
|
2410
|
+
lines.push(migrationMsg);
|
|
2411
|
+
}
|
|
2384
2412
|
console.log(lines.join("\n"));
|
|
2385
2413
|
process.exit(0);
|
|
2386
2414
|
}
|
|
@@ -2422,7 +2450,7 @@ async function handlePrintCurrent() {
|
|
|
2422
2450
|
}
|
|
2423
2451
|
|
|
2424
2452
|
// src/cli/saveCheckpoint.ts
|
|
2425
|
-
import
|
|
2453
|
+
import path9 from "path";
|
|
2426
2454
|
async function handleSaveCheckpoint() {
|
|
2427
2455
|
const wsPath = resolveWsPath();
|
|
2428
2456
|
const reader = new KeepGoingReader(wsPath);
|
|
@@ -2450,9 +2478,9 @@ async function handleSaveCheckpoint() {
|
|
|
2450
2478
|
sessionStartTime: lastSession?.timestamp ?? now,
|
|
2451
2479
|
lastActivityTime: now
|
|
2452
2480
|
});
|
|
2453
|
-
const summary = buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) =>
|
|
2481
|
+
const summary = buildSmartSummary(events) ?? `Worked on ${touchedFiles.slice(0, 5).map((f) => path9.basename(f)).join(", ")}`;
|
|
2454
2482
|
const nextStep = buildSmartNextStep(events);
|
|
2455
|
-
const projectName =
|
|
2483
|
+
const projectName = path9.basename(resolveStorageRoot(wsPath));
|
|
2456
2484
|
const sessionId = generateSessionId({ workspaceRoot: wsPath, branch: gitBranch ?? void 0, worktreePath: wsPath });
|
|
2457
2485
|
const checkpoint = createCheckpoint({
|
|
2458
2486
|
summary,
|
|
@@ -2543,7 +2571,8 @@ async function handleUpdateTaskFromHook() {
|
|
|
2543
2571
|
const fileName = filePath ? filePath.split("/").pop() ?? filePath : "";
|
|
2544
2572
|
const writer = new KeepGoingWriter(wsPath);
|
|
2545
2573
|
const existing = writer.readCurrentTasks();
|
|
2546
|
-
const
|
|
2574
|
+
const sessionIdFromHook = hookData.session_id;
|
|
2575
|
+
const cachedBranch = sessionIdFromHook ? existing.find((t) => t.sessionId === sessionIdFromHook)?.branch : void 0;
|
|
2547
2576
|
const branch = cachedBranch ?? getCurrentBranch(wsPath) ?? void 0;
|
|
2548
2577
|
const task = {
|
|
2549
2578
|
taskSummary: fileName ? `${toolName} ${fileName}` : `Used ${toolName}`,
|
|
@@ -2563,13 +2592,69 @@ async function handleUpdateTaskFromHook() {
|
|
|
2563
2592
|
process.stdin.resume();
|
|
2564
2593
|
}
|
|
2565
2594
|
|
|
2595
|
+
// src/cli/statusline.ts
|
|
2596
|
+
import fs7 from "fs";
|
|
2597
|
+
import path10 from "path";
|
|
2598
|
+
var STDIN_TIMEOUT_MS2 = 3e3;
|
|
2599
|
+
async function handleStatusline() {
|
|
2600
|
+
const chunks = [];
|
|
2601
|
+
const timeout = setTimeout(() => process.exit(0), STDIN_TIMEOUT_MS2);
|
|
2602
|
+
process.stdin.on("error", () => {
|
|
2603
|
+
clearTimeout(timeout);
|
|
2604
|
+
process.exit(0);
|
|
2605
|
+
});
|
|
2606
|
+
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
2607
|
+
process.stdin.on("end", () => {
|
|
2608
|
+
clearTimeout(timeout);
|
|
2609
|
+
try {
|
|
2610
|
+
const raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
2611
|
+
if (!raw) {
|
|
2612
|
+
process.exit(0);
|
|
2613
|
+
}
|
|
2614
|
+
const input = JSON.parse(raw);
|
|
2615
|
+
const dir = input.workspace?.current_dir ?? input.cwd;
|
|
2616
|
+
if (!dir) {
|
|
2617
|
+
process.exit(0);
|
|
2618
|
+
}
|
|
2619
|
+
const gitRoot = findGitRoot(dir);
|
|
2620
|
+
const tasksFile = path10.join(gitRoot, ".keepgoing", "current-tasks.json");
|
|
2621
|
+
if (!fs7.existsSync(tasksFile)) {
|
|
2622
|
+
process.exit(0);
|
|
2623
|
+
}
|
|
2624
|
+
const data = JSON.parse(fs7.readFileSync(tasksFile, "utf-8"));
|
|
2625
|
+
const branch = getCurrentBranch(gitRoot) ?? "";
|
|
2626
|
+
const active = pruneStaleTasks(data.tasks ?? []).filter((t) => t.sessionActive && t.branch === branch);
|
|
2627
|
+
if (active.length === 0) {
|
|
2628
|
+
process.exit(0);
|
|
2629
|
+
}
|
|
2630
|
+
active.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
|
|
2631
|
+
const task = active[active.length - 1];
|
|
2632
|
+
const summary = task.taskSummary;
|
|
2633
|
+
if (!summary) {
|
|
2634
|
+
process.exit(0);
|
|
2635
|
+
}
|
|
2636
|
+
if (branch) {
|
|
2637
|
+
process.stdout.write(`[KG] ${branch}: ${summary}
|
|
2638
|
+
`);
|
|
2639
|
+
} else {
|
|
2640
|
+
process.stdout.write(`[KG] ${summary}
|
|
2641
|
+
`);
|
|
2642
|
+
}
|
|
2643
|
+
} catch {
|
|
2644
|
+
}
|
|
2645
|
+
process.exit(0);
|
|
2646
|
+
});
|
|
2647
|
+
process.stdin.resume();
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2566
2650
|
// src/index.ts
|
|
2567
2651
|
var CLI_HANDLERS = {
|
|
2568
2652
|
"--print-momentum": handlePrintMomentum,
|
|
2569
2653
|
"--save-checkpoint": handleSaveCheckpoint,
|
|
2570
2654
|
"--update-task": handleUpdateTask,
|
|
2571
2655
|
"--update-task-from-hook": handleUpdateTaskFromHook,
|
|
2572
|
-
"--print-current": handlePrintCurrent
|
|
2656
|
+
"--print-current": handlePrintCurrent,
|
|
2657
|
+
"--statusline": handleStatusline
|
|
2573
2658
|
};
|
|
2574
2659
|
var flag = process.argv.slice(2).find((a) => a in CLI_HANDLERS);
|
|
2575
2660
|
if (flag) {
|