@ulpi/codemap 0.3.7 → 0.3.8
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/dist/index.js +267 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import "./chunk-WR342MP3.js";
|
|
|
5
5
|
import "./chunk-2OBAJYRP.js";
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
-
import
|
|
8
|
+
import path14 from "path";
|
|
9
9
|
import { fileURLToPath } from "url";
|
|
10
10
|
|
|
11
11
|
// ../../packages/intelligence/codemap-engine/dist/index.js
|
|
@@ -4250,6 +4250,19 @@ function releaseCodemapLock(projectDir, branch) {
|
|
|
4250
4250
|
} catch {
|
|
4251
4251
|
}
|
|
4252
4252
|
}
|
|
4253
|
+
function isCodemapLocked(projectDir, branch) {
|
|
4254
|
+
const file = lockPath(projectDir, branch);
|
|
4255
|
+
const info = readLock(file);
|
|
4256
|
+
if (!info) return false;
|
|
4257
|
+
if (isStale(info)) {
|
|
4258
|
+
try {
|
|
4259
|
+
fs6.unlinkSync(file);
|
|
4260
|
+
} catch {
|
|
4261
|
+
}
|
|
4262
|
+
return false;
|
|
4263
|
+
}
|
|
4264
|
+
return true;
|
|
4265
|
+
}
|
|
4253
4266
|
function saveManifest(branchDir, manifest) {
|
|
4254
4267
|
fs7.mkdirSync(branchDir, { recursive: true });
|
|
4255
4268
|
const file = path7.join(branchDir, "manifest.json");
|
|
@@ -6164,13 +6177,14 @@ function registerStatus(program2) {
|
|
|
6164
6177
|
const projectDir = program2.opts().cwd || process.cwd();
|
|
6165
6178
|
const branch = getCurrentBranch(projectDir);
|
|
6166
6179
|
const statsFile = codemapStatsFile(projectDir, branch, getDataDir2());
|
|
6180
|
+
const indexing = isCodemapLocked(projectDir, branch);
|
|
6167
6181
|
let stats = null;
|
|
6168
6182
|
try {
|
|
6169
6183
|
stats = JSON.parse(fs14.readFileSync(statsFile, "utf-8"));
|
|
6170
6184
|
} catch {
|
|
6171
6185
|
}
|
|
6172
6186
|
if (opts.json) {
|
|
6173
|
-
console.log(JSON.stringify({ projectDir, branch, stats }, null, 2));
|
|
6187
|
+
console.log(JSON.stringify({ projectDir, branch, stats, indexing }, null, 2));
|
|
6174
6188
|
return;
|
|
6175
6189
|
}
|
|
6176
6190
|
console.log(chalk6.bold("Codemap Status"));
|
|
@@ -6179,6 +6193,10 @@ function registerStatus(program2) {
|
|
|
6179
6193
|
console.log(`Branch: ${branch}`);
|
|
6180
6194
|
console.log(`Data dir: ${getDataDir2()}`);
|
|
6181
6195
|
console.log();
|
|
6196
|
+
if (indexing) {
|
|
6197
|
+
console.log(chalk6.yellow("Indexing in progress..."));
|
|
6198
|
+
console.log();
|
|
6199
|
+
}
|
|
6182
6200
|
if (!stats) {
|
|
6183
6201
|
console.log(chalk6.yellow("No index found. Run `codemap index` first."));
|
|
6184
6202
|
return;
|
|
@@ -6869,13 +6887,10 @@ function registerCoupling(program2) {
|
|
|
6869
6887
|
const projectDir = program2.opts().cwd || process.cwd();
|
|
6870
6888
|
const branch = getCurrentBranch(projectDir);
|
|
6871
6889
|
const graphFile = depgraphGraphFile(projectDir, branch, getDataDir2());
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
graph = loadGraph(graphFile);
|
|
6875
|
-
} catch {
|
|
6890
|
+
const graph = loadGraph(graphFile);
|
|
6891
|
+
if (!graph) {
|
|
6876
6892
|
console.error(chalk14.red("Dependency graph not available. Run `codemap index` first."));
|
|
6877
6893
|
process.exit(1);
|
|
6878
|
-
return;
|
|
6879
6894
|
}
|
|
6880
6895
|
let coupling = computeCoupling(graph);
|
|
6881
6896
|
if (opts.module) {
|
|
@@ -6914,13 +6929,10 @@ function registerGraphStats(program2) {
|
|
|
6914
6929
|
program2.command("graph-stats").description("Show aggregate dependency graph statistics").option("--json", "Output as JSON").action(async (opts) => {
|
|
6915
6930
|
const projectDir = program2.opts().cwd || process.cwd();
|
|
6916
6931
|
const branch = getCurrentBranch(projectDir);
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
metrics = loadMetrics(depgraphMetricsFile(projectDir, branch, getDataDir2()));
|
|
6920
|
-
} catch {
|
|
6932
|
+
const metrics = loadMetrics(depgraphMetricsFile(projectDir, branch, getDataDir2()));
|
|
6933
|
+
if (!metrics) {
|
|
6921
6934
|
console.error(chalk15.red("Dependency metrics not available. Run `codemap index` first."));
|
|
6922
6935
|
process.exit(1);
|
|
6923
|
-
return;
|
|
6924
6936
|
}
|
|
6925
6937
|
const result = {
|
|
6926
6938
|
totalFiles: metrics.totalFiles,
|
|
@@ -7010,9 +7022,249 @@ function registerRebuild(program2) {
|
|
|
7010
7022
|
});
|
|
7011
7023
|
}
|
|
7012
7024
|
|
|
7025
|
+
// src/commands/statusline.ts
|
|
7026
|
+
import chalk17 from "chalk";
|
|
7027
|
+
import fs18 from "fs";
|
|
7028
|
+
import path13 from "path";
|
|
7029
|
+
import { homedir as homedir3 } from "os";
|
|
7030
|
+
|
|
7031
|
+
// src/commands/statusline-script.ts
|
|
7032
|
+
function buildStatuslineScript(originalScript) {
|
|
7033
|
+
const body = originalScript.replace(/^#!\/.*\n/, "").trim();
|
|
7034
|
+
return `#!/bin/bash
|
|
7035
|
+
# CodeMap statusline for Claude Code
|
|
7036
|
+
# Generated by: codemap statusline
|
|
7037
|
+
# Do not edit \u2014 re-run \`codemap statusline\` to regenerate.
|
|
7038
|
+
# Original script backed up to statusline-command.sh.bak
|
|
7039
|
+
|
|
7040
|
+
set -euo pipefail
|
|
7041
|
+
|
|
7042
|
+
# Read session JSON from stdin (Claude Code pipes it)
|
|
7043
|
+
SESSION_JSON=$(cat)
|
|
7044
|
+
|
|
7045
|
+
# --- Original statusline ---
|
|
7046
|
+
${body ? `(
|
|
7047
|
+
${body}
|
|
7048
|
+
) <<< "$SESSION_JSON"` : "# (none)"}
|
|
7049
|
+
|
|
7050
|
+
# --- CodeMap status ---
|
|
7051
|
+
# Resolve the working directory from session JSON
|
|
7052
|
+
current_dir=$(echo "$SESSION_JSON" | ${jsonExtract("cwd")} 2>/dev/null || pwd)
|
|
7053
|
+
|
|
7054
|
+
# Run codemap status --json for the project directory
|
|
7055
|
+
cm_json=$(codemap status --json --cwd "$current_dir" 2>/dev/null || true)
|
|
7056
|
+
|
|
7057
|
+
if [ -z "$cm_json" ]; then
|
|
7058
|
+
exit 0
|
|
7059
|
+
fi
|
|
7060
|
+
|
|
7061
|
+
# Parse fields
|
|
7062
|
+
stats_null=$(echo "$cm_json" | ${jsonExtract("stats")} 2>/dev/null || echo "null")
|
|
7063
|
+
if [ "$stats_null" = "null" ] || [ -z "$stats_null" ]; then
|
|
7064
|
+
echo "CM: \u2014 no index"
|
|
7065
|
+
exit 0
|
|
7066
|
+
fi
|
|
7067
|
+
|
|
7068
|
+
total_files=$(echo "$cm_json" | ${jsonPath("stats", "totalFiles")} 2>/dev/null || echo "0")
|
|
7069
|
+
total_chunks=$(echo "$cm_json" | ${jsonPath("stats", "totalChunks")} 2>/dev/null || echo "0")
|
|
7070
|
+
stale_files=$(echo "$cm_json" | ${jsonPath("stats", "staleFiles")} 2>/dev/null || echo "0")
|
|
7071
|
+
last_updated=$(echo "$cm_json" | ${jsonPath("stats", "lastUpdated")} 2>/dev/null || echo "")
|
|
7072
|
+
indexing=$(echo "$cm_json" | ${jsonExtract("indexing")} 2>/dev/null || echo "false")
|
|
7073
|
+
|
|
7074
|
+
# Format chunks (e.g. 12400 \u2192 12.4k)
|
|
7075
|
+
format_chunks() {
|
|
7076
|
+
local n=$1
|
|
7077
|
+
if [ "$n" -ge 1000 ]; then
|
|
7078
|
+
local k=$((n / 100))
|
|
7079
|
+
local whole=$((k / 10))
|
|
7080
|
+
local frac=$((k % 10))
|
|
7081
|
+
echo "\${whole}.\${frac}k"
|
|
7082
|
+
else
|
|
7083
|
+
echo "$n"
|
|
7084
|
+
fi
|
|
7085
|
+
}
|
|
7086
|
+
|
|
7087
|
+
# Calculate time ago
|
|
7088
|
+
time_ago() {
|
|
7089
|
+
local updated="$1"
|
|
7090
|
+
if [ -z "$updated" ]; then
|
|
7091
|
+
echo "unknown"
|
|
7092
|
+
return
|
|
7093
|
+
fi
|
|
7094
|
+
local now
|
|
7095
|
+
now=$(date +%s)
|
|
7096
|
+
local then_ts
|
|
7097
|
+
# macOS date -j vs GNU date
|
|
7098
|
+
if date -j -f "%Y-%m-%dT%H:%M:%S" "$(echo "$updated" | cut -c1-19)" +%s >/dev/null 2>&1; then
|
|
7099
|
+
then_ts=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$(echo "$updated" | cut -c1-19)" +%s 2>/dev/null || echo "$now")
|
|
7100
|
+
else
|
|
7101
|
+
then_ts=$(date -d "$updated" +%s 2>/dev/null || echo "$now")
|
|
7102
|
+
fi
|
|
7103
|
+
local diff=$(( now - then_ts ))
|
|
7104
|
+
if [ "$diff" -lt 60 ]; then
|
|
7105
|
+
echo "\${diff}s ago"
|
|
7106
|
+
elif [ "$diff" -lt 3600 ]; then
|
|
7107
|
+
echo "$(( diff / 60 ))m ago"
|
|
7108
|
+
elif [ "$diff" -lt 86400 ]; then
|
|
7109
|
+
echo "$(( diff / 3600 ))h ago"
|
|
7110
|
+
else
|
|
7111
|
+
echo "$(( diff / 86400 ))d ago"
|
|
7112
|
+
fi
|
|
7113
|
+
}
|
|
7114
|
+
|
|
7115
|
+
# Watcher detection
|
|
7116
|
+
watcher_icon="\u25CB"
|
|
7117
|
+
if pgrep -f "codemap watch" >/dev/null 2>&1; then
|
|
7118
|
+
watcher_icon="\u25CF"
|
|
7119
|
+
fi
|
|
7120
|
+
|
|
7121
|
+
# Indexing indicator
|
|
7122
|
+
idx_icon=""
|
|
7123
|
+
if [ "$indexing" = "true" ]; then
|
|
7124
|
+
idx_icon=" IDX"
|
|
7125
|
+
fi
|
|
7126
|
+
|
|
7127
|
+
chunks_fmt=$(format_chunks "$total_chunks")
|
|
7128
|
+
|
|
7129
|
+
# Build status line
|
|
7130
|
+
line="CM: \${watcher_icon} \${total_files}f \${chunks_fmt}\u25C6"
|
|
7131
|
+
|
|
7132
|
+
if [ "$stale_files" -gt 0 ] 2>/dev/null; then
|
|
7133
|
+
line="\${line} \u26A0\${stale_files}"
|
|
7134
|
+
fi
|
|
7135
|
+
|
|
7136
|
+
line="\${line}\${idx_icon} | $(time_ago "$last_updated")"
|
|
7137
|
+
|
|
7138
|
+
echo "$line"
|
|
7139
|
+
`;
|
|
7140
|
+
}
|
|
7141
|
+
function jsonExtract(field) {
|
|
7142
|
+
return `grep -o '"${field}"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*:[[:space:]]*//' | sed 's/"//g' | head -1`;
|
|
7143
|
+
}
|
|
7144
|
+
function jsonPath(parent, child) {
|
|
7145
|
+
return `grep -o '"${child}"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*:[[:space:]]*//' | sed 's/"//g' | head -1`;
|
|
7146
|
+
}
|
|
7147
|
+
|
|
7148
|
+
// src/commands/statusline.ts
|
|
7149
|
+
var CLAUDE_DIR = path13.join(homedir3(), ".claude");
|
|
7150
|
+
var SETTINGS_FILE2 = path13.join(CLAUDE_DIR, "settings.json");
|
|
7151
|
+
var SCRIPT_FILE = path13.join(CLAUDE_DIR, "statusline-command.sh");
|
|
7152
|
+
var BACKUP_FILE = path13.join(CLAUDE_DIR, "statusline-command.sh.bak");
|
|
7153
|
+
function readSettings() {
|
|
7154
|
+
try {
|
|
7155
|
+
return JSON.parse(fs18.readFileSync(SETTINGS_FILE2, "utf-8"));
|
|
7156
|
+
} catch {
|
|
7157
|
+
return {};
|
|
7158
|
+
}
|
|
7159
|
+
}
|
|
7160
|
+
function writeSettings(settings) {
|
|
7161
|
+
fs18.mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
7162
|
+
fs18.writeFileSync(SETTINGS_FILE2, JSON.stringify(settings, null, 2) + "\n");
|
|
7163
|
+
}
|
|
7164
|
+
function registerStatusline(program2) {
|
|
7165
|
+
program2.command("statusline").description("Install CodeMap status into Claude Code statusline").option("--uninstall", "Remove CodeMap from statusline and restore backup").action(async (opts) => {
|
|
7166
|
+
if (opts.uninstall) {
|
|
7167
|
+
uninstall();
|
|
7168
|
+
return;
|
|
7169
|
+
}
|
|
7170
|
+
install();
|
|
7171
|
+
});
|
|
7172
|
+
}
|
|
7173
|
+
function install() {
|
|
7174
|
+
const settings = readSettings();
|
|
7175
|
+
if (fs18.existsSync(SCRIPT_FILE)) {
|
|
7176
|
+
try {
|
|
7177
|
+
const existing = fs18.readFileSync(SCRIPT_FILE, "utf-8");
|
|
7178
|
+
if (existing.includes("Generated by: codemap statusline")) {
|
|
7179
|
+
console.log(chalk17.yellow("CodeMap statusline is already installed."));
|
|
7180
|
+
console.log(chalk17.dim("Run `codemap statusline --uninstall` to remove, then reinstall."));
|
|
7181
|
+
return;
|
|
7182
|
+
}
|
|
7183
|
+
} catch {
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
7186
|
+
let originalScript = "";
|
|
7187
|
+
if (settings.statusline_command) {
|
|
7188
|
+
const currentCommand = settings.statusline_command;
|
|
7189
|
+
if (currentCommand.includes(SCRIPT_FILE) || currentCommand.endsWith("statusline-command.sh")) {
|
|
7190
|
+
if (fs18.existsSync(SCRIPT_FILE)) {
|
|
7191
|
+
originalScript = fs18.readFileSync(SCRIPT_FILE, "utf-8");
|
|
7192
|
+
}
|
|
7193
|
+
} else if (currentCommand.startsWith("/") || currentCommand.startsWith("~")) {
|
|
7194
|
+
const resolved = currentCommand.replace(/^~/, homedir3());
|
|
7195
|
+
try {
|
|
7196
|
+
originalScript = fs18.readFileSync(resolved, "utf-8");
|
|
7197
|
+
} catch {
|
|
7198
|
+
originalScript = `#!/bin/bash
|
|
7199
|
+
${currentCommand}`;
|
|
7200
|
+
}
|
|
7201
|
+
} else {
|
|
7202
|
+
originalScript = `#!/bin/bash
|
|
7203
|
+
${currentCommand}`;
|
|
7204
|
+
}
|
|
7205
|
+
}
|
|
7206
|
+
if (fs18.existsSync(SCRIPT_FILE)) {
|
|
7207
|
+
fs18.copyFileSync(SCRIPT_FILE, BACKUP_FILE);
|
|
7208
|
+
console.log(chalk17.dim(`Backed up existing script to ${BACKUP_FILE}`));
|
|
7209
|
+
}
|
|
7210
|
+
const script = buildStatuslineScript(originalScript);
|
|
7211
|
+
fs18.mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
7212
|
+
fs18.writeFileSync(SCRIPT_FILE, script, { mode: 493 });
|
|
7213
|
+
if (settings.statusline_command !== SCRIPT_FILE) {
|
|
7214
|
+
settings.statusline_command = SCRIPT_FILE;
|
|
7215
|
+
writeSettings(settings);
|
|
7216
|
+
console.log(chalk17.dim(`Updated ${SETTINGS_FILE2}`));
|
|
7217
|
+
}
|
|
7218
|
+
console.log();
|
|
7219
|
+
console.log(chalk17.green("CodeMap statusline installed."));
|
|
7220
|
+
console.log();
|
|
7221
|
+
console.log("The statusline will show:");
|
|
7222
|
+
console.log(chalk17.cyan(" CM: \u25CF 842f 12.4k\u25C6 | 23m ago") + chalk17.dim(" \u2014 watcher running, index fresh"));
|
|
7223
|
+
console.log(chalk17.cyan(" CM: \u25CB 842f 12.4k\u25C6 \u26A03 | 2h ago") + chalk17.dim(" \u2014 no watcher, 3 stale files"));
|
|
7224
|
+
console.log(chalk17.cyan(" CM: \u25CB 842f 12.4k\u25C6 IDX | 5s ago") + chalk17.dim(" \u2014 indexing in progress"));
|
|
7225
|
+
console.log(chalk17.cyan(" CM: \u2014 no index") + chalk17.dim(" \u2014 no stats.json found"));
|
|
7226
|
+
console.log();
|
|
7227
|
+
console.log(chalk17.dim("Restart Claude Code to see the statusline."));
|
|
7228
|
+
console.log(chalk17.dim("Run `codemap statusline --uninstall` to remove."));
|
|
7229
|
+
}
|
|
7230
|
+
function uninstall() {
|
|
7231
|
+
let restored = false;
|
|
7232
|
+
if (fs18.existsSync(BACKUP_FILE)) {
|
|
7233
|
+
fs18.copyFileSync(BACKUP_FILE, SCRIPT_FILE);
|
|
7234
|
+
fs18.unlinkSync(BACKUP_FILE);
|
|
7235
|
+
console.log(chalk17.dim(`Restored original script from backup.`));
|
|
7236
|
+
restored = true;
|
|
7237
|
+
} else if (fs18.existsSync(SCRIPT_FILE)) {
|
|
7238
|
+
try {
|
|
7239
|
+
const content = fs18.readFileSync(SCRIPT_FILE, "utf-8");
|
|
7240
|
+
if (content.includes("Generated by: codemap statusline")) {
|
|
7241
|
+
fs18.unlinkSync(SCRIPT_FILE);
|
|
7242
|
+
console.log(chalk17.dim(`Removed statusline script.`));
|
|
7243
|
+
const settings = readSettings();
|
|
7244
|
+
if (settings.statusline_command === SCRIPT_FILE) {
|
|
7245
|
+
delete settings.statusline_command;
|
|
7246
|
+
writeSettings(settings);
|
|
7247
|
+
console.log(chalk17.dim(`Cleared statusline_command from settings.`));
|
|
7248
|
+
}
|
|
7249
|
+
}
|
|
7250
|
+
} catch {
|
|
7251
|
+
}
|
|
7252
|
+
}
|
|
7253
|
+
if (!restored) {
|
|
7254
|
+
const settings = readSettings();
|
|
7255
|
+
if (settings.statusline_command) {
|
|
7256
|
+
delete settings.statusline_command;
|
|
7257
|
+
writeSettings(settings);
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
console.log();
|
|
7261
|
+
console.log(chalk17.green("CodeMap statusline removed."));
|
|
7262
|
+
console.log(chalk17.dim("Restart Claude Code for changes to take effect."));
|
|
7263
|
+
}
|
|
7264
|
+
|
|
7013
7265
|
// src/index.ts
|
|
7014
|
-
var __dirname =
|
|
7015
|
-
var grammarsDir =
|
|
7266
|
+
var __dirname = path14.dirname(fileURLToPath(import.meta.url));
|
|
7267
|
+
var grammarsDir = path14.join(__dirname, "grammars");
|
|
7016
7268
|
setGrammarDir(grammarsDir);
|
|
7017
7269
|
var program = new Command();
|
|
7018
7270
|
program.name("codemap").description("Code intelligence CLI \u2014 hybrid search, dependency analysis, PageRank").version("0.3.5").option("--cwd <dir>", "Project directory (default: cwd)");
|
|
@@ -7033,4 +7285,5 @@ registerSummary(program);
|
|
|
7033
7285
|
registerCoupling(program);
|
|
7034
7286
|
registerGraphStats(program);
|
|
7035
7287
|
registerRebuild(program);
|
|
7288
|
+
registerStatusline(program);
|
|
7036
7289
|
program.parse();
|