@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 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
- import { z as z4 } from "zod";
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 = path7.join(workspacePath, ".claude");
2019
- const settingsPath = path7.join(claudeDir, "settings.json");
2055
+ const claudeDir = path8.join(workspacePath, ".claude");
2056
+ const settingsPath = path8.join(claudeDir, "settings.json");
2020
2057
  let settings = {};
2021
- if (fs5.existsSync(settingsPath)) {
2022
- settings = JSON.parse(fs5.readFileSync(settingsPath, "utf-8"));
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 statuslineSrc = path7.resolve(
2058
- new URL(".", import.meta.url).pathname,
2059
- "statusline.sh"
2060
- );
2061
- const claudeHome = path7.join(os2.homedir(), ".claude");
2062
- const statuslineDest = path7.join(claudeHome, "keepgoing-statusline.sh");
2063
- if (fs5.existsSync(statuslineSrc)) {
2064
- if (!fs5.existsSync(claudeHome)) {
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:** Script not found in package, skipped");
2103
+ results.push("**Statusline:** `statusLine` already configured in settings, skipped");
2081
2104
  }
2105
+ cleanupLegacyScript();
2082
2106
  }
2083
2107
  if (settingsChanged) {
2084
- if (!fs5.existsSync(claudeDir)) {
2085
- fs5.mkdirSync(claudeDir, { recursive: true });
2108
+ if (!fs6.existsSync(claudeDir)) {
2109
+ fs6.mkdirSync(claudeDir, { recursive: true });
2086
2110
  }
2087
- fs5.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
2111
+ fs6.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
2088
2112
  }
2089
2113
  if (claudeMd) {
2090
- const dotClaudeMdPath = path7.join(workspacePath, ".claude", "CLAUDE.md");
2091
- const rootClaudeMdPath = path7.join(workspacePath, "CLAUDE.md");
2092
- const claudeMdPath = fs5.existsSync(dotClaudeMdPath) ? dotClaudeMdPath : rootClaudeMdPath;
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 (fs5.existsSync(claudeMdPath)) {
2095
- existing = fs5.readFileSync(claudeMdPath, "utf-8");
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
- fs5.writeFileSync(claudeMdPath, updated);
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 path8 from "path";
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) => path8.basename(f)).join(", ")}`;
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 = path8.basename(resolveStorageRoot(wsPath));
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 cachedBranch = existing.find((t) => t.sessionActive && t.worktreePath === wsPath)?.branch;
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) {