Skip to content

Commit 0afc355

Browse files
committed
feat: implement global configuration support and update related scripts for XDG compliance
1 parent 33cfd4d commit 0afc355

21 files changed

+167
-50
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ env/
4848
*.zip
4949
sdd-*
5050

51+
# User-specific configuration (now stored globally in ~/.config/specify/)
52+
# Old local config directory is kept for backward compatibility but should not be used
53+
.specify/config/
54+
5155
# Evaluation artifacts
5256
eval-results*.json
5357
*.backup

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ All notable changes to the Specify CLI and templates are documented here.
77
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
99

10+
## [0.0.23] - 2025-01-28
11+
12+
### Changed
13+
14+
- **Global Configuration Support**: Configuration now stored globally in `~/.config/specify/config.json` (XDG Base Directory compliant)
15+
- Linux: `$XDG_CONFIG_HOME/specify/config.json` (defaults to `~/.config/specify/config.json`)
16+
- macOS: `~/Library/Application Support/specify/config.json`
17+
- Windows: `%APPDATA%\specify\config.json`
18+
- All projects share a single global configuration file
19+
- Uses `platformdirs` for cross-platform path resolution
20+
- Updated Python CLI (`src/specify_cli/__init__.py`) with `get_global_config_path()` function
21+
- Updated bash scripts (`scripts/bash/common.sh`) with `get_global_config_path()` helper
22+
- Updated PowerShell scripts (`scripts/powershell/common.ps1`) with `Get-GlobalConfigPath` function
23+
- Old local `.specify/config/` directories are now ignored (added to `.gitignore`)
24+
25+
### Removed
26+
27+
- **`mode_history` from configuration**: Removed `workflow.mode_history` field from config structure (was unused)
28+
1029
## [0.0.22] - 2025-11-07
1130

