@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 +176 -132
- package/build/cli/commands/add.js +115 -2
- package/build/cli/commands/config.js +17 -11
- package/build/cli/commands/init.js +1 -2
- package/build/index.js +6 -6
- package/build/mcp-server.js +15 -6
- package/package.json +1 -1
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
|
-
|
|
13
|
+
## Getting an API Key
|
|
14
14
|
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
+
All commands **must be run** from your project's root directory:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
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 (
|
|
30
|
+
### Option A: Interactive (recommended)
|
|
35
31
|
|
|
36
32
|
```bash
|
|
37
|
-
shift-cli start # Configure API key and project
|
|
38
|
-
shift-cli init #
|
|
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
|
-
|
|
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
|
-
|
|
44
|
+
### Option B: Non-interactive (CI/CD friendly)
|
|
44
45
|
|
|
45
46
|
```bash
|
|
46
|
-
shift-cli
|
|
47
|
+
shift-cli init --api-key YOUR_KEY --project-name "My App"
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
|
|
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
|
|
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
|
|
112
|
+
### `shift-cli status`
|
|
113
113
|
|
|
114
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
146
|
+
### `shift-cli stop`
|
|
148
147
|
|
|
149
|
-
|
|
148
|
+
Stops the background daemon process.
|
|
150
149
|
|
|
151
150
|
```bash
|
|
152
|
-
shift-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
|
|
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
|
-
|
|
174
|
+
After initializing your project, use `shift-cli add` to configure Shift's MCP server in your AI coding tool:
|
|
182
175
|
|
|
183
|
-
|
|
176
|
+
```bash
|
|
177
|
+
shift-cli add <tool>
|
|
178
|
+
```
|
|
184
179
|
|
|
185
|
-
|
|
180
|
+
### Supported tools
|
|
186
181
|
|
|
187
|
-
|
|
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
|
-
-
|
|
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
|
-
###
|
|
192
|
+
### Claude Desktop (manual)
|
|
197
193
|
|
|
198
|
-
|
|
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
|
-
```
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
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
|
-
|
|
213
|
-
coverage/
|
|
214
|
-
.nyc_output/
|
|
215
|
+
### Valid Languages
|
|
215
216
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
*.pem
|
|
220
|
-
*.key
|
|
217
|
+
```
|
|
218
|
+
javascript, typescript, python, cpp, csharp
|
|
219
|
+
```
|
|
221
220
|
|
|
222
|
-
|
|
223
|
-
*.log
|
|
224
|
-
logs/
|
|
221
|
+
### Format
|
|
225
222
|
|
|
226
|
-
|
|
227
|
-
.DS_Store
|
|
228
|
-
Thumbs.db
|
|
223
|
+
The file is a JSON array of objects, each with:
|
|
229
224
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
237
|
-
__pycache__/
|
|
238
|
-
*.pyc
|
|
239
|
-
venv/
|
|
240
|
-
.venv/
|
|
230
|
+
### Default Template (auto-generated)
|
|
241
231
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
232
|
+
```json
|
|
233
|
+
[
|
|
234
|
+
{
|
|
235
|
+
"language": null,
|
|
236
|
+
"path": ""
|
|
237
|
+
}
|
|
238
|
+
]
|
|
246
239
|
```
|
|
247
240
|
|
|
248
|
-
|
|
241
|
+
When left as-is (single entry with `language: null` and `path: ""`), the server auto-detects scan targets.
|
|
249
242
|
|
|
250
|
-
|
|
243
|
+
### Examples
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
|
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
|
-
|
|
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
|
|
26
|
-
console.log(' orch-url SHIFT_ORCH_URL
|
|
27
|
-
console.log(' ws-url SHIFT_WS_URL
|
|
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
|
|
32
|
-
console.log(' shift config set orch-url
|
|
33
|
-
console.log(' shift config set ws-url
|
|
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]
|
|
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
|
|
141
|
-
|
|
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
|
|
190
|
-
orch-url Orchestrator URL
|
|
191
|
-
ws-url WebSocket URL
|
|
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
|
|
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
|
`);
|
package/build/mcp-server.js
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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: "
|
|
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"),
|