@stackmemoryai/stackmemory
Version:
Lossless, project-scoped memory for AI coding tools. Durable context across sessions with 56 MCP tools, FTS5 search, conductor orchestrator, loop/watch monitoring, snapshot capture, pre-flight overlap checks, Claude/Codex/OpenCode wrappers, Linear sync, a
90 lines (89 loc) • 3.49 kB
JavaScript
import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { Command } from "commander";
import chalk from "chalk";
import { ContextCapture } from "../../core/worktree/capture.js";
function createSnapshotCommand() {
const cmd = new Command("snapshot").alias("snap").description("Point-in-time snapshot of work (what changed and why)");
cmd.command("save").alias("s").description("Save a snapshot of current branch state").option("-t, --task <name>", "Task name or description").option(
"-b, --base <branch>",
"Base branch to diff against (default: auto-detect)"
).option(
"-d, --decision <decisions...>",
"Key decisions made during this task"
).option("--json", "Output as JSON").action((options) => {
const capture = new ContextCapture();
const result = capture.capture({
task: options.task,
baseBranch: options.base,
decisions: options.decision
});
if (options.json) {
console.log(JSON.stringify(result, null, 2));
return;
}
console.log(chalk.green("\nSnapshot saved.\n"));
console.log(chalk.gray(` Branch: ${result.branch}`));
console.log(chalk.gray(` Base: ${result.baseBranch}`));
console.log(chalk.gray(` Changed: ${result.filesChanged.length} files`));
console.log(chalk.gray(` Created: ${result.filesCreated.length} files`));
console.log(chalk.gray(` Deleted: ${result.filesDeleted.length} files`));
console.log(chalk.gray(` Commits: ${result.commits.length}`));
if (result.decisions.length > 0) {
console.log(chalk.cyan("\n Decisions:"));
result.decisions.forEach((d) => console.log(chalk.gray(` - ${d}`)));
}
if (result.duration) {
console.log(chalk.gray(` Duration: ${result.duration}`));
}
console.log(chalk.gray(`
Saved: ${result.id}`));
});
cmd.command("list").alias("ls").description("List recent snapshots").option("-n, --limit <n>", "Number of captures to show", "10").option("--json", "Output as JSON").action((options) => {
const capture = new ContextCapture();
const captures = capture.list(parseInt(options.limit));
if (captures.length === 0) {
console.log(chalk.yellow("No snapshots found."));
return;
}
if (options.json) {
console.log(JSON.stringify(captures, null, 2));
return;
}
console.log(chalk.cyan(`
Recent Snapshots (${captures.length}):
`));
for (const cap of captures) {
const date = new Date(cap.timestamp).toLocaleDateString();
const files = cap.filesChanged.length + cap.filesCreated.length;
console.log(
chalk.gray(
` ${date} ${cap.branch.padEnd(30)} ${files} files ${cap.commits.length} commits`
)
);
}
});
cmd.command("show [branch]").description("Show snapshot details (latest or by branch)").option("--json", "Output as JSON").action((branch, options) => {
const capturer = new ContextCapture();
const result = capturer.getLatest(branch);
if (!result) {
console.log(
chalk.yellow(
branch ? `No snapshot found for branch: ${branch}` : "No snapshots found."
)
);
return;
}
if (options.json) {
console.log(JSON.stringify(result, null, 2));
return;
}
console.log(capturer.format(result));
});
return cmd;
}
export {
createSnapshotCommand
};