xray-code 0.1.0 → 0.1.2
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/cli.js +55 -12
- package/dist/install.d.ts +10 -0
- package/dist/install.js +265 -0
- package/dist/onboard.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -19,10 +19,11 @@ const commander_1 = require("commander");
|
|
|
19
19
|
const auth_js_1 = require("./auth.js");
|
|
20
20
|
const onboard_js_1 = require("./onboard.js");
|
|
21
21
|
const client_js_1 = require("./client.js");
|
|
22
|
+
const install_js_1 = require("./install.js");
|
|
22
23
|
const program = new commander_1.Command()
|
|
23
24
|
.name("xray")
|
|
24
25
|
.description("X-ray your codebase — instant cross-references and impact analysis")
|
|
25
|
-
.version("0.1.
|
|
26
|
+
.version("0.1.1");
|
|
26
27
|
// ─── Auth commands ──────────────────────────────────────────────
|
|
27
28
|
program
|
|
28
29
|
.command("login")
|
|
@@ -67,12 +68,28 @@ program
|
|
|
67
68
|
if (!existsSync(dir))
|
|
68
69
|
mkdirSync(dir, { recursive: true });
|
|
69
70
|
writeFileSync(join(dir, "config.json"), JSON.stringify({ server: entry.server, apiKey: entry.apiKey }, null, 2), { mode: 0o600 });
|
|
70
|
-
console.log(`
|
|
71
|
-
console.log(`
|
|
71
|
+
console.log(` Invite code accepted!\n`);
|
|
72
|
+
console.log(` Now let's connect your GitHub account...\n`);
|
|
73
|
+
try {
|
|
74
|
+
await (0, auth_js_1.login)();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
console.log(`\n GitHub login skipped.\n`);
|
|
78
|
+
}
|
|
72
79
|
const client = new client_js_1.XRayClient(entry.server, entry.apiKey);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
try {
|
|
81
|
+
const health = await client.health();
|
|
82
|
+
console.log(`\n ══════════════════════════════════════════════════`);
|
|
83
|
+
console.log(` XRay is ready!`);
|
|
84
|
+
console.log(` ══════════════════════════════════════════════════\n`);
|
|
85
|
+
console.log(` Symbols: ${health.symbols.toLocaleString()}`);
|
|
86
|
+
console.log(` Refs: ${health.uses.toLocaleString()}`);
|
|
87
|
+
console.log(` Files: ${health.files.toLocaleString()}\n`);
|
|
88
|
+
console.log(` Try: npx xray-code search <symbol-name>\n`);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
console.log(` Config saved. Try 'npx xray-code health' in a minute.\n`);
|
|
92
|
+
}
|
|
76
93
|
return;
|
|
77
94
|
}
|
|
78
95
|
}
|
|
@@ -84,13 +101,39 @@ program
|
|
|
84
101
|
if (!existsSync(dir))
|
|
85
102
|
mkdirSync(dir, { recursive: true });
|
|
86
103
|
writeFileSync(join(dir, "config.json"), JSON.stringify({ server: data.server, apiKey: data.api_key }, null, 2), { mode: 0o600 });
|
|
87
|
-
console.log(`
|
|
88
|
-
|
|
89
|
-
console.log(`
|
|
104
|
+
console.log(` Invite code accepted!\n`);
|
|
105
|
+
// Step 2: GitHub login
|
|
106
|
+
console.log(` Now let's connect your GitHub account...\n`);
|
|
107
|
+
try {
|
|
108
|
+
await (0, auth_js_1.login)();
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
console.log(`\n GitHub login skipped — you can run 'npx xray-code login' later.\n`);
|
|
112
|
+
}
|
|
113
|
+
// Step 3: Install Claude Code integration in current project
|
|
90
114
|
const client = new client_js_1.XRayClient(data.server, data.api_key);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
115
|
+
try {
|
|
116
|
+
const health = await client.health();
|
|
117
|
+
console.log(`\n Setting up Claude Code integration...\n`);
|
|
118
|
+
(0, install_js_1.installClaude)(process.cwd(), data.server, data.api_key, data.space, health.symbols, health.uses);
|
|
119
|
+
console.log(`\n ══════════════════════════════════════════════════`);
|
|
120
|
+
console.log(` XRay is ready!`);
|
|
121
|
+
console.log(` ══════════════════════════════════════════════════\n`);
|
|
122
|
+
console.log(` Codebase: ${data.space}`);
|
|
123
|
+
console.log(` Symbols: ${health.symbols.toLocaleString()}`);
|
|
124
|
+
console.log(` Refs: ${health.uses.toLocaleString()}`);
|
|
125
|
+
console.log(` Files: ${health.files.toLocaleString()}\n`);
|
|
126
|
+
console.log(` Your Claude Code agent now has ambient code intelligence.`);
|
|
127
|
+
console.log(` Every Grep/Glob search automatically gets cross-reference context.\n`);
|
|
128
|
+
console.log(` Manual commands:`);
|
|
129
|
+
console.log(` npx xray-code search <symbol-name>`);
|
|
130
|
+
console.log(` npx xray-code who-uses <symbol-name>`);
|
|
131
|
+
console.log(` npx xray-code impact <symbol-name>`);
|
|
132
|
+
console.log(` npx xray-code health\n`);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
console.log(` Config saved. Server may still be indexing — try 'npx xray-code health' in a minute.\n`);
|
|
136
|
+
}
|
|
94
137
|
}
|
|
95
138
|
catch (e) {
|
|
96
139
|
console.error(` Activation failed: ${e}\n`);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XRay Claude Code integration installer.
|
|
3
|
+
*
|
|
4
|
+
* After activation, installs:
|
|
5
|
+
* .claude/hooks/xray-inject.sh — ambient code intelligence on Grep/Glob
|
|
6
|
+
* .claude/settings.json — registers the hook
|
|
7
|
+
* CLAUDE.md — adds XRay section
|
|
8
|
+
* .claude/memory/xray.md — memory file for AI context
|
|
9
|
+
*/
|
|
10
|
+
export declare function installClaude(projectDir: string, server: string, apiKey: string, space: string, symbols: number, refs: number): void;
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XRay Claude Code integration installer.
|
|
4
|
+
*
|
|
5
|
+
* After activation, installs:
|
|
6
|
+
* .claude/hooks/xray-inject.sh — ambient code intelligence on Grep/Glob
|
|
7
|
+
* .claude/settings.json — registers the hook
|
|
8
|
+
* CLAUDE.md — adds XRay section
|
|
9
|
+
* .claude/memory/xray.md — memory file for AI context
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.installClaude = installClaude;
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
const HOOK_SCRIPT = `#!/usr/bin/env bash
|
|
16
|
+
# XRay Code Intelligence — ambient cross-reference injection
|
|
17
|
+
#
|
|
18
|
+
# PreToolUse:Grep|Glob
|
|
19
|
+
#
|
|
20
|
+
# When Claude searches for something, this hook queries the XRay API
|
|
21
|
+
# and injects cross-reference context automatically.
|
|
22
|
+
|
|
23
|
+
set -uo pipefail
|
|
24
|
+
|
|
25
|
+
XRAY_SERVER="\${XRAY_SERVER:-__XRAY_SERVER__}"
|
|
26
|
+
XRAY_KEY="\${XRAY_API_KEY:-__XRAY_KEY__}"
|
|
27
|
+
MAX_SYMBOLS=3
|
|
28
|
+
RATE_LIMIT_SECONDS=5
|
|
29
|
+
RATE_FILE="/tmp/.xray-inject-last"
|
|
30
|
+
|
|
31
|
+
RAW_INPUT=""
|
|
32
|
+
if [[ -t 0 ]]; then
|
|
33
|
+
RAW_INPUT="\${1:-}"
|
|
34
|
+
else
|
|
35
|
+
RAW_INPUT=$(cat)
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
[[ -z "$RAW_INPUT" ]] && exit 0
|
|
39
|
+
command -v jq &>/dev/null || exit 0
|
|
40
|
+
command -v curl &>/dev/null || exit 0
|
|
41
|
+
|
|
42
|
+
TOOL_NAME=$(echo "$RAW_INPUT" | jq -r '.tool_name // empty' 2>/dev/null) || exit 0
|
|
43
|
+
if [[ "$TOOL_NAME" != "Grep" ]] && [[ "$TOOL_NAME" != "Glob" ]]; then
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
PATTERN=$(echo "$RAW_INPUT" | jq -r '.tool_input.pattern // empty' 2>/dev/null) || exit 0
|
|
48
|
+
[[ -z "$PATTERN" ]] && exit 0
|
|
49
|
+
|
|
50
|
+
SEARCH_TERM="$PATTERN"
|
|
51
|
+
SEARCH_TERM="\${SEARCH_TERM//\\*/}"
|
|
52
|
+
SEARCH_TERM="\${SEARCH_TERM//\\?/}"
|
|
53
|
+
SEARCH_TERM="\${SEARCH_TERM//\\^/}"
|
|
54
|
+
SEARCH_TERM="\${SEARCH_TERM//$/}"
|
|
55
|
+
SEARCH_TERM="\${SEARCH_TERM//\\\\b/}"
|
|
56
|
+
SEARCH_TERM="\${SEARCH_TERM//\\\\s+/ }"
|
|
57
|
+
SEARCH_TERM="\${SEARCH_TERM//\\\\w+/}"
|
|
58
|
+
SEARCH_TERM="\${SEARCH_TERM//\\.\\*/}"
|
|
59
|
+
SEARCH_TERM="\${SEARCH_TERM//\\(/}"
|
|
60
|
+
SEARCH_TERM="\${SEARCH_TERM//\\)/}"
|
|
61
|
+
SEARCH_TERM="\${SEARCH_TERM//\\[/}"
|
|
62
|
+
SEARCH_TERM="\${SEARCH_TERM//\\]/}"
|
|
63
|
+
SEARCH_TERM="\${SEARCH_TERM//\\{/}"
|
|
64
|
+
SEARCH_TERM="\${SEARCH_TERM//\\}/}"
|
|
65
|
+
SEARCH_TERM="\${SEARCH_TERM//|/}"
|
|
66
|
+
SEARCH_TERM=$(echo "$SEARCH_TERM" | sed 's|.*/||')
|
|
67
|
+
SEARCH_TERM="\${SEARCH_TERM//\\./}"
|
|
68
|
+
SEARCH_TERM=$(echo "$SEARCH_TERM" | xargs)
|
|
69
|
+
|
|
70
|
+
if [[ "$SEARCH_TERM" == *" "* ]]; then
|
|
71
|
+
LONGEST=""
|
|
72
|
+
for word in $SEARCH_TERM; do
|
|
73
|
+
if [[ \${#word} -gt \${#LONGEST} ]]; then
|
|
74
|
+
LONGEST="$word"
|
|
75
|
+
fi
|
|
76
|
+
done
|
|
77
|
+
SEARCH_TERM="$LONGEST"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
[[ \${#SEARCH_TERM} -lt 4 ]] && exit 0
|
|
81
|
+
|
|
82
|
+
case "\${SEARCH_TERM,,}" in
|
|
83
|
+
import|require|function|class|struct|enum|trait|interface|const|type|return|async|await|pub|fn|let|mut|self|impl|use|mod|crate)
|
|
84
|
+
exit 0 ;;
|
|
85
|
+
esac
|
|
86
|
+
|
|
87
|
+
NOW=$(date +%s)
|
|
88
|
+
if [[ -f "$RATE_FILE" ]]; then
|
|
89
|
+
LAST=$(cat "$RATE_FILE" 2>/dev/null || echo "0")
|
|
90
|
+
if (( NOW - LAST < RATE_LIMIT_SECONDS )); then
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
CURL_ARGS=(-s --max-time 3)
|
|
96
|
+
if [[ -n "$XRAY_KEY" ]]; then
|
|
97
|
+
CURL_ARGS+=(-H "X-FoxRef-Key: $XRAY_KEY")
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
SEARCH_OUTPUT=$(curl "\${CURL_ARGS[@]}" "\${XRAY_SERVER}/api/v1/search?q=\${SEARCH_TERM}&limit=\${MAX_SYMBOLS}" 2>/dev/null) || exit 0
|
|
101
|
+
[[ -z "$SEARCH_OUTPUT" ]] && exit 0
|
|
102
|
+
|
|
103
|
+
TOTAL=$(echo "$SEARCH_OUTPUT" | jq -r '.count // 0' 2>/dev/null)
|
|
104
|
+
[[ "$TOTAL" == "0" ]] && exit 0
|
|
105
|
+
|
|
106
|
+
echo "$NOW" > "$RATE_FILE" 2>/dev/null || true
|
|
107
|
+
|
|
108
|
+
CONTEXT="XRAY: Pattern '\${SEARCH_TERM}' matches \${TOTAL} indexed symbol(s).\\n"
|
|
109
|
+
|
|
110
|
+
echo "$SEARCH_OUTPUT" | jq -r '.results[] | " \\(.name) (\\(.file):\\(.line))"' 2>/dev/null | while IFS= read -r line; do
|
|
111
|
+
CONTEXT="\${CONTEXT}\${line}\\n"
|
|
112
|
+
done
|
|
113
|
+
|
|
114
|
+
TOP_SYMBOL=$(echo "$SEARCH_OUTPUT" | jq -r '.results[0].name // empty' 2>/dev/null)
|
|
115
|
+
if [[ -n "$TOP_SYMBOL" ]]; then
|
|
116
|
+
USES_OUTPUT=$(curl "\${CURL_ARGS[@]}" "\${XRAY_SERVER}/api/v1/who-uses?symbol=\${TOP_SYMBOL}&limit=3" 2>/dev/null) || true
|
|
117
|
+
if [[ -n "$USES_OUTPUT" ]]; then
|
|
118
|
+
USES_COUNT=$(echo "$USES_OUTPUT" | jq -r '.count // 0' 2>/dev/null)
|
|
119
|
+
if [[ "$USES_COUNT" != "0" ]]; then
|
|
120
|
+
CONTEXT="\${CONTEXT}Top symbol '\${TOP_SYMBOL}' has \${USES_COUNT} cross-references.\\n"
|
|
121
|
+
echo "$USES_OUTPUT" | jq -r '.hits[:3][] | " [\\(if .is_heuristic then "heuristic" else "exact" end)] \\(.source_file):\\(.source_line)"' 2>/dev/null | while IFS= read -r line; do
|
|
122
|
+
CONTEXT="\${CONTEXT}\${line}\\n"
|
|
123
|
+
done
|
|
124
|
+
CONTEXT="\${CONTEXT}Run: npx xray-code who-uses \${TOP_SYMBOL} | npx xray-code impact \${TOP_SYMBOL}"
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
ESCAPED_CONTEXT=$(printf '%s' "$CONTEXT" | jq -Rs '.')
|
|
130
|
+
|
|
131
|
+
cat << EOF
|
|
132
|
+
{
|
|
133
|
+
"hookSpecificOutput": {
|
|
134
|
+
"hookEventName": "PreToolUse",
|
|
135
|
+
"additionalContext": $ESCAPED_CONTEXT
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
EOF
|
|
139
|
+
`;
|
|
140
|
+
function claudeMdSection(space, symbols, refs) {
|
|
141
|
+
return `## Code Intelligence (XRay)
|
|
142
|
+
|
|
143
|
+
This project has a code intelligence index at \`xray.proven.dev\`.
|
|
144
|
+
${symbols.toLocaleString()} symbols and ${refs.toLocaleString()} cross-references indexed, updated on every push.
|
|
145
|
+
|
|
146
|
+
### Commands
|
|
147
|
+
\`\`\`bash
|
|
148
|
+
npx xray-code search <query> # Fuzzy search for symbols by name
|
|
149
|
+
npx xray-code who-uses <symbol> # Find all usages of a symbol
|
|
150
|
+
npx xray-code impact <symbol> # What breaks if I change this?
|
|
151
|
+
npx xray-code symbols-in <file> # List symbols defined in a file
|
|
152
|
+
npx xray-code health # Check index status
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
All commands support \`--json\` for machine-readable output.
|
|
156
|
+
|
|
157
|
+
### Ambient Intelligence (Automatic)
|
|
158
|
+
|
|
159
|
+
A hook automatically queries XRay when you search with Grep or Glob.
|
|
160
|
+
You don't need to call xray-code explicitly — it enriches your searches automatically.
|
|
161
|
+
|
|
162
|
+
### Rules
|
|
163
|
+
- XRay data is **exact** — never approximate or infer on top of it
|
|
164
|
+
- Always check \`impact\` before refactoring shared symbols
|
|
165
|
+
- The index auto-rebuilds on every push to main (webhook)
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
function memoryContent(server) {
|
|
169
|
+
return `---
|
|
170
|
+
name: xray-code-intelligence
|
|
171
|
+
description: XRay code intelligence at ${server} — symbol search, cross-references, impact analysis
|
|
172
|
+
type: reference
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## XRay Code Intelligence
|
|
176
|
+
|
|
177
|
+
- **URL:** ${server}
|
|
178
|
+
- **What:** Code intelligence index — instant cross-references across the entire codebase
|
|
179
|
+
- **Commands:** npx xray-code search, who-uses, impact, symbols-in, health
|
|
180
|
+
- **Hook:** .claude/hooks/xray-inject.sh auto-injects context on Grep/Glob
|
|
181
|
+
- **Updated:** Index refreshes automatically when code is pushed to GitHub
|
|
182
|
+
- **Note:** All commands support --json flag for structured output
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
function installClaude(projectDir, server, apiKey, space, symbols, refs) {
|
|
186
|
+
const claudeDir = (0, node_path_1.join)(projectDir, ".claude");
|
|
187
|
+
const hooksDir = (0, node_path_1.join)(claudeDir, "hooks");
|
|
188
|
+
const memoryDir = (0, node_path_1.join)(claudeDir, "memory");
|
|
189
|
+
const settingsPath = (0, node_path_1.join)(claudeDir, "settings.json");
|
|
190
|
+
const claudeMdPath = (0, node_path_1.join)(projectDir, "CLAUDE.md");
|
|
191
|
+
const hookPath = (0, node_path_1.join)(hooksDir, "xray-inject.sh");
|
|
192
|
+
const memoryPath = (0, node_path_1.join)(memoryDir, "xray.md");
|
|
193
|
+
(0, node_fs_1.mkdirSync)(hooksDir, { recursive: true });
|
|
194
|
+
(0, node_fs_1.mkdirSync)(memoryDir, { recursive: true });
|
|
195
|
+
// 1. Write hook script
|
|
196
|
+
const hookContent = HOOK_SCRIPT
|
|
197
|
+
.replace("__XRAY_SERVER__", server)
|
|
198
|
+
.replace("__XRAY_KEY__", apiKey);
|
|
199
|
+
(0, node_fs_1.writeFileSync)(hookPath, hookContent, { mode: 0o755 });
|
|
200
|
+
console.log(` Created: ${hookPath}`);
|
|
201
|
+
// 2. Update .claude/settings.json
|
|
202
|
+
let settings = {};
|
|
203
|
+
if ((0, node_fs_1.existsSync)(settingsPath)) {
|
|
204
|
+
try {
|
|
205
|
+
settings = JSON.parse((0, node_fs_1.readFileSync)(settingsPath, "utf-8"));
|
|
206
|
+
}
|
|
207
|
+
catch { /* start fresh */ }
|
|
208
|
+
}
|
|
209
|
+
if (!settings.hooks || typeof settings.hooks !== "object" || Array.isArray(settings.hooks)) {
|
|
210
|
+
settings.hooks = {};
|
|
211
|
+
}
|
|
212
|
+
const hooks = settings.hooks;
|
|
213
|
+
const preToolUse = hooks.PreToolUse || [];
|
|
214
|
+
const hookExists = preToolUse.some((group) => {
|
|
215
|
+
const groupHooks = group.hooks;
|
|
216
|
+
return groupHooks?.some((h) => h.command && String(h.command).includes("xray-inject"));
|
|
217
|
+
});
|
|
218
|
+
if (!hookExists) {
|
|
219
|
+
preToolUse.push({
|
|
220
|
+
matcher: "Grep|Glob",
|
|
221
|
+
hooks: [
|
|
222
|
+
{
|
|
223
|
+
type: "command",
|
|
224
|
+
command: hookPath,
|
|
225
|
+
timeout: 5000,
|
|
226
|
+
statusMessage: "XRay: injecting code intelligence...",
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
});
|
|
230
|
+
hooks.PreToolUse = preToolUse;
|
|
231
|
+
(0, node_fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
232
|
+
console.log(` Updated: ${settingsPath}`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
console.log(` Skipped: ${settingsPath} (hook already installed)`);
|
|
236
|
+
}
|
|
237
|
+
// 3. Update CLAUDE.md
|
|
238
|
+
const SECTION_START = "<!-- XRAY_START -->";
|
|
239
|
+
const SECTION_END = "<!-- XRAY_END -->";
|
|
240
|
+
const section = claudeMdSection(space, symbols, refs);
|
|
241
|
+
const wrappedSection = `${SECTION_START}\n${section}\n${SECTION_END}`;
|
|
242
|
+
if ((0, node_fs_1.existsSync)(claudeMdPath)) {
|
|
243
|
+
let existing = (0, node_fs_1.readFileSync)(claudeMdPath, "utf-8");
|
|
244
|
+
if (existing.includes(SECTION_START)) {
|
|
245
|
+
const startIdx = existing.indexOf(SECTION_START);
|
|
246
|
+
const endIdx = existing.indexOf(SECTION_END);
|
|
247
|
+
if (endIdx > startIdx) {
|
|
248
|
+
existing = existing.slice(0, startIdx) + wrappedSection + existing.slice(endIdx + SECTION_END.length);
|
|
249
|
+
(0, node_fs_1.writeFileSync)(claudeMdPath, existing);
|
|
250
|
+
console.log(` Updated: ${claudeMdPath} (replaced XRay section)`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
(0, node_fs_1.writeFileSync)(claudeMdPath, existing + "\n" + wrappedSection);
|
|
255
|
+
console.log(` Updated: ${claudeMdPath} (appended XRay section)`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
(0, node_fs_1.writeFileSync)(claudeMdPath, `# Project Instructions\n\n${wrappedSection}`);
|
|
260
|
+
console.log(` Created: ${claudeMdPath}`);
|
|
261
|
+
}
|
|
262
|
+
// 4. Write memory file
|
|
263
|
+
(0, node_fs_1.writeFileSync)(memoryPath, memoryContent(server));
|
|
264
|
+
console.log(` Created: ${memoryPath}`);
|
|
265
|
+
}
|
package/dist/onboard.js
CHANGED
|
@@ -106,7 +106,7 @@ async function onboard(repoFilter) {
|
|
|
106
106
|
console.log(`\n Selected: ${repo.full_name}\n`);
|
|
107
107
|
// ─── Step 2: Clone ────────────────────────────────────────────
|
|
108
108
|
const repoName = (0, node_path_1.basename)(repo.full_name);
|
|
109
|
-
const cloneDir = (0, node_path_1.join)((0, node_os_1.homedir)(), "Code", repoName);
|
|
109
|
+
const cloneDir = (0, node_path_1.join)((0, node_os_1.homedir)(), "Code", "xray-tenants", repoName);
|
|
110
110
|
if ((0, node_fs_1.existsSync)(cloneDir)) {
|
|
111
111
|
console.log(` Repo already exists at ${cloneDir} — pulling latest...`);
|
|
112
112
|
try {
|