Skip to content

Commit 46602ea

Browse files
committed
more fixes for vscode ext
1 parent f22d67b commit 46602ea

10 files changed

Lines changed: 176 additions & 1318 deletions

File tree

renamify-mcp/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ Add to your MCP client configuration (e.g., for Claude Desktop or Cursor):
4444
}
4545
```
4646

47+
### Custom Binary Path
48+
49+
If `renamify` is not in your PATH or you want to use a specific binary, set the `RENAMIFY_PATH` environment variable:
50+
51+
```json
52+
{
53+
"mcpServers": {
54+
"renamify": {
55+
"command": "npx",
56+
"args": ["-y", "@renamify/mcp-server"],
57+
"env": {
58+
"RENAMIFY_PATH": "/path/to/renamify"
59+
}
60+
}
61+
}
62+
}
63+
```
64+
4765
### Supported AI Assistants
4866

4967
- **Claude Desktop** - Anthropic's AI assistant

renamify-mcp/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,10 @@ export function createServer(
261261
}
262262

263263
export async function main() {
264-
const server = createServer();
264+
// Allow configuration via environment variable
265+
const renamifyPath = process.env.RENAMIFY_PATH;
266+
const service = renamifyPath ? new RenamifyService(renamifyPath) : undefined;
267+
const server = createServer(service);
265268
const transport = new StdioServerTransport();
266269
await server.connect(transport);
267270
// Server started successfully - MCP servers communicate via stdio

renamify-vscode/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ node_modules
44
*.vsix
55
.DS_Store
66
src/renamify-core-bindings
7+
8+
# Generated files
9+
media/bundle.js
10+
media/webview.js
11+
media/webview.js.map

renamify-vscode/extension/src/cliService.ts

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { spawn } from "node:child_process";
2-
import * as fs from "node:fs";
3-
import * as path from "node:path";
4-
import * as vscode from "vscode";
5-
import type { SearchOptions, SearchResult, Status } from "./types";
1+
import { spawn } from 'node:child_process';
2+
import * as fs from 'node:fs';
3+
import * as path from 'node:path';
4+
import * as vscode from 'vscode';
5+
import type { SearchOptions, SearchResult, Status } from './types';
66

7-
export type { SearchOptions, SearchResult } from "./types";
7+
export type { SearchOptions, SearchResult } from './types';
88

99
export class RenamifyCliService {
1010
private readonly cliPath: string;
@@ -16,23 +16,23 @@ export class RenamifyCliService {
1616
}
1717

1818
private findCliPath(): string {
19-
const config = vscode.workspace.getConfiguration("renamify");
20-
const configuredPath = config.get<string>("cliPath");
19+
const config = vscode.workspace.getConfiguration('renamify');
20+
const configuredPath = config.get<string>('cliPath');
2121

2222
if (configuredPath && fs.existsSync(configuredPath)) {
2323
return configuredPath;
2424
}
2525

2626
// Try to find in PATH
27-
const pathEnv = process.env.PATH || "";
27+
const pathEnv = process.env.PATH || '';
2828
const paths = pathEnv.split(path.delimiter);
2929

3030
for (const p of paths) {
31-
const cliPath = path.join(p, "renamify");
31+
const cliPath = path.join(p, 'renamify');
3232
if (fs.existsSync(cliPath)) {
3333
return cliPath;
3434
}
35-
const cliPathExe = path.join(p, "renamify.exe");
35+
const cliPathExe = path.join(p, 'renamify.exe');
3636
if (fs.existsSync(cliPathExe)) {
3737
return cliPathExe;
3838
}
@@ -41,158 +41,171 @@ export class RenamifyCliService {
4141
// Try local development path
4242
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
4343
if (workspaceRoot) {
44-
const devPath = path.join(workspaceRoot, "target", "debug", "renamify");
44+
const devPath = path.join(workspaceRoot, 'target', 'debug', 'renamify');
4545
if (fs.existsSync(devPath)) {
4646
return devPath;
4747
}
4848
const devPathExe = path.join(
4949
workspaceRoot,
50-
"target",
51-
"debug",
52-
"renamify.exe"
50+
'target',
51+
'debug',
52+
'renamify.exe'
5353
);
5454
if (fs.existsSync(devPathExe)) {
5555
return devPathExe;
5656
}
5757
}
5858

5959
throw new Error(
60-
"Renamify CLI not found. Please install it or configure the path in settings."
60+
'Renamify CLI not found. Please install it or configure the path in settings.'
6161
);
6262
}
6363

6464
async search(searchTerm: string, options: SearchOptions): Promise<Plan> {
65-
const args = ["search", searchTerm, "--output", "json"];
65+
const args = ['search', searchTerm, '--output', 'json'];
6666

6767
if (options.include) {
68-
args.push("--include", options.include);
68+
args.push('--include', options.include);
6969
}
7070

7171
if (options.exclude) {
72-
args.push("--exclude", options.exclude);
72+
args.push('--exclude', options.exclude);
7373
}
7474

7575
if (options.excludeMatchingLines) {
76-
args.push("--exclude-matching-lines", options.excludeMatchingLines);
76+
args.push('--exclude-matching-lines', options.excludeMatchingLines);
7777
}
7878

7979
if (options.caseStyles && options.caseStyles.length > 0) {
80-
args.push("--only-styles", options.caseStyles.join(","));
80+
args.push('--only-styles', options.caseStyles.join(','));
8181
}
8282

83-
const config = vscode.workspace.getConfiguration("renamify");
84-
if (!config.get("respectGitignore")) {
85-
args.push("-u");
83+
const config = vscode.workspace.getConfiguration('renamify');
84+
if (!config.get('respectGitignore')) {
85+
args.push('-u');
8686
}
8787

8888
const result = await this.runCli(args);
89-
return JSON.parse(result);
89+
const parsed = JSON.parse(result);
90+
// The CLI returns a wrapper object with the plan nested inside
91+
if (!parsed.plan) {
92+
throw new Error('Invalid response from CLI: missing plan data');
93+
}
94+
return parsed.plan;
9095
}
9196

9297
async createPlan(
9398
searchTerm: string,
9499
replaceTerm: string,
95100
options: SearchOptions & { dryRun?: boolean }
96101
): Promise<Plan | SearchResult[]> {
97-
const args = ["plan", searchTerm, replaceTerm, "--output", "json"];
102+
const args = ['plan', searchTerm, replaceTerm, '--output', 'json'];
98103

99104
if (options.dryRun) {
100-
args.push("--dry-run");
105+
args.push('--dry-run');
101106
}
102107

103108
if (options.include) {
104-
args.push("--include", options.include);
109+
args.push('--include', options.include);
105110
}
106111

107112
if (options.exclude) {
108-
args.push("--exclude", options.exclude);
113+
args.push('--exclude', options.exclude);
109114
}
110115

111116
if (options.excludeMatchingLines) {
112-
args.push("--exclude-matching-lines", options.excludeMatchingLines);
117+
args.push('--exclude-matching-lines', options.excludeMatchingLines);
113118
}
114119

115120
if (options.caseStyles && options.caseStyles.length > 0) {
116-
args.push("--only-styles", options.caseStyles.join(","));
121+
args.push('--only-styles', options.caseStyles.join(','));
117122
}
118123

119-
const config = vscode.workspace.getConfiguration("renamify");
120-
if (!config.get("respectGitignore")) {
121-
args.push("-u");
124+
const config = vscode.workspace.getConfiguration('renamify');
125+
if (!config.get('respectGitignore')) {
126+
args.push('-u');
122127
}
123128

124129
const result = await this.runCli(args);
125-
126-
// Always return the full Plan object, whether dry-run or not
127-
return JSON.parse(result);
130+
const parsed = JSON.parse(result);
131+
// The CLI returns a wrapper object with the plan nested inside
132+
if (!parsed.plan) {
133+
throw new Error('Invalid response from CLI: missing plan data');
134+
}
135+
return parsed.plan;
128136
}
129137

130138
async rename(
131139
searchTerm: string,
132140
replaceTerm: string,
133141
options: SearchOptions
134142
): Promise<{ planId: string }> {
135-
const args = ["rename", searchTerm, replaceTerm, "-y", "--output", "json"];
143+
const args = ['rename', searchTerm, replaceTerm, '-y', '--output', 'json'];
136144

137145
if (options.include) {
138-
args.push("--include", options.include);
146+
args.push('--include', options.include);
139147
}
140148

141149
if (options.exclude) {
142-
args.push("--exclude", options.exclude);
150+
args.push('--exclude', options.exclude);
143151
}
144152

145153
if (options.excludeMatchingLines) {
146-
args.push("--exclude-matching-lines", options.excludeMatchingLines);
154+
args.push('--exclude-matching-lines', options.excludeMatchingLines);
147155
}
148156

149157
if (options.caseStyles && options.caseStyles.length > 0) {
150-
args.push("--only-styles", options.caseStyles.join(","));
158+
args.push('--only-styles', options.caseStyles.join(','));
151159
}
152160

153-
const config = vscode.workspace.getConfiguration("renamify");
154-
if (!config.get("respectGitignore")) {
155-
args.push("-u");
161+
const config = vscode.workspace.getConfiguration('renamify');
162+
if (!config.get('respectGitignore')) {
163+
args.push('-u');
156164
}
157165

158166
const result = await this.runCli(args);
159167

160168
// Parse the JSON response
161-
const planData = JSON.parse(result);
162-
return { planId: planData.plan_id };
169+
const parsed = JSON.parse(result);
170+
// Extract the plan ID from the wrapper or plan
171+
const planId = parsed.plan_id || parsed.plan?.id;
172+
if (!planId) {
173+
throw new Error('Invalid response from CLI: missing plan ID');
174+
}
175+
return { planId };
163176
}
164177

165178
async apply(planId?: string): Promise<void> {
166-
const args = ["apply", "--output", "json"];
179+
const args = ['apply', '--output', 'json'];
167180

168181
if (planId) {
169-
args.push("--id", planId);
182+
args.push('--id', planId);
170183
}
171184

172185
await this.runCli(args);
173186
}
174187

175188
async undo(id: string): Promise<void> {
176-
await this.runCli(["undo", id, "--output", "json"]);
189+
await this.runCli(['undo', id, '--output', 'json']);
177190
}
178191

179192
async redo(id: string): Promise<void> {
180-
await this.runCli(["redo", id, "--output", "json"]);
193+
await this.runCli(['redo', id, '--output', 'json']);
181194
}
182195

183196
async history(limit?: number): Promise<HistoryEntry[]> {
184-
const args = ["history", "--output", "json"];
197+
const args = ['history', '--output', 'json'];
185198

186199
if (limit) {
187-
args.push("--limit", limit.toString());
200+
args.push('--limit', limit.toString());
188201
}
189202

190203
const result = await this.runCli(args);
191204
return JSON.parse(result);
192205
}
193206

194207
async status(): Promise<Status> {
195-
const result = await this.runCli(["status", "--output", "json"]);
208+
const result = await this.runCli(['status', '--output', 'json']);
196209
return JSON.parse(result);
197210
}
198211

@@ -210,18 +223,18 @@ export class RenamifyCliService {
210223
env: process.env,
211224
});
212225

213-
let stdout = "";
214-
let stderr = "";
226+
let stdout = '';
227+
let stderr = '';
215228

216-
proc.stdout.on("data", (data) => {
229+
proc.stdout.on('data', (data) => {
217230
stdout += data.toString();
218231
});
219232

220-
proc.stderr.on("data", (data) => {
233+
proc.stderr.on('data', (data) => {
221234
stderr += data.toString();
222235
});
223236

224-
proc.on("close", (code) => {
237+
proc.on('close', (code) => {
225238
if (code === 0) {
226239
resolve(stdout);
227240
} else {
@@ -230,7 +243,7 @@ export class RenamifyCliService {
230243
}
231244
});
232245

233-
proc.on("error", (err) => {
246+
proc.on('error', (err) => {
234247
reject(err);
235248
});
236249
});

0 commit comments

Comments
 (0)