1231
- Support for VS Code/Copilot agents, and moving away from prompts to proper agents with hand-offs.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "agentic-sdlc-specify-cli"
3-
version = "0.0.22"
3+
version = "0.0.23"
44
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
55
requires-python = ">=3.11"
66
dependencies = [

roadmap.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@
146146

147147
-**Gateway Health Checks**: Only basic configuration exists, no health check implementation
148148
-**Tool Selection Guidance**: Claims implementation but no actual guidance logic found
149-
- **Global Configuration Support**: Implement hierarchical config loading (Local `.specify/config/config.json` overrides Global `~/.config/specify/config.json`).
150-
- **CLI Config Refactor**: Update `src/specify_cli/__init__.py` to use `platformdirs` for XDG-compliant global path resolution and deep merging logic.
151-
- **Script Config Resolution**: Update `common.sh` and `common.ps1` helper functions to check global paths if local config is missing values.
149+
- **Global Configuration Support**: All configuration now stored globally in `~/.config/specify/config.json` (XDG compliant). Single shared configuration across all projects. Linux: `$XDG_CONFIG_HOME/specify/config.json`, macOS: `~/Library/Application Support/specify/config.json`, Windows: `%APPDATA%\specify\config.json`.
150+
- **CLI Config Refactor**: Updated `src/specify_cli/__init__.py` to use `platformdirs` for XDG-compliant global path resolution.
151+
- **Script Config Resolution**: Updated `common.sh` and `common.ps1` with `get_global_config_path()` / `Get-GlobalConfigPath` helper functions.
152152
-**Config Consolidation**: Successfully implemented as single unified configuration file to reduce complexity and improve maintainability
153153
-**Atomic Commits Config**: Add `atomic_commits` boolean option to `config.json` (default: `false`). Externalize as global configuration available to all workflow modes (build/spec/ad) with per-mode override capability.
154154
-**Execution Logic**: Update `scripts/bash/tasks-meta-utils.sh` and `scripts/powershell/common.ps1` to read `atomic_commits` config and inject constraint into `generate_delegation_prompt()` when enabled.

scripts/bash/check-prerequisites.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ PY
149149

150150
# Extract mode configuration
151151
get_mode_config() {
152-
local config_file=".specify/config/config.json"
152+
local config_file
153+
config_file=$(get_global_config_path)
153154

154155
# Extract current mode and options from consolidated config
155156
python3 - "$config_file" <<'PY'
@@ -225,11 +226,12 @@ fi
225226
if [[ ! -f "$IMPL_PLAN" ]]; then
226227
# Get current mode to determine if plan.md is required
227228
current_mode="spec"
228-
if [[ -f ".specify/config/config.json" ]]; then
229+
global_config=$(get_global_config_path)
230+
if [[ -f "$global_config" ]]; then
229231
current_mode=$(python3 -c "
230232
import json
231233
try:
232-
with open('.specify/config/config.json', 'r') as f:
234+
with open('$global_config', 'r') as f:
233235
data = json.load(f)
234236
print(data.get('workflow', {}).get('current_mode', 'spec'))
235237
except:

scripts/bash/common.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,20 @@
44
# Shared constants
55
TEAM_DIRECTIVES_DIRNAME="team-ai-directives"
66

7+
# Get the global config path using XDG Base Directory spec
8+
# Platform-specific locations:
9+
# - Linux: ~/.config/specify/config.json
10+
# - macOS: ~/Library/Application Support/specify/config.json (but we use XDG for consistency)
11+
get_global_config_path() {
12+
local config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
13+
echo "$config_home/specify/config.json"
14+
}
15+
716
load_team_directives_config() {
817
local repo_root="$1"
918

10-
local config_file="$repo_root/.specify/config/config.json"
19+
local config_file
20+
config_file=$(get_global_config_path)
1121
if [[ -f "$config_file" ]] && command -v jq >/dev/null 2>&1; then
1222
local path
1323
path=$(jq -r '.team_directives.path // empty' "$config_file" 2>/dev/null)

scripts/bash/create-new-feature.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ fi
174174

175175
cd "$REPO_ROOT"
176176

177+
# Get the global config path using XDG Base Directory spec
178+
get_global_config_path() {
179+
local config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
180+
echo "$config_home/specify/config.json"
181+
}
182+
177183
SPECS_DIR="$REPO_ROOT/specs"
178184
mkdir -p "$SPECS_DIR"
179185

@@ -298,7 +304,7 @@ replace_date_placeholders() {
298304
}
299305

300306
# Mode-aware template selection
301-
MODE_FILE="$REPO_ROOT/.specify/config/config.json"
307+
MODE_FILE=$(get_global_config_path)
302308
CURRENT_MODE="spec"
303309
if [ -f "$MODE_FILE" ]; then
304310
CURRENT_MODE=$(python3 -c "

scripts/bash/implement.sh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ load_implementation_context() {
121121

122122
# Get current workflow mode
123123
local workflow_mode="spec" # Default
124-
if [[ -f ".specify/config/config.json" ]]; then
125-
workflow_mode=$(jq -r '.workflow.current_mode // "spec"' ".specify/config/config.json" 2>/dev/null || echo "spec")
124+
local global_config
125+
global_config=$(get_global_config_path)
126+
if [[ -f "$global_config" ]]; then
127+
workflow_mode=$(jq -r '.workflow.current_mode // "spec"' "$global_config" 2>/dev/null || echo "spec")
126128
fi
127129

128130
# Required files (plan.md is optional in build mode)
@@ -426,8 +428,10 @@ handle_task_failure() {
426428

427429
# Get workflow mode for mode-aware rollback
428430
local mode="spec" # Default
429-
if [[ -f ".specify/config/config.json" ]]; then
430-
mode=$(jq -r '.workflow.current_mode // "spec"' ".specify/config/config.json" 2>/dev/null || echo "spec")
431+
local global_config
432+
global_config=$(get_global_config_path)
433+
if [[ -f "$global_config" ]]; then
434+
mode=$(jq -r '.workflow.current_mode // "spec"' "$global_config" 2>/dev/null || echo "spec")
431435
fi
432436

433437
echo "Task $task_id failed. Options:

scripts/bash/spec-hooks-install.sh

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,23 @@ set -euo pipefail
7777
SCRIPT_DIR="\$(cd "\$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
7878
PROJECT_ROOT="\$(cd "\$SCRIPT_DIR/../.." && pwd)"
7979
80+
# Get the global config path using XDG Base Directory spec
81+
GLOBAL_CONFIG="\${XDG_CONFIG_HOME:-\$HOME/.config}/specify/config.json"
82+
8083
# Check if spec sync is enabled for this project
81-
if [[ ! -f "\$PROJECT_ROOT/.specify/config/config.json" ]]; then
84+
if [[ ! -f "\$GLOBAL_CONFIG" ]]; then
8285
exit 0
8386
fi
8487
8588
# Check if spec sync is enabled in config
8689
if command -v jq >/dev/null 2>&1; then
87-
enabled=\$(jq -r '.spec_sync.enabled // false' "\$PROJECT_ROOT/.specify/config/config.json" 2>/dev/null)
90+
enabled=\$(jq -r '.spec_sync.enabled // false' "\$GLOBAL_CONFIG" 2>/dev/null)
8891
if [[ "\$enabled" != "true" ]]; then
8992
exit 0
9093
fi
9194
else
9295
# Fallback: check if enabled exists in config (simple grep)
93-
if ! grep -q '"enabled":\s*true' "\$PROJECT_ROOT/.specify/config/config.json" 2>/dev/null; then
96+
if ! grep -q '"enabled":\s*true' "\$GLOBAL_CONFIG" 2>/dev/null; then
9497
exit 0
9598
fi
9699
fi
@@ -107,9 +110,11 @@ EOF
107110
log_success "Installed $hook_name hook"
108111
}
109112

110-
# Create spec sync configuration
113+
# Create spec sync configuration (in global config location)
111114
function create_config {
112-
local config_dir=".specify/config"
115+
# Use XDG Base Directory spec for global config
116+
local config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
117+
local config_dir="$config_home/specify"
113118
local config_file="$config_dir/config.json"
114119
mkdir -p "$config_dir"
115120

@@ -124,8 +129,7 @@ function create_config {
124129
},
125130
"workflow": {
126131
"current_mode": "spec",
127-
"default_mode": "spec",
128-
"mode_history": []
132+
"default_mode": "spec"
129133
},
130134
"options": {
131135
"tdd_enabled": false,
@@ -169,7 +173,7 @@ EOF
169173
fi
170174
fi
171175

172-
log_success "Created/updated spec sync configuration"
176+
log_success "Created/updated spec sync configuration at $config_file"
173177
}
174178

175179
# Main installation function

scripts/bash/spec-sync-post-commit.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ log_error() {
3232
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
3333
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
3434

35-
# Check if spec sync is enabled
36-
CONFIG_FILE="$PROJECT_ROOT/.specify/config/config.json"
35+
# Check if spec sync is enabled (global config)
36+
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/specify/config.json"
3737
if [[ ! -f "$CONFIG_FILE" ]]; then
3838
exit 0
3939
fi

0 commit comments

Comments
 (0)