@ulpi/codemap 0.3.11 → 0.3.13
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/README.md +29 -0
- package/dist/index.js +181 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,35 @@ codemap watch --debounce 500
|
|
|
111
111
|
|--------|-------------|---------|
|
|
112
112
|
| `--debounce <ms>` | Debounce interval | `300` |
|
|
113
113
|
|
|
114
|
+
### `codemap statusline`
|
|
115
|
+
|
|
116
|
+
Install a CodeMap status indicator into Claude Code's statusline. It extends your existing statusline (if any) and appends CodeMap info.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
codemap statusline # Install
|
|
120
|
+
codemap statusline --uninstall # Remove and restore previous statusline
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The statusline shows at a glance:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
MyProject | git:main | Opus (1M context) | ctx:8%
|
|
127
|
+
CodeMap: ● 842 files · ◆12.4k chunks | 23m ago
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
With multiple codemap MCP servers registered in `.mcp.json`, each gets its own line:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
MyProject | git:main | Opus (1M context) | ctx:8%
|
|
134
|
+
CodeMap: ● 842 files · ◆12.4k chunks | 23m ago
|
|
135
|
+
CodeMap (frontend): ○ 360 files · ◆1.9k chunks · ⚠3 stale | 2h ago
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- **●/○** — `codemap watch` running or not
|
|
139
|
+
- **◆** — indexed chunks (search units)
|
|
140
|
+
- **⚠N stale** — files modified since last index
|
|
141
|
+
- **IDX** — indexing in progress
|
|
142
|
+
|
|
114
143
|
### `codemap deps <file>`
|
|
115
144
|
|
|
116
145
|
Show files this file depends on (outgoing imports).
|
package/dist/index.js
CHANGED
|
@@ -5924,13 +5924,10 @@ function registerInit(program2) {
|
|
|
5924
5924
|
console.log(` ${chalk3.cyan("codemap search")} Search your code`);
|
|
5925
5925
|
console.log(` ${chalk3.cyan("codemap serve")} Start MCP server`);
|
|
5926
5926
|
console.log();
|
|
5927
|
-
|
|
5927
|
+
await showAgentSnippet(program2.opts().cwd || process.cwd());
|
|
5928
5928
|
});
|
|
5929
5929
|
}
|
|
5930
|
-
|
|
5931
|
-
console.log(chalk3.bold("Add to your CLAUDE.md / agents.md / rules:"));
|
|
5932
|
-
console.log(chalk3.dim("\u2500".repeat(60)));
|
|
5933
|
-
console.log(`
|
|
5930
|
+
var AGENT_SNIPPET = `
|
|
5934
5931
|
## Code Intelligence (codemap)
|
|
5935
5932
|
|
|
5936
5933
|
This project is indexed with codemap for semantic code search,
|
|
@@ -5976,10 +5973,34 @@ symbol lookup, dependency analysis, and PageRank file ranking.
|
|
|
5976
5973
|
- **Understanding impact**: \`get_dependents\` to see what breaks if you change a file
|
|
5977
5974
|
- **Architecture review**: \`get_coupling_metrics\` and \`find_cycles\` for code health
|
|
5978
5975
|
- **Navigation**: \`get_file_rank\` to identify the most important files
|
|
5979
|
-
|
|
5976
|
+
- **Cross-project**: Any \`codemap-<name>\` MCP servers (e.g. \`codemap-frontend\`) are connected projects \u2014 use their tools to search and trace dependencies across your stack
|
|
5977
|
+
`.trim();
|
|
5978
|
+
async function showAgentSnippet(projectDir) {
|
|
5979
|
+
console.log(chalk3.bold("Agent configuration snippet:"));
|
|
5980
|
+
console.log(chalk3.dim("\u2500".repeat(60)));
|
|
5981
|
+
console.log(AGENT_SNIPPET);
|
|
5980
5982
|
console.log();
|
|
5981
5983
|
console.log(chalk3.dim("\u2500".repeat(60)));
|
|
5982
|
-
|
|
5984
|
+
const claudeMdPath = path11.join(projectDir, "CLAUDE.md");
|
|
5985
|
+
const exists = fs13.existsSync(claudeMdPath);
|
|
5986
|
+
const prompt = exists ? `Append this to ${chalk3.cyan("CLAUDE.md")}? (Y/n): ` : `Create ${chalk3.cyan("CLAUDE.md")} with this content? (Y/n): `;
|
|
5987
|
+
const answer = await ask(prompt);
|
|
5988
|
+
if (answer.toLowerCase() !== "n") {
|
|
5989
|
+
if (exists) {
|
|
5990
|
+
const current = fs13.readFileSync(claudeMdPath, "utf-8");
|
|
5991
|
+
if (current.includes("## Code Intelligence (codemap)")) {
|
|
5992
|
+
console.log(chalk3.yellow("CLAUDE.md already contains a codemap section. Skipping."));
|
|
5993
|
+
} else {
|
|
5994
|
+
fs13.appendFileSync(claudeMdPath, "\n\n" + AGENT_SNIPPET + "\n");
|
|
5995
|
+
console.log(chalk3.green("Appended to ") + chalk3.cyan("CLAUDE.md"));
|
|
5996
|
+
}
|
|
5997
|
+
} else {
|
|
5998
|
+
fs13.writeFileSync(claudeMdPath, AGENT_SNIPPET + "\n");
|
|
5999
|
+
console.log(chalk3.green("Created ") + chalk3.cyan("CLAUDE.md"));
|
|
6000
|
+
}
|
|
6001
|
+
} else {
|
|
6002
|
+
console.log(chalk3.dim("Skipped. You can copy the snippet above manually."));
|
|
6003
|
+
}
|
|
5983
6004
|
console.log();
|
|
5984
6005
|
console.log(chalk3.bold("Multi-project setup"));
|
|
5985
6006
|
console.log();
|
|
@@ -6137,14 +6158,24 @@ function registerIndex(program2) {
|
|
|
6137
6158
|
console.log(chalk4.bold("Indexing ") + chalk4.cyan(projectDir));
|
|
6138
6159
|
console.log(chalk4.dim(`Branch: ${branch} | Provider: ${config.embedding.provider} | Model: ${config.embedding.model}`));
|
|
6139
6160
|
console.log();
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6161
|
+
let stats;
|
|
6162
|
+
try {
|
|
6163
|
+
stats = await runInitPipeline(projectDir, config, {
|
|
6164
|
+
branch,
|
|
6165
|
+
dataDir: getDataDir2(),
|
|
6166
|
+
onProgress: (progress) => {
|
|
6167
|
+
const pct = progress.total ? ` (${progress.current ?? 0}/${progress.total})` : "";
|
|
6168
|
+
console.log(chalk4.dim(`[${progress.phase}]`) + ` ${progress.message}${pct}`);
|
|
6169
|
+
}
|
|
6170
|
+
});
|
|
6171
|
+
} catch (err) {
|
|
6172
|
+
if (err instanceof Error && err.message.includes("Failed to acquire codemap lock")) {
|
|
6173
|
+
console.log(chalk4.yellow("Another codemap process is already indexing this project."));
|
|
6174
|
+
console.log(chalk4.dim("Wait for it to finish, or run `codemap status` to check."));
|
|
6175
|
+
return;
|
|
6146
6176
|
}
|
|
6147
|
-
|
|
6177
|
+
throw err;
|
|
6178
|
+
}
|
|
6148
6179
|
console.log();
|
|
6149
6180
|
console.log(chalk4.green("Index complete:"));
|
|
6150
6181
|
console.log(` Files: ${stats.totalFiles}`);
|
|
@@ -7051,7 +7082,11 @@ import { homedir as homedir3 } from "os";
|
|
|
7051
7082
|
function buildStatuslineScript(originalCommand) {
|
|
7052
7083
|
const escapedCmd = originalCommand.replace(/'/g, "'\\''");
|
|
7053
7084
|
const originalSection = originalCommand ? `ORIGINAL_CMD='${escapedCmd}'
|
|
7054
|
-
echo "$SESSION_JSON" | eval "$ORIGINAL_CMD" 2>/dev/null || true
|
|
7085
|
+
original_out=$(echo "$SESSION_JSON" | eval "$ORIGINAL_CMD" 2>/dev/null || true)
|
|
7086
|
+
if [ -n "$original_out" ]; then
|
|
7087
|
+
echo "$original_out"
|
|
7088
|
+
has_line1=true
|
|
7089
|
+
fi` : "";
|
|
7055
7090
|
return `#!/bin/bash
|
|
7056
7091
|
# CodeMap statusline for Claude Code
|
|
7057
7092
|
# Generated by: codemap statusline
|
|
@@ -7062,34 +7097,49 @@ set -euo pipefail
|
|
|
7062
7097
|
# Read session JSON from stdin (Claude Code pipes it)
|
|
7063
7098
|
SESSION_JSON=$(cat)
|
|
7064
7099
|
|
|
7065
|
-
|
|
7100
|
+
has_line1=false
|
|
7101
|
+
|
|
7102
|
+
# --- Original statusline command (if any) ---
|
|
7066
7103
|
${originalSection}
|
|
7067
7104
|
|
|
7068
|
-
# ---
|
|
7069
|
-
# Resolve the working directory from session JSON
|
|
7105
|
+
# --- Reconstruct Claude Code default status (line 1) ---
|
|
7070
7106
|
current_dir=$(echo "$SESSION_JSON" | ${jsonExtract("cwd")} 2>/dev/null || pwd)
|
|
7071
7107
|
|
|
7072
|
-
|
|
7073
|
-
|
|
7108
|
+
if [ "$has_line1" = "false" ]; then
|
|
7109
|
+
project_name=$(basename "$current_dir")
|
|
7110
|
+
git_branch=$(cd "$current_dir" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
|
7111
|
+
model_display=$(echo "$SESSION_JSON" | ${jsonExtract("display_name")} 2>/dev/null || echo "")
|
|
7112
|
+
ctx_size=$(echo "$SESSION_JSON" | ${jsonExtract("context_window_size")} 2>/dev/null || echo "")
|
|
7113
|
+
ctx_label=""
|
|
7114
|
+
if [ -n "$ctx_size" ]; then
|
|
7115
|
+
if [ "$ctx_size" -ge 1000000 ] 2>/dev/null; then
|
|
7116
|
+
ctx_label="1M context"
|
|
7117
|
+
elif [ "$ctx_size" -ge 100000 ] 2>/dev/null; then
|
|
7118
|
+
ctx_label="200k context"
|
|
7119
|
+
fi
|
|
7120
|
+
fi
|
|
7121
|
+
ctx_pct=$(echo "$SESSION_JSON" | ${jsonExtract("used_percentage")} 2>/dev/null || echo "")
|
|
7074
7122
|
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7123
|
+
line1="$project_name"
|
|
7124
|
+
if [ -n "$git_branch" ]; then
|
|
7125
|
+
line1="\${line1} | git:$git_branch"
|
|
7126
|
+
fi
|
|
7127
|
+
if [ -n "$model_display" ]; then
|
|
7128
|
+
if [ -n "$ctx_label" ]; then
|
|
7129
|
+
line1="\${line1} | \${model_display} (\${ctx_label})"
|
|
7130
|
+
else
|
|
7131
|
+
line1="\${line1} | \${model_display}"
|
|
7132
|
+
fi
|
|
7133
|
+
fi
|
|
7134
|
+
if [ -n "$ctx_pct" ]; then
|
|
7135
|
+
line1="\${line1} | ctx:\${ctx_pct}%"
|
|
7136
|
+
fi
|
|
7078
7137
|
|
|
7079
|
-
|
|
7080
|
-
stats_null=$(echo "$cm_json" | ${jsonExtract("stats")} 2>/dev/null || echo "null")
|
|
7081
|
-
if [ "$stats_null" = "null" ] || [ -z "$stats_null" ]; then
|
|
7082
|
-
echo "CM: \u2014 no index (run: codemap index)"
|
|
7083
|
-
exit 0
|
|
7138
|
+
echo "$line1"
|
|
7084
7139
|
fi
|
|
7085
7140
|
|
|
7086
|
-
|
|
7087
|
-
total_chunks=$(echo "$cm_json" | ${jsonPath("stats", "totalChunks")} 2>/dev/null || echo "0")
|
|
7088
|
-
stale_files=$(echo "$cm_json" | ${jsonPath("stats", "staleFiles")} 2>/dev/null || echo "0")
|
|
7089
|
-
last_updated=$(echo "$cm_json" | ${jsonPath("stats", "lastUpdated")} 2>/dev/null || echo "")
|
|
7090
|
-
indexing=$(echo "$cm_json" | ${jsonExtract("indexing")} 2>/dev/null || echo "false")
|
|
7141
|
+
# --- Helper functions ---
|
|
7091
7142
|
|
|
7092
|
-
# Format chunks (e.g. 12400 \u2192 12.4k)
|
|
7093
7143
|
format_chunks() {
|
|
7094
7144
|
local n=$1
|
|
7095
7145
|
if [ "$n" -ge 1000 ]; then
|
|
@@ -7102,7 +7152,6 @@ format_chunks() {
|
|
|
7102
7152
|
fi
|
|
7103
7153
|
}
|
|
7104
7154
|
|
|
7105
|
-
# Calculate time ago
|
|
7106
7155
|
time_ago() {
|
|
7107
7156
|
local updated="$1"
|
|
7108
7157
|
if [ -z "$updated" ]; then
|
|
@@ -7112,7 +7161,6 @@ time_ago() {
|
|
|
7112
7161
|
local now
|
|
7113
7162
|
now=$(date +%s)
|
|
7114
7163
|
local then_ts
|
|
7115
|
-
# macOS date -j vs GNU date
|
|
7116
7164
|
if date -j -f "%Y-%m-%dT%H:%M:%S" "$(echo "$updated" | cut -c1-19)" +%s >/dev/null 2>&1; then
|
|
7117
7165
|
then_ts=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$(echo "$updated" | cut -c1-19)" +%s 2>/dev/null || echo "$now")
|
|
7118
7166
|
else
|
|
@@ -7130,36 +7178,104 @@ time_ago() {
|
|
|
7130
7178
|
fi
|
|
7131
7179
|
}
|
|
7132
7180
|
|
|
7133
|
-
#
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
fi
|
|
7181
|
+
# Print one CodeMap status line for a given project directory and label
|
|
7182
|
+
print_codemap_status() {
|
|
7183
|
+
local label="$1"
|
|
7184
|
+
local target_dir="$2"
|
|
7138
7185
|
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
if [ "$
|
|
7142
|
-
|
|
7143
|
-
fi
|
|
7186
|
+
local cm_json
|
|
7187
|
+
cm_json=$(codemap status --json --cwd "$target_dir" 2>/dev/null || true)
|
|
7188
|
+
if [ -z "$cm_json" ]; then
|
|
7189
|
+
return
|
|
7190
|
+
fi
|
|
7144
7191
|
|
|
7145
|
-
|
|
7192
|
+
local stats_null
|
|
7193
|
+
stats_null=$(echo "$cm_json" | ${jsonExtract("stats")} 2>/dev/null || echo "null")
|
|
7194
|
+
if [ "$stats_null" = "null" ] || [ -z "$stats_null" ]; then
|
|
7195
|
+
echo "\${label} \u2014 no index (run: codemap index)"
|
|
7196
|
+
return
|
|
7197
|
+
fi
|
|
7146
7198
|
|
|
7147
|
-
|
|
7148
|
-
|
|
7199
|
+
local total_files total_chunks stale_files last_updated indexing
|
|
7200
|
+
total_files=$(echo "$cm_json" | ${jsonPath("stats", "totalFiles")} 2>/dev/null || echo "0")
|
|
7201
|
+
total_chunks=$(echo "$cm_json" | ${jsonPath("stats", "totalChunks")} 2>/dev/null || echo "0")
|
|
7202
|
+
stale_files=$(echo "$cm_json" | ${jsonPath("stats", "staleFiles")} 2>/dev/null || echo "0")
|
|
7203
|
+
last_updated=$(echo "$cm_json" | ${jsonPath("stats", "lastUpdated")} 2>/dev/null || echo "")
|
|
7204
|
+
indexing=$(echo "$cm_json" | ${jsonExtract("indexing")} 2>/dev/null || echo "false")
|
|
7149
7205
|
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7206
|
+
local watcher_icon="\u25CB"
|
|
7207
|
+
if pgrep -f "codemap watch" >/dev/null 2>&1; then
|
|
7208
|
+
watcher_icon="\u25CF"
|
|
7209
|
+
fi
|
|
7210
|
+
|
|
7211
|
+
local idx_icon=""
|
|
7212
|
+
if [ "$indexing" = "true" ]; then
|
|
7213
|
+
idx_icon=" \xB7 IDX"
|
|
7214
|
+
fi
|
|
7215
|
+
|
|
7216
|
+
local chunks_fmt
|
|
7217
|
+
chunks_fmt=$(format_chunks "$total_chunks")
|
|
7218
|
+
|
|
7219
|
+
local line="\${label} \${watcher_icon} \${total_files} files \xB7 \u25C6\${chunks_fmt} chunks"
|
|
7220
|
+
|
|
7221
|
+
if [ "$stale_files" -gt 0 ] 2>/dev/null; then
|
|
7222
|
+
line="\${line} \xB7 \u26A0\${stale_files} stale"
|
|
7223
|
+
fi
|
|
7153
7224
|
|
|
7154
|
-
line="\${line}\${idx_icon} | $(time_ago "$last_updated")"
|
|
7225
|
+
line="\${line}\${idx_icon} | $(time_ago "$last_updated")"
|
|
7155
7226
|
|
|
7156
|
-
echo "$line"
|
|
7227
|
+
echo "$line"
|
|
7228
|
+
}
|
|
7229
|
+
|
|
7230
|
+
# --- CodeMap status lines ---
|
|
7231
|
+
|
|
7232
|
+
# Discover codemap MCP servers from .mcp.json
|
|
7233
|
+
mcp_file="$current_dir/.mcp.json"
|
|
7234
|
+
found_servers=false
|
|
7235
|
+
|
|
7236
|
+
if [ -f "$mcp_file" ]; then
|
|
7237
|
+
# Use node to reliably parse JSON \u2014 extract "name|cwd" pairs for codemap servers
|
|
7238
|
+
codemap_servers=$(node -e "
|
|
7239
|
+
const fs = require('fs');
|
|
7240
|
+
try {
|
|
7241
|
+
const mcp = JSON.parse(fs.readFileSync(process.argv[1], 'utf-8'));
|
|
7242
|
+
const servers = mcp.mcpServers || {};
|
|
7243
|
+
for (const [name, config] of Object.entries(servers)) {
|
|
7244
|
+
if (config.command !== 'codemap') continue;
|
|
7245
|
+
const args = config.args || [];
|
|
7246
|
+
const cwdIdx = args.indexOf('--cwd');
|
|
7247
|
+
const cwd = cwdIdx >= 0 && cwdIdx + 1 < args.length ? args[cwdIdx + 1] : '';
|
|
7248
|
+
console.log(name + '|' + cwd);
|
|
7249
|
+
}
|
|
7250
|
+
} catch {}
|
|
7251
|
+
" "$mcp_file" 2>/dev/null || true)
|
|
7252
|
+
|
|
7253
|
+
if [ -n "$codemap_servers" ]; then
|
|
7254
|
+
found_servers=true
|
|
7255
|
+
while IFS='|' read -r server_name server_cwd; do
|
|
7256
|
+
target_dir="\${server_cwd:-$current_dir}"
|
|
7257
|
+
# Derive label: "codemap" \u2192 "CodeMap:", "codemap-frontend" \u2192 "CodeMap (frontend):"
|
|
7258
|
+
suffix=$(echo "$server_name" | sed 's/^codemap-//' | sed 's/^codemap$//')
|
|
7259
|
+
if [ -n "$suffix" ]; then
|
|
7260
|
+
label="CodeMap (\${suffix}):"
|
|
7261
|
+
else
|
|
7262
|
+
label="CodeMap:"
|
|
7263
|
+
fi
|
|
7264
|
+
print_codemap_status "$label" "$target_dir"
|
|
7265
|
+
done <<< "$codemap_servers"
|
|
7266
|
+
fi
|
|
7267
|
+
fi
|
|
7268
|
+
|
|
7269
|
+
# Fallback: no .mcp.json or no codemap entries \u2014 show status for current dir
|
|
7270
|
+
if [ "$found_servers" = "false" ]; then
|
|
7271
|
+
print_codemap_status "CodeMap:" "$current_dir"
|
|
7272
|
+
fi
|
|
7157
7273
|
`;
|
|
7158
7274
|
}
|
|
7159
7275
|
function jsonExtract(field) {
|
|
7160
7276
|
return `grep -o '"${field}"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*:[[:space:]]*//' | sed 's/"//g' | head -1`;
|
|
7161
7277
|
}
|
|
7162
|
-
function jsonPath(
|
|
7278
|
+
function jsonPath(_parent, child) {
|
|
7163
7279
|
return `grep -o '"${child}"[[:space:]]*:[[:space:]]*[^,}]*' | sed 's/.*:[[:space:]]*//' | sed 's/"//g' | head -1`;
|
|
7164
7280
|
}
|
|
7165
7281
|
|
|
@@ -7221,11 +7337,16 @@ function install() {
|
|
|
7221
7337
|
console.log(chalk17.dim("Your existing statusline is preserved \u2014 CodeMap appends to it."));
|
|
7222
7338
|
}
|
|
7223
7339
|
console.log();
|
|
7224
|
-
console.log("
|
|
7225
|
-
console.log(
|
|
7226
|
-
console.log(chalk17.cyan("
|
|
7227
|
-
console.log(chalk17.cyan("
|
|
7228
|
-
console.log(
|
|
7340
|
+
console.log("The statusline will show:");
|
|
7341
|
+
console.log();
|
|
7342
|
+
console.log(" " + chalk17.cyan("MyProject | git:main | Opus (1M context) | ctx:8%"));
|
|
7343
|
+
console.log(" " + chalk17.cyan("CodeMap: \u25CF 842 files \xB7 \u25C612.4k chunks | 23m ago"));
|
|
7344
|
+
console.log();
|
|
7345
|
+
console.log(" With multiple codemap MCP servers:");
|
|
7346
|
+
console.log();
|
|
7347
|
+
console.log(" " + chalk17.cyan("MyProject | git:main | Opus (1M context) | ctx:8%"));
|
|
7348
|
+
console.log(" " + chalk17.cyan("CodeMap: \u25CF 842 files \xB7 \u25C612.4k chunks | 23m ago"));
|
|
7349
|
+
console.log(" " + chalk17.cyan("CodeMap (frontend): \u25CB 360 files \xB7 \u25C61.9k chunks \xB7 \u26A03 stale | 2h ago"));
|
|
7229
7350
|
console.log();
|
|
7230
7351
|
console.log(chalk17.dim("Restart Claude Code to see the statusline."));
|
|
7231
7352
|
console.log(chalk17.dim("Run `codemap statusline --uninstall` to remove."));
|