Skip to content

Commit 906df8f

Browse files
feat: Add process cleanup utility and API skill tests
- Add cleanup-processes CLI command to kill stale stackmemory processes - Finds processes older than 24h (configurable) with no log activity - Supports --dry-run, --all, --force, --max-age flags - Add comprehensive tests for API skill (18 tests) - Tests for add, list, describe, remove, help - Tests for API discovery (GitHub, Stripe, Railway, GCP) - Bump version to 0.5.5
1 parent 6093a10 commit 906df8f

6 files changed

Lines changed: 608 additions & 5 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stackmemoryai/stackmemory",
3-
"version": "0.5.4",
3+
"version": "0.5.5",
44
"description": "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention",
55
"engines": {
66
"node": ">=20.0.0",
@@ -10,7 +10,9 @@
1010
"main": "dist/index.js",
1111
"bin": {
1212
"stackmemory": "dist/cli/index.js",
13-
"codex-sm": "dist/cli/codex-sm.js"
13+
"codex-sm": "dist/cli/codex-sm.js",
14+
"claude-sm": "bin/claude-sm",
15+
"claude-smd": "bin/claude-smd"
1416
},
1517
"types": "dist/src/index.d.ts",
1618
"files": [
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* CLI Command for Process Cleanup
3+
*/
4+
5+
import { Command } from 'commander';
6+
import {
7+
cleanupStaleProcesses,
8+
findStaleProcesses,
9+
getStackmemoryProcesses,
10+
} from '../../utils/process-cleanup.js';
11+
12+
export function createCleanupProcessesCommand(): Command {
13+
const cmd = new Command('cleanup-processes');
14+
cmd.description('Clean up stale stackmemory processes');
15+
16+
cmd
17+
.option('--max-age <hours>', 'Max process age in hours (default: 24)', '24')
18+
.option('--dry-run', 'Show what would be killed without actually killing')
19+
.option('--all', 'Show all stackmemory processes (not just stale)')
20+
.option('--force', 'Kill without checking log activity')
21+
.action((options) => {
22+
const maxAgeHours = parseInt(options.maxAge, 10);
23+
24+
if (options.all) {
25+
// Just list all processes
26+
const processes = getStackmemoryProcesses();
27+
28+
if (processes.length === 0) {
29+
console.log('No stackmemory processes running');
30+
return;
31+
}
32+
33+
console.log(`Found ${processes.length} stackmemory process(es):\n`);
34+
for (const proc of processes) {
35+
const age =
36+
proc.ageHours < 1
37+
? `${Math.round(proc.ageHours * 60)}m`
38+
: `${Math.round(proc.ageHours)}h`;
39+
console.log(` PID ${proc.pid} (${age} old)`);
40+
console.log(` ${proc.command}`);
41+
}
42+
return;
43+
}
44+
45+
// Find and optionally kill stale processes
46+
const staleProcesses = options.force
47+
? getStackmemoryProcesses().filter((p) => p.ageHours >= maxAgeHours)
48+
: findStaleProcesses(maxAgeHours);
49+
50+
if (staleProcesses.length === 0) {
51+
console.log(`No stale processes older than ${maxAgeHours}h found`);
52+
return;
53+
}
54+
55+
console.log(
56+
`Found ${staleProcesses.length} stale process(es) older than ${maxAgeHours}h:\n`
57+
);
58+
59+
for (const proc of staleProcesses) {
60+
const age = `${Math.round(proc.ageHours)}h`;
61+
console.log(` PID ${proc.pid} (${age} old)`);
62+
console.log(` ${proc.command}`);
63+
if (proc.lastLogActivity) {
64+
console.log(` Last log: ${proc.lastLogActivity.toISOString()}`);
65+
}
66+
}
67+
68+
if (options.dryRun) {
69+
console.log('\n[DRY RUN] No processes killed');
70+
return;
71+
}
72+
73+
console.log('\nKilling stale processes...');
74+
const result = cleanupStaleProcesses({ maxAgeHours, dryRun: false });
75+
76+
console.log(`\nKilled: ${result.killed.length}`);
77+
if (result.errors.length > 0) {
78+
console.log(`Errors: ${result.errors.length}`);
79+
for (const err of result.errors) {
80+
console.log(` PID ${err.pid}: ${err.error}`);
81+
}
82+
}
83+
});
84+
85+
return cmd;
86+
}

src/cli/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { createSweepCommand } from './commands/sweep.js';
5252
import { createHooksCommand } from './commands/hooks.js';
5353
import { createShellCommand } from './commands/shell.js';
5454
import { createAPICommand } from './commands/api.js';
55+
import { createCleanupProcessesCommand } from './commands/cleanup-processes.js';
5556
import { ProjectManager } from '../core/projects/project-manager.js';
5657
import Database from 'better-sqlite3';
5758
import { join } from 'path';
@@ -64,7 +65,7 @@ import {
6465
getStorageModeDescription,
6566
} from '../core/config/storage-config.js';
6667

67-
const VERSION = '0.5.3';
68+
const VERSION = '0.5.5';
6869

6970
// Check for updates on CLI startup
7071
UpdateChecker.checkForUpdates(VERSION, true).catch(() => {
@@ -582,6 +583,7 @@ program.addCommand(createSweepCommand());
582583
program.addCommand(createHooksCommand());
583584
program.addCommand(createShellCommand());
584585
program.addCommand(createAPICommand());
586+
program.addCommand(createCleanupProcessesCommand());
585587

586588
// Register dashboard command
587589
program

0 commit comments

Comments
 (0)