@latentforce/shift 1.0.11 → 1.0.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 CHANGED
@@ -10,71 +10,45 @@ Shift indexes your codebase, builds a dependency relationship graph (DRG), and p
10
10
  npm install -g @latentforce/shift
11
11
  ```
12
12
 
13
- Requires Node.js >= 18.
13
+ ## Getting an API Key
14
14
 
15
- ## Quick Start
15
+ 1. Go to **https://dev-shift-lite.latentforce.ai/auth**
16
+ 2. **Sign up** for an account
17
+ 3. **Sign in** to your dashboard
18
+ 4. Copy your **API key** from the dashboard
16
19
 
17
- ### Guest mode (zero-config)
20
+ From the dashboard you can also **create a project** and **select a migration template** — or you can do both directly from the CLI (see below).
18
21
 
19
- ```bash
20
- cd /path/to/your/project
21
- shift-cli init --guest # Auto-creates guest key + project, scans, and indexes
22
- ```
22
+ ## Quick Start
23
23
 
24
- ### With an API key
24
+ All commands **must be run** from your project's root directory:
25
25
 
26
26
  ```bash
27
- # Create a new project and index it (prompts for template selection)
28
- shift-cli init --api-key YOUR_KEY --project-name "My App"
29
-
30
- # Fully non-interactive (CI/CD friendly)
31
- shift-cli init --api-key YOUR_KEY --project-name "My App" --template TEMPLATE_ID
27
+ cd /path/to/your/project
32
28
  ```
33
29
 
34
- ### Interactive (original behavior)
30
+ ### Option A: Interactive (recommended)
35
31
 
36
32
  ```bash
37
- shift-cli start # Configure API key and project interactively
38
- shift-cli init # Index project files
33
+ shift-cli start # Step 1: Configure API key and project, launch daemon
34
+ shift-cli init # Step 2: Scan and index project files
35
+ shift-cli status # Step 3: Verify everything is connected
39
36
  ```
40
37
 
41
- ## MCP Integration
38
+ When you run `shift-cli start` interactively, it will:
39
+ 1. **Ask for your API key** — paste the key from your dashboard (or choose guest mode)
40
+ 2. **Ask to create or select a project** — you can either:
41
+ - **Select an existing project** from your account (if you created one on the dashboard)
42
+ - **Create a new project** from the CLI — it will prompt for a name (defaults to your directory name) and let you select a migration template
42
43
 
43
- After initializing your project, use `shift-cli add` to configure Shift's MCP server in your AI coding tool:
44
+ ### Option B: Non-interactive (CI/CD friendly)
44
45
 
45
46
  ```bash
46
- shift-cli add <tool>
47
+ shift-cli init --api-key YOUR_KEY --project-name "My App"
47
48
  ```
48
49
 
49
- ### Supported tools
50
-
51
- | Tool | Command | Config method |
52
- |------|---------|---------------|
53
- | Claude Code | `shift-cli add claude-code` | Runs `claude mcp add-json` |
54
- | Opencode | `shift-cli add opencode` | Writes `opencode.json` |
55
- | Codex | `shift-cli add codex` | Runs `codex mcp add` |
56
- | GitHub Copilot | `shift-cli add copilot` | Writes `.vscode/mcp.json` |
57
- | Factory Droid | `shift-cli add droid` | Runs `droid mcp add` |
58
-
59
- For CLI-based tools, if the CLI is not installed, the command will print manual setup instructions.
60
-
61
- ### Claude Desktop (manual)
50
+ If a project named "My App" already exists in your account, it will be reused. Otherwise a new one is created with the specified template.
62
51
 
63
- Add to your config file (`%APPDATA%\Claude\claude_desktop_config.json` on Windows, `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
64
-
65
- ```json
66
- {
67
- "mcpServers": {
68
- "shift": {
69
- "command": "shift-cli",
70
- "args": ["mcp"],
71
- "env": {
72
- "SHIFT_PROJECT_ID": "YOUR_PROJECT_ID"
73
- }
74
- }
75
- }
76
- }
77
- ```
78
52
 
79
53
  ## CLI Commands
80
54
 
