Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ codedb_remote repo="justrach/merjs" action="meta"
| `codedb serve` | HTTP daemon on :7719 |
| `codedb mcp [path]` | JSON-RPC/MCP server over stdio |
| `codedb update` | Self-update via install script |
| `codedb nuke` | Uninstall codedb, remove caches/snapshots, and deregister MCP integrations |
| `codedb --version` | Print version |

**Options:** `--no-telemetry` (or set `CODEDB_NO_TELEMETRY` env var)
Expand Down Expand Up @@ -365,8 +366,9 @@ To disable telemetry: set `CODEDB_NO_TELEMETRY=1` or pass `--no-telemetry`.
To sync the local NDJSON file into Postgres for analysis or dashboards, use [`scripts/sync-telemetry.py`](./scripts/sync-telemetry.py) with the schema in [`docs/telemetry/postgres-schema.sql`](./docs/telemetry/postgres-schema.sql). The data flow is documented in [`docs/telemetry.md`](./docs/telemetry.md).

```bash
rm -rf ~/.codedb/ # clear all cached indexes
rm -f codedb.snapshot # remove snapshot from project
codedb nuke # uninstall binary, clear caches/snapshots, remove MCP registrations
rm -rf ~/.codedb/ # cache-only cleanup if you want to keep the binary installed
rm -f codedb.snapshot # remove snapshot from current project only
```

---
Expand Down
89 changes: 3 additions & 86 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const index_mod = @import("index.zig");
const snapshot_mod = @import("snapshot.zig");
const telemetry = @import("telemetry.zig");
const root_policy = @import("root_policy.zig");
const nuke_mod = @import("nuke.zig");

/// Thin wrapper: format + write to a File via allocator.
const Out = struct {
Expand Down Expand Up @@ -156,91 +157,7 @@ fn mainImpl() !void {

// Handle nuke command early — before root resolution so it works from anywhere
if (std.mem.eql(u8, cmd, "nuke")) {
const home = std.process.getEnvVarOwned(allocator, "HOME") catch {
out.p("{s}\xe2\x9c\x97{s} cannot determine HOME directory\n", .{ s.red, s.reset });
std.process.exit(1);
};
defer allocator.free(home);

// Kill other running codedb processes (exclude ourselves)
const my_pid = std.Thread.getCurrentId();
var pid_buf: [32]u8 = undefined;
const my_pid_str = std.fmt.bufPrint(&pid_buf, "{d}", .{my_pid}) catch "0";

const pgrep_result = std.process.Child.run(.{
.allocator = allocator,
.argv = &.{ "pgrep", "-f", "codedb.*(serve|mcp)" },
.max_output_bytes = 4096,
}) catch null;
if (pgrep_result) |pr| {
defer allocator.free(pr.stdout);
defer allocator.free(pr.stderr);
var line_iter = std.mem.splitScalar(u8, pr.stdout, '\n');
while (line_iter.next()) |pid_line| {
const trimmed = std.mem.trim(u8, pid_line, " \t\r\n");
if (trimmed.len == 0) continue;
if (std.mem.eql(u8, trimmed, my_pid_str)) continue;
const kill_r = std.process.Child.run(.{
.allocator = allocator,
.argv = &.{ "kill", trimmed },
.max_output_bytes = 256,
}) catch null;
if (kill_r) |kr| {
allocator.free(kr.stdout);
allocator.free(kr.stderr);
}
}
}

// Remove ~/.codedb/
const codedb_dir = std.fmt.allocPrint(allocator, "{s}/.codedb", .{home}) catch {
std.process.exit(1);
};
defer allocator.free(codedb_dir);

// Read all project roots from ~/.codedb/projects/*/project.txt
// before deleting the data dir, so we can clean their snapshots
var snapshot_count: usize = 0;
const projects_dir = std.fmt.allocPrint(allocator, "{s}/.codedb/projects", .{home}) catch null;
if (projects_dir) |pd| {
defer allocator.free(pd);
var dir = std.fs.cwd().openDir(pd, .{ .iterate = true }) catch null;
if (dir) |*d| {
defer d.close();
var iter = d.iterate();
while (iter.next() catch null) |entry| {
if (entry.kind != .directory) continue;
// Read project.txt to get the project root path
const proj_file = std.fmt.allocPrint(allocator, "{s}/{s}/project.txt", .{ pd, entry.name }) catch continue;
defer allocator.free(proj_file);
const proj_root = std.fs.cwd().readFileAlloc(allocator, proj_file, 4096) catch continue;
defer allocator.free(proj_root);
const trimmed_root = std.mem.trim(u8, proj_root, " \t\r\n");
if (trimmed_root.len == 0) continue;
// Delete codedb.snapshot in that project root
const snap = std.fmt.allocPrint(allocator, "{s}/codedb.snapshot", .{trimmed_root}) catch continue;
defer allocator.free(snap);
std.fs.cwd().deleteFile(snap) catch continue;
snapshot_count += 1;
}
}
}

// Also try cwd snapshot (in case project wasn't registered)
std.fs.cwd().deleteFile("codedb.snapshot") catch {};

// Now remove ~/.codedb/
std.fs.cwd().deleteTree(codedb_dir) catch |err| {
if (err != error.FileNotFound) {
out.p("{s}\xe2\x9c\x97{s} failed to remove {s}: {}\n", .{ s.red, s.reset, codedb_dir, err });
}
};

out.p("{s}\xe2\x9c\x93{s} nuked all codedb data\n", .{ s.green, s.reset });
out.p(" removed {s}{s}{s}\n", .{ s.dim, codedb_dir, s.reset });
out.p(" removed {d} project snapshot(s)\n", .{snapshot_count});
out.p(" killed running codedb processes\n", .{});
out.p("\n to reinstall: {s}curl -fsSL https://codedb.codegraff.com/install.sh | bash{s}\n", .{ s.cyan, s.reset });
nuke_mod.run(stdout, s, allocator);
return;
}

Expand Down Expand Up @@ -818,7 +735,7 @@ fn printUsage(out: Out, s: sty.Style) void {
\\ {s}hot{s} recently modified files
\\ {s}serve{s} HTTP daemon on :7719
\\ {s}mcp{s} JSON-RPC/MCP server over stdio
\\ {s}nuke{s} remove all codedb data, snapshots, and kill processes
\\ {s}nuke{s} uninstall codedb, clear caches, and deregister integrations
\\
, .{
s.bold, s.reset,
Expand Down
Loading
Loading