@popoverai/dotrequirements 0.11.0 → 0.11.1

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.
@@ -165,7 +165,8 @@ async function createNewProjectFlow(cwd, envPath, options) {
165
165
  return;
166
166
  }
167
167
  // Reload env file so newly written credentials are available to subsequent commands
168
- loadEnvFile(cwd);
168
+ // Use force=true to overwrite any previously cached values
169
+ loadEnvFile(cwd, true);
169
170
  // 4. Create .requirements/ directory
170
171
  await createRequirementsDirectory(cwd, projectId);
171
172
  // 5. Update .gitignore
@@ -242,7 +243,8 @@ async function connectExistingProjectFlow(cwd, envPath) {
242
243
  return;
243
244
  }
244
245
  // Reload env file so newly written credentials are available to pullCommand
245
- loadEnvFile(cwd);
246
+ // Use force=true to overwrite any previously cached values
247
+ loadEnvFile(cwd, true);
246
248
  // Create .requirements/ directory
247
249
  await createRequirementsDirectory(cwd, projectId);
248
250
  // Update .gitignore
@@ -106,6 +106,7 @@ export async function mcpSetupCommand() {
106
106
  message: 'Which AI assistant are you using?',
107
107
  choices: [
108
108
  { title: 'Claude Code', value: 'claude-code' },
109
+ { title: 'Claude Desktop', value: 'claude-desktop' },
109
110
  { title: 'Cursor', value: 'cursor' },
110
111
  { title: 'Google Antigravity', value: 'antigravity' },
111
112
  { title: 'OpenAI Codex', value: 'codex' },
@@ -122,6 +123,9 @@ export async function mcpSetupCommand() {
122
123
  case 'claude-code':
123
124
  await setupClaudeCode();
124
125
  break;
126
+ case 'claude-desktop':
127
+ await setupClaudeDesktop();
128
+ break;
125
129
  case 'cursor':
126
130
  await setupCursor();
127
131
  break;
@@ -174,6 +178,78 @@ async function setupClaudeCode() {
174
178
  await installAllSkills('claude-code');
175
179
  }
176
180
  }
181
+ async function setupClaudeDesktop() {
182
+ console.log('\nšŸ“¦ Configuring MCP for Claude Desktop...\n');
183
+ // Determine config path based on OS
184
+ const platform = process.platform;
185
+ let configPath;
186
+ let configDir;
187
+ if (platform === 'darwin') {
188
+ configDir = join(homedir(), 'Library', 'Application Support', 'Claude');
189
+ configPath = join(configDir, 'claude_desktop_config.json');
190
+ }
191
+ else if (platform === 'win32') {
192
+ const appData = process.env.APPDATA || join(homedir(), 'AppData', 'Roaming');
193
+ configDir = join(appData, 'Claude');
194
+ configPath = join(configDir, 'claude_desktop_config.json');
195
+ }
196
+ else {
197
+ console.error('āŒ Claude Desktop is only supported on macOS and Windows.');
198
+ console.log('\nFor Linux, please manually configure the MCP server.');
199
+ return;
200
+ }
201
+ const mcpServerConfig = {
202
+ command: 'npx',
203
+ args: ['-y', '@popoverai/dotrequirements', 'mcp'],
204
+ env: {
205
+ REQUIREMENTS_DIR: process.cwd(),
206
+ },
207
+ };
208
+ try {
209
+ if (!existsSync(configDir)) {
210
+ console.log('Creating Claude Desktop config directory...');
211
+ mkdirSync(configDir, { recursive: true });
212
+ }
213
+ let config = {};
214
+ if (existsSync(configPath)) {
215
+ try {
216
+ const existingContent = readFileSync(configPath, 'utf-8');
217
+ if (existingContent.trim()) {
218
+ config = JSON.parse(existingContent);
219
+ }
220
+ }
221
+ catch (parseError) {
222
+ console.log('āš ļø Existing config file is invalid, creating fresh config...');
223
+ config = {};
224
+ }
225
+ }
226
+ if (!config.mcpServers) {
227
+ config.mcpServers = {};
228
+ }
229
+ config.mcpServers['dotrequirements'] = mcpServerConfig;
230
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
231
+ console.log(`āœ… MCP configured successfully!`);
232
+ console.log(` Config file: ${configPath}`);
233
+ console.log(` REQUIREMENTS_DIR: ${process.cwd()}\n`);
234
+ console.log('āš ļø Important: Quit and restart Claude Desktop for changes to take effect.');
235
+ console.log(' (Cmd+Q on macOS, not just close the window)\n');
236
+ console.log('You can now ask Claude Desktop to help write requirements!\n');
237
+ // Claude Desktop doesn't use skills like Claude Code, so we skip that step
238
+ }
239
+ catch (error) {
240
+ console.error('āŒ Failed to configure MCP automatically.');
241
+ console.log(`\nError: ${error instanceof Error ? error.message : String(error)}`);
242
+ console.log('\nYou can manually edit the config file at:');
243
+ console.log(` ${configPath}\n`);
244
+ console.log('Add the following configuration:');
245
+ const manualConfig = {
246
+ mcpServers: {
247
+ dotrequirements: mcpServerConfig,
248
+ },
249
+ };
250
+ console.log(JSON.stringify(manualConfig, null, 2));
251
+ }
252
+ }
177
253
  async function setupCursor() {
178
254
  console.log('\nšŸ“¦ Configuring MCP for Cursor (project-specific)...\n');
179
255
  const configPath = join(process.cwd(), '.cursor', 'mcp.json');
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * Load environment variables from .env.local file
3
- * Merges with existing process.env (process.env takes precedence)
3
+ * Merges with existing process.env (process.env takes precedence by default)
4
+ * @param cwd - Directory containing .env.local (defaults to process.cwd())
5
+ * @param force - If true, overwrite existing process.env values (used when reloading after init)
4
6
  */
5
- export declare function loadEnvFile(cwd?: string): void;
7
+ export declare function loadEnvFile(cwd?: string, force?: boolean): void;
6
8
  /**
7
9
  * Get project credentials from environment
8
10
  * Returns undefined if not found
package/dist/utils/env.js CHANGED
@@ -2,9 +2,11 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  /**
4
4
  * Load environment variables from .env.local file
5
- * Merges with existing process.env (process.env takes precedence)
5
+ * Merges with existing process.env (process.env takes precedence by default)
6
+ * @param cwd - Directory containing .env.local (defaults to process.cwd())
7
+ * @param force - If true, overwrite existing process.env values (used when reloading after init)
6
8
  */
7
- export function loadEnvFile(cwd = process.cwd()) {
9
+ export function loadEnvFile(cwd = process.cwd(), force = false) {
8
10
  const envPath = path.join(cwd, '.env.local');
9
11
  if (!fs.existsSync(envPath)) {
10
12
  return;
@@ -22,8 +24,8 @@ export function loadEnvFile(cwd = process.cwd()) {
22
24
  if (match) {
23
25
  const key = match[1].trim();
24
26
  const value = match[2].trim();
25
- // Only set if not already in process.env
26
- if (!process.env[key]) {
27
+ // Set if force=true, or if not already in process.env
28
+ if (force || !process.env[key]) {
27
29
  process.env[key] = value;
28
30
  }
29
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popoverai/dotrequirements",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Requirements tracking CLI, test harness, and MCP server",
5
5
  "type": "module",
6
6
  "bin": {