-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Problem Statement
Currently, the OpenSpec directory name is hardcoded as OPENSPEC_DIR_NAME = 'openspec' in src/core/config.ts 1 . This prevents users from customizing the directory name to suit their project conventions or preferences.
Use Case
Users working in environments with specific naming conventions or those who want to integrate OpenSpec into existing project structures may need to use a different directory name than the default openspec/. For example, a team might prefer .openspec/, specs/, or docs/openspec/ to match their existing documentation structure.
Proposed Solution
Add configuration support for customizing the OpenSpec directory name through the existing configuration systems:
Option 1: Global Configuration
Add a directoryName field to the GlobalConfig interface 2 :
export interface GlobalConfig {
featureFlags?: Record<string, boolean>;
directoryName?: string; // New field
}Option 2: Project Configuration
Add support for openspec.config.yaml (as discussed in docs/project-config-demo.md 3 ) with a directoryName field:
# openspec.config.yaml
directoryName: .openspec # or any preferred nameImplementation Approach
-
Modify config resolution: Update the configuration loading logic to check for a custom directory name, with precedence:
- Project-level
openspec.config.yaml(highest priority) - Global config 4
- Default
'openspec'(fallback)
- Project-level
-
Update directory references: Replace hardcoded
OPENSPEC_DIR_NAMEusage with a function that resolves the directory name based on configuration. -
Update CLI commands: Modify
init,update, and other commands to use the configurable directory name.
Benefits
- Flexibility: Teams can adopt OpenSpec without disrupting existing directory structures
- Integration: Better compatibility with different project layouts and conventions
- Backward compatibility: Default behavior remains unchanged for existing users
Files to Modify
src/core/config.ts- Add directory name resolution logicsrc/core/global-config.ts- ExtendGlobalConfiginterfacesrc/core/init.ts- Use configurable directory name 5src/core/update.ts- Update directory resolution 6src/commands/config.ts- Add config management for directory name
Notes
This feature leverages the existing configuration infrastructure 7 and aligns with the project configuration work already documented in docs/project-config-demo.md 3 .
Citations
File: src/core/config.ts (L1-1)
export const OPENSPEC_DIR_NAME = 'openspec';File: src/core/global-config.ts (L1-79)
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as os from 'node:os';
// Constants
export const GLOBAL_CONFIG_DIR_NAME = 'openspec';
export const GLOBAL_CONFIG_FILE_NAME = 'config.json';
export const GLOBAL_DATA_DIR_NAME = 'openspec';
// TypeScript interfaces
export interface GlobalConfig {
featureFlags?: Record<string, boolean>;
}
const DEFAULT_CONFIG: GlobalConfig = {
featureFlags: {}
};
/**
* Gets the global configuration directory path following XDG Base Directory Specification.
*
* - All platforms: $XDG_CONFIG_HOME/openspec/ if XDG_CONFIG_HOME is set
* - Unix/macOS fallback: ~/.config/openspec/
* - Windows fallback: %APPDATA%/openspec/
*/
export function getGlobalConfigDir(): string {
// XDG_CONFIG_HOME takes precedence on all platforms when explicitly set
const xdgConfigHome = process.env.XDG_CONFIG_HOME;
if (xdgConfigHome) {
return path.join(xdgConfigHome, GLOBAL_CONFIG_DIR_NAME);
}
const platform = os.platform();
if (platform === 'win32') {
// Windows: use %APPDATA%
const appData = process.env.APPDATA;
if (appData) {
return path.join(appData, GLOBAL_CONFIG_DIR_NAME);
}
// Fallback for Windows if APPDATA is not set
return path.join(os.homedir(), 'AppData', 'Roaming', GLOBAL_CONFIG_DIR_NAME);
}
// Unix/macOS fallback: ~/.config
return path.join(os.homedir(), '.config', GLOBAL_CONFIG_DIR_NAME);
}
/**
* Gets the global data directory path following XDG Base Directory Specification.
* Used for user data like schema overrides.
*
* - All platforms: $XDG_DATA_HOME/openspec/ if XDG_DATA_HOME is set
* - Unix/macOS fallback: ~/.local/share/openspec/
* - Windows fallback: %LOCALAPPDATA%/openspec/
*/
export function getGlobalDataDir(): string {
// XDG_DATA_HOME takes precedence on all platforms when explicitly set
const xdgDataHome = process.env.XDG_DATA_HOME;
if (xdgDataHome) {
return path.join(xdgDataHome, GLOBAL_DATA_DIR_NAME);
}
const platform = os.platform();
if (platform === 'win32') {
// Windows: use %LOCALAPPDATA%
const localAppData = process.env.LOCALAPPDATA;
if (localAppData) {
return path.join(localAppData, GLOBAL_DATA_DIR_NAME);
}
// Fallback for Windows if LOCALAPPDATA is not set
return path.join(os.homedir(), 'AppData', 'Local', GLOBAL_DATA_DIR_NAME);
}
// Unix/macOS fallback: ~/.local/share
return path.join(os.homedir(), '.local', 'share', GLOBAL_DATA_DIR_NAME);
}