@@ -82,12 +56,39 @@ Add to your config file (`%APPDATA%\Claude\claude_desktop_config.json` on Window
82
56
  |---------|-------------|
83
57
  | `shift-cli start` | Start the daemon and configure the project |
84
58
  | `shift-cli init` | Scan and index project files |
59
+ | `shift-cli status` | Show current status |
85
60
  | `shift-cli update-drg` | Update the dependency relationship graph |
86
- | `shift-cli add <tool>` | Add Shift MCP server to an AI coding tool |
87
61
  | `shift-cli stop` | Stop the daemon |
88
- | `shift-cli status` | Show current status |
62
+ | `shift-cli add <tool>` | Add Shift MCP server to an AI coding tool |
89
63
  | `shift-cli config` | Manage configuration |
90
64
 
65
+ ### `shift-cli start`
66
+
67
+ Resolves authentication, configures the project, and launches a background daemon that maintains a WebSocket connection to the Shift backend.
68
+
69
+ **When run interactively (no flags):**
70
+ 1. Prompts you to enter your API key or choose guest mode
71
+ 2. Prompts you to **select an existing project** or **create a new one**
72
+ - If creating: asks for a project name and lets you pick a migration template
73
+ 3. Saves config to `.shift/config.json`
74
+ 4. Launches the background daemon
75
+
76
+ If you already created a project on the dashboard (https://dev-shift-lite.latentforce.ai), you can select it from the list. Otherwise, create one directly from the CLI.
77
+
78
+ | Flag | Description |
79
+ |------|-------------|
80
+ | `--guest` | Use guest authentication (auto-creates a temporary project) |
81
+ | `--api-key <key>` | Provide API key directly (skips the key prompt) |
82
+ | `--project-name <name>` | Create new project or match existing by name (skips project prompt) |
83
+ | `--project-id <id>` | Use existing project UUID (skips project prompt) |
84
+ | `--template <id>` | Migration template ID for project creation |
85
+
86
+ ```bash
87
+ shift-cli start # Interactive setup (prompts for key + project)
88
+ shift-cli start --guest # Quick start without API key
89
+ shift-cli start --api-key <key> --project-name "My App" # Non-interactive
90
+ ```
91
+
91
92
  ### `shift-cli init`
92
93
 
93
94
  Performs a full project scan — collects the file tree, categorizes files (source, config, assets), gathers git info, and sends everything to the Shift backend for indexing. Automatically starts the daemon if not running.
@@ -106,30 +107,28 @@ If the project is already indexed, you will be prompted to re-index. Use `--forc
106
107
  ```bash
107
108
  shift-cli init # Interactive initialization
108
109
  shift-cli init --force # Force re-index without prompt
109
- shift-cli init --guest # Quick init with guest auth
110
110
  ```
111
111
 
112
- ### `shift-cli start`
112
+ ### `shift-cli status`
113
113
 
114
- Resolves authentication, configures the project, and launches a background daemon that maintains a WebSocket connection to the Shift backend.
115
-
116
- | Flag | Description |
117
- |------|-------------|
118
- | `--guest` | Use guest authentication (auto-creates a temporary project) |
119
- | `--api-key <key>` | Provide API key directly |
120
- | `--project-name <name>` | Create new project or match existing by name |
121
- | `--project-id <id>` | Use existing project UUID |
122
- | `--template <id>` | Migration template ID for project creation |
114
+ Displays comprehensive information about the current Shift setup API key status, project details, backend indexing state, and daemon health.
123
115
 
124
116
  ```bash
125
- shift-cli start # Interactive setup
126
- shift-cli start --guest # Quick start without API key
127
- shift-cli start --api-key <key> --project-name "My App"
117
+ shift-cli status
128
118
  ```
129
119
 
130
120
  ### `shift-cli update-drg`
131
121
 
132
- Scans JavaScript/TypeScript files (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`), detects git changes, and sends file contents to the backend for dependency analysis.
122
+ Scans source files across all supported languages, detects git changes, and sends file contents to the backend for dependency analysis.
123
+
124
+ **Supported languages and extensions:**
125
+
126
+ | Language | Extensions |
127
+ |----------|------------|
128
+ | JavaScript / TypeScript | `.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs` |
129
+ | Python | `.py` |
130
+ | C# | `.cs` |
131
+ | C/C++ | `.cpp`, `.cc`, `.cxx`, `.h`, `.hpp`, `.c` |
133
132
 
134
133
  | Flag | Description |
135
134
  |------|-------------|
@@ -137,23 +136,19 @@ Scans JavaScript/TypeScript files (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`)
137
136
 
138
137
  **Modes:**
139
138
  - **incremental** (default) — sends only git-changed files for faster updates
140
- - **baseline** — sends all JS/TS files for a full re-analysis
139
+ - **baseline** — sends all source files for a full re-analysis
141
140
 
142
141
  ```bash
143
142
  shift-cli update-drg # Incremental update (default)
144
143
  shift-cli update-drg -m baseline # Full re-analysis
145
144
  ```
146
145
 
147
- ### `shift-cli add <tool>`
146
+ ### `shift-cli stop`
148
147
 
149
- Configures Shift's MCP server in the specified AI coding tool. Reads `project_id` from `.shift/config.json` (run `shift-cli init` first).
148
+ Stops the background daemon process.
150
149
 
151
150
  ```bash
152
- shift-cli add claude-code # Configure via Claude Code CLI
153
- shift-cli add opencode # Write to opencode.json
154
- shift-cli add codex # Configure via Codex CLI
155
- shift-cli add copilot # Write to .vscode/mcp.json
156
- shift-cli add droid # Configure via Droid CLI
151
+ shift-cli stop
157
152
  ```
158
153
 
159
154
  ### `shift-cli config`
@@ -166,92 +161,141 @@ Manage Shift configuration (URLs, API key).
166
161
  | `set <key> <value>` | Set a configuration value |
167
162
  | `clear [key]` | Clear a specific key or all configuration |
168
163
 
169
- **Configurable keys:** `api-key`, `api-url`, `orch-url`, `ws-url`
170
-
171
- URLs can also be set via environment variables: `SHIFT_API_URL`, `SHIFT_ORCH_URL`, `SHIFT_WS_URL`.
164
+ **Configurable key:** `api-key`
172
165
 
173
166
  ```bash
174
167
  shift-cli config # Show config
175
168
  shift-cli config set api-key sk-abc123 # Set API key
176
- shift-cli config set api-url https://api.shift.ai # Set API URL
177
169
  shift-cli config clear api-key # Clear API key
178
170
  shift-cli config clear # Clear all config
179
171
  ```
172
+ ## MCP Integration
180
173
 
181
- ## `.shiftignore`
174
+ After initializing your project, use `shift-cli add` to configure Shift's MCP server in your AI coding tool:
182
175
 
183
- Shift uses a `.shiftignore` file to control which files and directories are excluded from indexing and dependency analysis. It follows the same syntax as `.gitignore`.
176
+ ```bash
177
+ shift-cli add <tool>
178
+ ```
184
179
 
185
- A default `.shiftignore` is **automatically created** the first time you run `shift-cli init` or `shift-cli start`. You can edit it to customize which files are excluded.
180
+ ### Supported tools
186
181
 
187
- ### Syntax
182
+ | Tool | Command | Config method |
183
+ |------|---------|---------------|
184
+ | Claude Code | `shift-cli add claude-code` | Runs `claude mcp add-json` |
185
+ | Opencode | `shift-cli add opencode` | Writes `opencode.json` |
186
+ | Codex | `shift-cli add codex` | Runs `codex mcp add` |
187
+ | GitHub Copilot | `shift-cli add copilot` | Writes `.vscode/mcp.json` |
188
+ | Factory Droid | `shift-cli add droid` | Runs `droid mcp add` |
188
189
 
189
- - Blank lines are ignored
190
- - Lines starting with `#` are comments
191
- - Standard glob patterns (`*`, `**`, `?`)
192
- - Trailing `/` matches directories only
193
- - Leading `/` anchors to the project root
194
- - `!` negates a pattern (re-includes a previously ignored path)
190
+ For CLI-based tools, if the CLI is not installed, the command will print manual setup instructions.
195
191
 
196
- ### Default `.shiftignore`
192
+ ### Claude Desktop (manual)
197
193
 
198
- The auto-generated file excludes common non-source directories and files:
194
+ Add to your config file (`%APPDATA%\Claude\claude_desktop_config.json` on Windows, `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
199
195
 
200
- ```gitignore
201
- # Dependencies
202
- node_modules/
203
- vendor/
204
- bower_components/
196
+ ```json
197
+ {
198
+ "mcpServers": {
199
+ "shift": {
200
+ "command": "shift-cli",
201
+ "args": ["mcp"],
202
+ "env": {
203
+ "SHIFT_PROJECT_ID": "YOUR_PROJECT_ID"
204
+ }
205
+ }
206
+ }
207
+ }
208
+ ```
209
+ ## `.shift/scan_target.json`
210
+
211
+ Shift uses a `scan_target.json` file inside the `.shift/` directory to let you specify which parts of your codebase to scan and in which language. This is especially useful for monorepos or projects with multiple languages.
205
212
 
206
- # Build output
207
- dist/
208
- build/
209
- out/
210
- .next/
213
+ A default template is **automatically created** the first time you run `shift-cli init` or `shift-cli start`. By default, it is unconfigured and the server will auto-detect scan targets. Edit the file to manually specify targets.
211
214
 
212
- # Test & coverage
213
- coverage/
214
- .nyc_output/
215
+ ### Valid Languages
215
216
 
216
- # Environment & secrets
217
- .env
218
- .env.*
219
- *.pem
220
- *.key
217
+ ```
218
+ javascript, typescript, python, cpp, csharp
219
+ ```
221
220
 
222
- # Logs
223
- *.log
224
- logs/
221
+ ### Format
225
222
 
226
- # OS files
227
- .DS_Store
228
- Thumbs.db
223
+ The file is a JSON array of objects, each with:
229
224
 
230
- # IDE
231
- .vscode/
232
- .idea/
233
- *.swp
234
- *.swo
225
+ | Field | Type | Description |
226
+ |-------|------|-------------|
227
+ | `language` | `string \| null` | One of the valid languages above, or `null` for auto-detect |
228
+ | `path` | `string` | Relative path from project root (empty string `""` for root) |
235
229
 
236
- # Python
237
- __pycache__/
238
- *.pyc
239
- venv/
240
- .venv/
230
+ ### Default Template (auto-generated)
241
231
 
242
- # Misc
243
- *.min.js
244
- *.min.css
245
- *.map
232
+ ```json
233
+ [
234
+ {
235
+ "language": null,
236
+ "path": ""
237
+ }
238
+ ]
246
239
  ```
247
240
 
248
- ### Bypassing `.shiftignore`
241
+ When left as-is (single entry with `language: null` and `path: ""`), the server auto-detects scan targets.
249
242
 
250
- Use the `--no-ignore` flag to skip `.shiftignore` rules for a single run:
243
+ ### Examples
251
244
 
252
- ```bash
253
- shift-cli init --no-ignore # Index all files
254
- shift-cli update-drg --no-ignore # Include ignored files in DRG update
245
+ **Single-language project (TypeScript at root):**
246
+
247
+ ```json
248
+ [
249
+ {
250
+ "language": "typescript",
251
+ "path": ""
252
+ }
253
+ ]
254
+ ```
255
+
256
+ **Monorepo with multiple languages:**
257
+
258
+ ```json
259
+ [
260
+ {
261
+ "language": "typescript",
262
+ "path": "frontend"
263
+ },
264
+ {
265
+ "language": "python",
266
+ "path": "backend"
267
+ },
268
+ {
269
+ "language": "csharp",
270
+ "path": "services/auth"
271
+ }
272
+ ]
273
+ ```
274
+
275
+ **C++ project in a subdirectory:**
276
+
277
+ ```json
278
+ [
279
+ {
280
+ "language": "cpp",
281
+ "path": "engine/src"
282
+ }
283
+ ]
284
+ ```
285
+
286
+ **Mixed JavaScript and Python at root:**
287
+
288
+ ```json
289
+ [
290
+ {
291
+ "language": "javascript",
292
+ "path": ""
293
+ },
294
+ {
295
+ "language": "python",
296
+ "path": ""
297
+ }
298
+ ]
255
299
  ```
256
300
 
257
301
  ## MCP Tools
@@ -270,4 +314,4 @@ Each tool accepts an optional `project_id` parameter. If not provided, it falls
270
314
  |------|----------|-------------|
271
315
  | Global config | `~/.shift/config.json` | API key and server URLs |
272
316
  | Project config | `.shift/config.json` | Project ID, name, and agent info |
273
- | Ignore rules | `.shiftignore` | Files/directories to exclude (auto-created) |
317
+ | Scan targets | `.shift/scan_target.json` | Language and path targets for scanning (auto-created) |
@@ -26,7 +26,119 @@ function getMcpConfig(projectId) {
26
26
  env: { SHIFT_PROJECT_ID: projectId },
27
27
  };
28
28
  }
29
- async function addClaudeCode(projectId) {
29
+ const CLAUDE_MD_SECTION_MARKER = '<!-- shift-mcp-instructions -->';
30
+ const CLAUDE_MD_CONTENT = `${CLAUDE_MD_SECTION_MARKER}
31
+ ## Shift MCP Tools — MANDATORY USAGE RULES
32
+
33
+ This project has the **Shift MCP server** (\`shift\`) configured with a pre-built knowledge graph of the entire codebase. You MUST use its tools as the primary way to understand code. Do NOT rely solely on reading raw files.
34
+
35
+ ### Tools
36
+
37
+ | Tool | Purpose |
38
+ |------|---------|
39
+ | \`file_summary\` | Get an summary of any file |
40
+ | \`dependencies\` | List every file that a given file imports/depends on |
41
+ | \`blast_radius\` | List every file that would be affected if a given file changed |
42
+
43
+ ### Supported file types
44
+
45
+ The knowledge graph is built **only** from source files. The tools will return an error for any other file type.
46
+
47
+ **Indexed (use MCP tools):**
48
+ \`.js\` \`.jsx\` \`.ts\` \`.tsx\` \`.py\` \`.java\` \`.cpp\` \`.cs\` \`.go\` \`.c\` \`.h\` \`.css\` \`.scss\` \`.html\`
49
+
50
+ **NOT indexed (read directly with normal file tools):**
51
+ \`.json\` \`.yaml\` \`.yml\` \`.toml\` \`.env\` \`.md\` \`.txt\` \`.pdf\` \`.png\` \`.lock\` \`.xml\` \`.csv\` and any other non-source format.
52
+
53
+ Do NOT call \`file_summary\`, \`dependencies\`, or \`blast_radius\` on non-indexed files — it will fail. Read those files directly instead.
54
+
55
+ ---
56
+
57
+ ### RULE 1 — Codebase exploration (e.g. "explain the codebase", "how does this project work")
58
+
59
+ You MUST call \`file_summary\` on **multiple key files** to build a complete picture. Do not stop after one call.
60
+
61
+ Follow this protocol:
62
+ 1. Identify the likely entry points (e.g. \`main.ts\`, \`index.ts\`, \`app.py\`, \`server.ts\`, \`main.py\`, route files, CLI entry files).
63
+ 2. Call \`file_summary\` on each entry point (run calls in parallel where possible).
64
+ 3. Call \`dependencies\` on the most central files to discover the module graph.
65
+ 4. Call \`file_summary\` on the key modules discovered in step 3.
66
+ 5. Synthesise all results into a coherent explanation.
67
+
68
+ Never answer a "explain the whole project" question from a single \`file_summary\` call.
69
+
70
+ ---
71
+
72
+ ### RULE 2 — Before reading any file
73
+
74
+ ALWAYS call \`file_summary\` first. Only open the raw file if you need implementation details that the summary does not cover.
75
+
76
+ ---
77
+
78
+ ### RULE 3 — Before editing any file
79
+
80
+ ALWAYS call \`blast_radius\` on that file first. List the affected files in your plan before making any changes.
81
+
82
+ ---
83
+
84
+ ### RULE 4 — When tracing a bug or data flow
85
+
86
+ Use \`dependencies\` to follow the chain rather than grepping manually. Start from the file where the symptom appears and walk the dependency graph.
87
+
88
+ ---
89
+
90
+ ### Usage reference
91
+
92
+ \`\`\`
93
+ # Understand a file
94
+ file_summary(file_path="src/server.ts")
95
+
96
+ # Understand with folder context (level = number of parent dirs to include)
97
+ file_summary(file_path="src/server.ts", level=1)
98
+
99
+ # See what a file imports
100
+ dependencies(file_path="src/server.ts")
101
+
102
+ # See what breaks if this file changes
103
+ blast_radius(file_path="src/server.ts")
104
+ \`\`\`
105
+
106
+ > Run \`shift-cli update-drg\` after significant code changes to keep the knowledge graph current.
107
+ <!-- end-shift-mcp-instructions -->
108
+ `;
109
+ const CLAUDE_MD_END_MARKER = '<!-- end-shift-mcp-instructions -->';
110
+ function createClaudeMd(projectRoot) {
111
+ const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
112
+ if (fs.existsSync(claudeMdPath)) {
113
+ const existing = fs.readFileSync(claudeMdPath, 'utf-8');
114
+ if (existing.includes(CLAUDE_MD_SECTION_MARKER)) {
115
+ // Replace the existing section (start marker to end marker inclusive)
116
+ const start = existing.indexOf(CLAUDE_MD_SECTION_MARKER);
117
+ const end = existing.indexOf(CLAUDE_MD_END_MARKER);
118
+ if (end !== -1) {
119
+ const before = existing.slice(0, start).trimEnd();
120
+ const after = existing.slice(end + CLAUDE_MD_END_MARKER.length).trimStart();
121
+ const updated = (before ? before + '\n\n' : '') + CLAUDE_MD_CONTENT + (after ? '\n\n' + after : '');
122
+ fs.writeFileSync(claudeMdPath, updated);
123
+ }
124
+ else {
125
+ // Malformed — just overwrite from the marker onwards
126
+ const before = existing.slice(0, existing.indexOf(CLAUDE_MD_SECTION_MARKER)).trimEnd();
127
+ fs.writeFileSync(claudeMdPath, (before ? before + '\n\n' : '') + CLAUDE_MD_CONTENT);
128
+ }
129
+ console.log(' Updated Shift MCP instructions in CLAUDE.md.');
130
+ return;
131
+ }
132
+ // Append section to existing file
133
+ fs.writeFileSync(claudeMdPath, existing.trimEnd() + '\n\n' + CLAUDE_MD_CONTENT);
134
+ console.log(' Updated CLAUDE.md with Shift MCP instructions.');
135
+ }
136
+ else {
137
+ fs.writeFileSync(claudeMdPath, CLAUDE_MD_CONTENT);
138
+ console.log(' Created CLAUDE.md with Shift MCP instructions.');
139
+ }
140
+ }
141
+ async function addClaudeCode(projectId, projectRoot) {
30
142
  const jsonPayload = JSON.stringify({
31
143
  type: 'stdio',
32
144
  command: 'shift-cli',
@@ -55,6 +167,7 @@ async function addClaudeCode(projectId) {
55
167
  console.log(` claude mcp add-json shift '${jsonPayload}'`);
56
168
  }
57
169
  }
170
+ createClaudeMd(projectRoot);
58
171
  }
59
172
  async function addCodex(projectId) {
60
173
  const config = getMcpConfig(projectId);
@@ -190,7 +303,7 @@ export async function addCommand(tool) {
190
303
  console.log(`\n Configuring Shift MCP for ${tool}...\n`);
191
304
  switch (tool) {
192
305
  case 'claude-code':
193
- await addClaudeCode(projectId);
306
+ await addClaudeCode(projectId, projectRoot);
194
307
  break;
195
308
  case 'opencode':
196
309
  addOpencode(projectId, projectRoot);
@@ -13,7 +13,7 @@ export async function configCommand(action, key, value) {
13
13
  await clearConfig(key);
14
14
  break;
15
15
  default:
16
- console.log('Usage: shift config [show|set|clear] [key] [value]');
16
+ console.log('Usage: shift-cli config [show|set|clear] [key] [value]');
17
17
  console.log('');
18
18
  console.log('Commands:');
19
19
  console.log(' show Show current configuration');
@@ -22,16 +22,16 @@ export async function configCommand(action, key, value) {
22
22
  console.log('');
23
23
  console.log('Keys:');
24
24
  console.log(' api-key Your Shift API key');
25
- console.log(' api-url SHIFT_API_URL (default: http://localhost:9000)');
26
- console.log(' orch-url SHIFT_ORCH_URL (default: http://localhost:9999)');
27
- console.log(' ws-url SHIFT_WS_URL (default: ws://localhost:9999)');
25
+ console.log(' api-url SHIFT_API_URL');
26
+ console.log(' orch-url SHIFT_ORCH_URL');
27
+ console.log(' ws-url SHIFT_WS_URL');
28
28
  console.log('');
29
29
  console.log('Examples:');
30
- console.log(' shift config');
31
- console.log(' shift config set api-url https://api.latentforce.ai');
32
- console.log(' shift config set orch-url https://orch.latentforce.ai');
33
- console.log(' shift config set ws-url wss://ws.latentforce.ai');
34
- console.log(' shift config clear urls');
30
+ console.log(' shift-cli config');
31
+ console.log(' shift-cli config set api-url http://localhost:9000');
32
+ console.log(' shift-cli config set orch-url http://localhost:9999');
33
+ console.log(' shift-cli config set ws-url ws://localhost:9999');
34
+ console.log(' shift-cli config clear urls');
35
35
  break;
36
36
  }
37
37
  }
@@ -66,7 +66,13 @@ function showConfig() {
66
66
  }
67
67
  async function setConfigValue(key, value) {
68
68
  if (!key) {
69
- console.error('Error: Key is required. Run "shift config" to see available keys.');
69
+ console.error('Error: Key is required. Run "shift-cli config" to see available keys.');
70
+ process.exit(1);
71
+ }
72
+ const validKeys = ['api-key', 'api-url', 'orch-url', 'ws-url'];
73
+ if (!validKeys.includes(key)) {
74
+ console.error(`Unknown key: ${key}`);
75
+ console.log(`Available keys: ${validKeys.join(', ')}`);
70
76
  process.exit(1);
71
77
  }
72
78
  // If no value provided, prompt for it
@@ -126,7 +132,7 @@ async function clearConfig(key) {
126
132
  case 'api-url':
127
133
  case 'orch-url':
128
134
  case 'ws-url':
129
- console.log('Use "shift config clear urls" to clear all URLs');
135
+ console.log('Use "shift-cli config clear urls" to clear all URLs');
130
136
  break;
131
137
  default:
132
138
  console.error(`Unknown key: ${key}`);
@@ -226,8 +226,7 @@ export async function initCommand(options = {}) {
226
226
  try {
227
227
  const response = await sendInitScan(apiKey, project.projectId, payload);
228
228
  console.log('[Init] ✓ Backend initialization completed');
229
- console.log(`[Init] Files read: ${response.files_read}`);
230
- console.log(`[Init] Files failed: ${response.files_failed}`);
229
+ console.log(`[Init] Source files queued: ${response.source_files_count ?? response.files_read}`);
231
230
  // Update local config with agent info (matching extension)
232
231
  if (response.agents_created?.theme_planner) {
233
232
  const agentInfo = {
package/build/index.js CHANGED
@@ -137,8 +137,8 @@ const updateDrgCmd = program
137
137
  });
138
138
  updateDrgCmd.addHelpText('after', `
139
139
  Details:
140
- Scans JavaScript/TypeScript files (.js, .jsx, .ts, .tsx, .mjs, .cjs),
141
- detects git changes, and sends file contents to the backend for
140
+ Scans files, detects git changes,
141
+ and sends file contents to the backend for
142
142
  dependency analysis.
143
143
 
144
144
  Modes:
@@ -186,9 +186,9 @@ Actions:
186
186
 
187
187
  Configurable keys:
188
188
  api-key Your Shift API key
189
- api-url Backend API URL (default: http://localhost:9000)
190
- orch-url Orchestrator URL (default: http://localhost:9999)
191
- ws-url WebSocket URL (default: ws://localhost:9999)
189
+ api-url Backend API URL
190
+ orch-url Orchestrator URL
191
+ ws-url WebSocket URL
192
192
 
193
193
  URLs can also be set via environment variables:
194
194
  SHIFT_API_URL, SHIFT_ORCH_URL, SHIFT_WS_URL
@@ -196,7 +196,7 @@ URLs can also be set via environment variables:
196
196
  Examples:
197
197
  shift-cli config Show config
198
198
  shift-cli config set api-key sk-abc123 Set API key
199
- shift-cli config set api-url https://api.shift.ai Set API URL
199
+ shift-cli config set api-url http://localhost:9000 Set API URL
200
200
  shift-cli config clear api-key Clear API key
201
201
  shift-cli config clear Clear all config
202
202
  `);
@@ -2,9 +2,13 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { z } from 'zod';
4
4
  import { createRequire } from 'module';
5
+ import { getApiKey } from './utils/config.js';
5
6
  const require = createRequire(import.meta.url);
6
7
  const { version } = require('../package.json');
7
8
  const BASE_URL = process.env.SHIFT_BACKEND_URL || "https://dev-shift-lite.latentforce.ai";
9
+ function getApiKeyFromEnv() {
10
+ return process.env.SHIFT_API_KEY?.trim() || getApiKey();
11
+ }
8
12
  function getProjectIdFromEnv() {
9
13
  const projectId = process.env.SHIFT_PROJECT_ID;
10
14
  if (!projectId || projectId.trim() === "") {
@@ -30,11 +34,16 @@ function normalizePath(filePath) {
30
34
  // helper
31
35
  async function callBackendAPI(endpoint, data) {
32
36
  try {
37
+ const apiKey = getApiKeyFromEnv();
38
+ const headers = {
39
+ 'Content-Type': 'application/json',
40
+ };
41
+ if (apiKey) {
42
+ headers['Authorization'] = `Bearer ${apiKey}`;
43
+ }
33
44
  const response = await fetch(`${BASE_URL}${endpoint}`, {
34
45
  method: 'POST',
35
- headers: {
36
- 'Content-Type': 'application/json',
37
- },
46
+ headers,
38
47
  body: JSON.stringify(data),
39
48
  });
40
49
  if (!response.ok) {
@@ -144,7 +153,7 @@ export async function startMcpServer() {
144
153
  // Tools:
145
154
  // Blast radius
146
155
  server.registerTool("blast_radius", {
147
- description: "Analyzes the blast radius of a file or component - shows what would be affected if this file were modified or deleted",
156
+ description: "Use this BEFORE editing or refactoring any source file. Returns every file in the project that imports or depends on the given file, grouped by dependency depth (level 1 = direct importers, level 2 = their importers, etc.). Use this to understand the full impact of a change before making it. Only works on indexed source files: .js .jsx .ts .tsx .py .java .cpp .cs .go .c .h .css .scss .html — do not call for .json, .yaml, .md or other non-source files.",
148
157
  inputSchema: z.object({
149
158
  file_path: z.string().describe("Path to the file (relative to project root)"),
150
159
  project_id: z.string().optional().describe("Shift Lite project UUID; overrides SHIFT_PROJECT_ID if provided"),
@@ -168,7 +177,7 @@ export async function startMcpServer() {
168
177
  });
169
178
  // Dependencies
170
179
  server.registerTool("dependencies", {
171
- description: "Retrieves all dependencies for a given file or component, including direct and transitive dependencies",
180
+ description: "Returns every file that the given source file imports or depends on, along with a short summary of why each dependency is used. Use this to trace data flow, understand module relationships, follow a bug through the call chain, or map out what a file relies on before modifying it. Only works on indexed source files: .js .jsx .ts .tsx .py .java .cpp .cs .go .c .h .css .scss .html — do not call for .json, .yaml, .md or other non-source files.",
172
181
  inputSchema: z.object({
173
182
  file_path: z.string().describe("Path to the file"),
174
183
  project_id: z.string().optional().describe("Shift Lite project UUID; overrides SHIFT_PROJECT_ID if provided"),
@@ -190,7 +199,7 @@ export async function startMcpServer() {
190
199
  });
191
200
  // File summary (maps to what-is-this-file)
192
201
  server.registerTool("file_summary", {
193
- description: "Generates a comprehensive summary of a file including its purpose, exports, imports, and key functions, with optional parent directory context",
202
+ description: "Returns an AI-generated summary of a source file: what it does, its key exports and functions, its role in the project, and how it fits into the surrounding architecture. Always call this before reading a raw file — it gives you the essential context without having to parse the full source. Use the 'level' parameter to include summaries of parent directories for broader context. Only works on indexed source files: .js .jsx .ts .tsx .py .java .cpp .cs .go .c .h .css .scss .html — for .json, .yaml, .md, or other non-source files, read them directly instead.",
194
203
  inputSchema: z.object({
195
204
  file_path: z.string().describe("Path to the file to summarize"),
196
205
  project_id: z.string().optional().describe("Shift Lite project UUID; overrides SHIFT_PROJECT_ID if provided"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latentforce/shift",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Shift CLI - AI-powered code intelligence with MCP support",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",