Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [📽️ Video Overview](#️-video-overview)
- [🤖 Supported AI Agents](#-supported-ai-agents)
- [🔧 Specify CLI Reference](#-specify-cli-reference)
- [🔀 Source Management Modes](#-source-management-modes)
- [📚 Core Philosophy](#-core-philosophy)
- [🌟 Development Phases](#-development-phases)
- [🎯 Experimental Goals](#-experimental-goals)
Expand Down Expand Up @@ -274,6 +275,133 @@ Additional commands for enhanced quality and validation:
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches.<br/>\*\*Must be set in the context of the agent you're working with prior to using `/speckit.plan` or follow-up commands. |

## 🔀 Source Management Modes

Spec Kit supports three Git workflow modes to match your development style:

### Branch Mode (Default)

Traditional branch-based workflow where each feature is developed on its own branch.

```bash
specify init my-project --ai claude
# Detects standard Git repo → recommends "branch" mode (you can choose during init)
```

**Best for:**
- Standard Git repositories
- Small to medium teams
- Projects with simple branching strategies

**How it works:**
- `create-new-feature.sh` creates a new Git branch (e.g., `001-feature-name`)
- Specs stored in `specs/001-feature-name/`
- Switch between features with `git checkout`

### Worktree Mode

Isolated working directories per feature using [Git worktrees](https://git-scm.com/docs/git-worktree).

```bash
specify init my-project --ai claude
# In a bare repository → recommends "worktree" mode (you can choose during init)
```

**Best for:**
- Bare repositories (highly recommended)
- Working on multiple features simultaneously
- Large teams with many parallel features
- Projects requiring quick context switching without stashing

**How it works:**
- `create-new-feature.sh` creates a Git worktree in `./worktrees/001-feature-name/`
- Each feature has its own isolated directory
- No need to switch branches or stash changes
- All worktrees share the same Git history

**Configuration:**
During initialization, you'll be prompted for the worktree folder location (default: `./worktrees`).

**Example workflow:**
```bash
# Initialize project in worktree mode
specify init --here --ai claude
# Select "worktree" mode when prompted

# Create first feature (creates worktree)
.specify/scripts/bash/create-new-feature.sh "Add user authentication"
# Creates: ./worktrees/001-user-authentication/

# Work in first feature
cd ./worktrees/001-user-authentication/
# Edit code, run tests...

# Create second feature without leaving first
cd ../..
.specify/scripts/bash/create-new-feature.sh "Add payment processing"
# Creates: ./worktrees/002-payment-processing/

# Both features are independent and isolated!
```

### None Mode

Skip Git operations entirely for non-Git projects or manual Git control.

```bash
specify init my-project --ai claude --no-git
# Recommends "none" mode (you can choose during init)
```

**Best for:**
- Non-Git version control systems
- Projects where you want manual Git control
- Prototyping or exploration without version control

**How it works:**
- No Git branches or worktrees created
- Specs stored in `specs/001-feature-name/` as normal
- Feature numbers still auto-increment

### Mode Selection

During `specify init`, you'll be prompted to select your preferred source management mode:

1. **Environment Detection**: The CLI detects your Git environment (bare repo, worktree, standard repo, or no Git)
2. **Recommendation**: Based on the detection, a recommended mode is shown
3. **Interactive Choice**: You select your preferred mode using arrow keys:
- `branch` - Traditional Git branches (recommended for most projects)
- `worktree` - Git worktrees (advanced, for parallel feature development)
- `none` - No Git integration (manual source management)
4. **Configuration**: Your selected mode is saved to `.specify/memory/config.json`

**Example selection screen:**
```
Detected environment: Standard Git repository
Recommended mode: branch

Select source management mode:
▶ branch (Traditional Git branches - recommended for most projects)
worktree (Git worktrees - advanced, for parallel feature development)
none (No Git integration - manual source management)
```

### Mode Configuration

Your selected mode is saved in `.specify/memory/config.json`:

```json
{
"version": "1.0",
"source_management_flow": "worktree",
"worktree_folder": "./worktrees"
}
```

**Mode detection:** Run `specify check` to see your current mode.

**Important:** Source management mode cannot be changed after initialization. To switch modes, delete `.specify/memory/config.json` and run `specify init` again.

## 📚 Core Philosophy

Spec-Driven Development is a structured process that emphasizes:
Expand Down
24 changes: 24 additions & 0 deletions scripts/bash/common.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,30 @@ check_feature_branch() {
return 1
fi

# Feature 001: Worktree/branch alignment validation
# Check if we're in a worktree and validate directory/branch name alignment
if [[ -f .git ]]; then
# We're in a worktree (.git is a file, not a directory)
local worktree_dir=$(basename "$(pwd)")

Comment on lines +85 to +86
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The worktree validation logic uses basename "$(pwd)" to get the directory name, but this will only work if the user is currently in the worktree directory. If they're in a subdirectory of the worktree (e.g., worktrees/001-feature/src/), this will return the subdirectory name (e.g., "src") instead of the worktree name (e.g., "001-feature"), causing a false mismatch error.

Consider using git rev-parse --show-toplevel to get the worktree root directory before extracting the basename.

Suggested change
local worktree_dir=$(basename "$(pwd)")
local worktree_root
local worktree_dir
if worktree_root="$(git rev-parse --show-toplevel 2>/dev/null)"; then
worktree_dir="$(basename "$worktree_root")"
else
# Fallback: use current directory name if git metadata is unavailable
worktree_dir="$(basename "$(pwd)")"
fi

Copilot uses AI. Check for mistakes.
if [[ "$worktree_dir" != "$branch" ]]; then
echo "ERROR: Worktree directory name doesn't match branch name" >&2
echo " Directory: $worktree_dir" >&2
echo " Branch: $branch" >&2
echo "" >&2
echo "Spec Kit expects worktree directory names to match branch names." >&2
echo "This mismatch may have occurred due to manual worktree creation or directory renaming." >&2
echo "" >&2
echo "To fix this issue:" >&2
echo " 1. Return to the main repository" >&2
echo " 2. Remove this worktree: git worktree remove $worktree_dir" >&2
echo " 3. Recreate using Spec Kit: ./scripts/bash/create-new-feature.sh '$branch'" >&2
return 1
else
echo "[specify] ✓ Worktree/branch alignment validated: $branch" >&2
fi
fi

return 0
}

Expand Down
152 changes: 145 additions & 7 deletions scripts/bash/create-new-feature.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,20 @@ clean_branch_name() {
# were initialised with --no-git.
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

if git rev-parse --show-toplevel >/dev/null 2>&1; then
REPO_ROOT=$(git rev-parse --show-toplevel)
# Check if we're in any Git repository (works for both bare and non-bare repos)
if git rev-parse --git-dir >/dev/null 2>&1; then
HAS_GIT=true
# Check if this is a bare repository
if [ "$(git rev-parse --is-bare-repository 2>/dev/null)" = "true" ]; then
# Bare repository - use git-dir as root
REPO_ROOT=$(git rev-parse --git-dir)
REPO_ROOT=$(cd "$REPO_ROOT" && pwd) # Resolve to absolute path
else
# Non-bare repository - use show-toplevel
REPO_ROOT=$(git rev-parse --show-toplevel)
fi
else
# Not a Git repository - fall back to marker search
REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
if [ -z "$REPO_ROOT" ]; then
echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
Expand All @@ -174,9 +184,28 @@ fi

cd "$REPO_ROOT"

# Save original directory for error recovery
ORIGINAL_DIR="$PWD"

SPECS_DIR="$REPO_ROOT/specs"
mkdir -p "$SPECS_DIR"

# Feature 001: Read source management mode from config
CONFIG_FILE="$REPO_ROOT/.specify/memory/config.json"
SOURCE_MODE="branch" # Default to branch mode for backward compatibility
WORKTREE_FOLDER=""

if [ -f "$CONFIG_FILE" ]; then
# Parse JSON config using grep/sed (no jq dependency needed)
SOURCE_MODE=$(grep -o '"source_management_flow"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" | sed 's/.*"\([^"]*\)".*/\1/' || echo "branch")
WORKTREE_FOLDER=$(grep -o '"worktree_folder"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
fi

# Fallback to branch mode if config is invalid
if [ -z "$SOURCE_MODE" ]; then
Comment on lines +199 to +205
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON parsing using grep/sed is fragile and may fail with certain valid JSON formats. For example:

  • If there's no whitespace after the colon: "source_management_flow":"branch"
  • If there are newlines in the string value
  • If the field appears in a nested object or comment

The regex pattern [[:space:]]* requires at least the ability to match zero spaces, but the overall pattern may still fail. Consider using a more robust approach or adding validation that the parsed value is one of the expected modes (branch/worktree/none).

Suggested change
# Parse JSON config using grep/sed (no jq dependency needed)
SOURCE_MODE=$(grep -o '"source_management_flow"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" | sed 's/.*"\([^"]*\)".*/\1/' || echo "branch")
WORKTREE_FOLDER=$(grep -o '"worktree_folder"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
fi
# Fallback to branch mode if config is invalid
if [ -z "$SOURCE_MODE" ]; then
# Parse JSON config using python's json module for robustness
if CONFIG_VALUES=$(python3 - <<'PY' "$CONFIG_FILE" 2>/dev/null
import json
import sys
path = sys.argv[1]
try:
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
except Exception:
# On any parsing/IO error, fall back to defaults handled in shell
print("branch")
print("")
sys.exit(0)
source_mode = data.get("source_management_flow", "branch")
worktree_folder = data.get("worktree_folder", "")
# Ensure we always print exactly two lines
print(source_mode if isinstance(source_mode, str) else "branch")
print(worktree_folder if isinstance(worktree_folder, str) else "")
PY
); then
SOURCE_MODE=$(printf '%s\n' "$CONFIG_VALUES" | sed -n '1p')
WORKTREE_FOLDER=$(printf '%s\n' "$CONFIG_VALUES" | sed -n '2p')
fi
fi
# Fallback to branch mode if config is invalid or unexpected
if [ -z "$SOURCE_MODE" ] || { [ "$SOURCE_MODE" != "branch" ] && [ "$SOURCE_MODE" != "worktree" ] && [ "$SOURCE_MODE" != "none" ]; }; then

Copilot uses AI. Check for mistakes.
SOURCE_MODE="branch"
fi

# Function to generate branch name with stop word filtering and length filtering
generate_branch_name() {
local description="$1"
Expand Down Expand Up @@ -272,24 +301,133 @@ if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
fi

if [ "$HAS_GIT" = true ]; then
git checkout -b "$BRANCH_NAME"
# Feature 001: Create worktree or branch based on mode
if [ "$SOURCE_MODE" = "worktree" ]; then
# Worktree mode: create worktree instead of branch
if [ -z "$WORKTREE_FOLDER" ]; then
WORKTREE_FOLDER="./worktrees"
fi

# Resolve to absolute path
if [[ "$WORKTREE_FOLDER" != /* ]]; then
WORKTREE_FOLDER="$REPO_ROOT/$WORKTREE_FOLDER"
fi

Comment on lines +311 to +315
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The worktree folder path is resolved relative to REPO_ROOT without validating that the resulting path doesn't escape the repository. A malicious config file could set worktree_folder to something like "../../../../tmp/worktrees" which would create worktrees outside the repository.

Consider validating that the resolved absolute path is still within or explicitly outside the repository with user awareness, or restrict worktree_folder to relative paths only that don't contain path traversal sequences.

Suggested change
# Resolve to absolute path
if [[ "$WORKTREE_FOLDER" != /* ]]; then
WORKTREE_FOLDER="$REPO_ROOT/$WORKTREE_FOLDER"
fi
# Ensure REPO_ROOT is absolute and canonical for comparisons
REPO_ROOT_ABS="$(cd "$REPO_ROOT" >/dev/null 2>&1 && pwd)"
# Normalize and validate worktree folder path
if [[ "$WORKTREE_FOLDER" != /* ]]; then
# Relative path: forbid path traversal via ".." segments
case "$WORKTREE_FOLDER" in
".." | "../"* | *"/../"* | *"/.." )
>&2 echo "[specify] Error: Relative worktree folder must not contain '..' path traversal segments: $WORKTREE_FOLDER"
exit 1
;;
esac
if command -v realpath >/dev/null 2>&1; then
WORKTREE_FOLDER="$(realpath -m "$REPO_ROOT_ABS/$WORKTREE_FOLDER")"
else
WORKTREE_FOLDER="$REPO_ROOT_ABS/$WORKTREE_FOLDER"
fi
else
# Absolute path: canonicalize if possible
if command -v realpath >/dev/null 2>&1; then
WORKTREE_FOLDER="$(realpath -m "$WORKTREE_FOLDER")"
fi
fi
# If realpath is available and worktree folder is outside repo root, require explicit confirmation
if command -v realpath >/dev/null 2>&1; then
if [[ "$WORKTREE_FOLDER" != "$REPO_ROOT_ABS" && "$WORKTREE_FOLDER" != "$REPO_ROOT_ABS/"* ]]; then
>&2 echo "[specify] Warning: Worktree folder is outside the repository root:"
>&2 echo "[specify] Repo root: $REPO_ROOT_ABS"
>&2 echo "[specify] Worktree: $WORKTREE_FOLDER"
read -p "Continue using an external worktree folder? (y/N): " -n 1 -r ALLOW_EXTERNAL_WORKTREE
echo
if [[ ! $ALLOW_EXTERNAL_WORKTREE =~ ^[Yy]$ ]]; then
>&2 echo "[specify] Aborting: external worktree folder not confirmed"
exit 1
fi
fi
fi

Copilot uses AI. Check for mistakes.
Copy link
Author

@askpatrickw askpatrickw Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is valid (very common) for worktrees to be outside (../myworktree) the bare repo. We could warn on any traversal, or fail on any more than one level of traversal, but I fear that's being too restrictive.

# Check if worktree folder exists (FR-015)
if [ ! -d "$WORKTREE_FOLDER" ]; then
>&2 echo "[specify] The configured worktree folder does not exist: $WORKTREE_FOLDER"
read -p "Create this directory? (y/N): " -n 1 -r CREATE_FOLDER
echo
if [[ $CREATE_FOLDER =~ ^[Yy]$ ]]; then
mkdir -p "$WORKTREE_FOLDER" || {
>&2 echo "[specify] Error: Failed to create worktree folder (permission denied or invalid path)"
exit 1
}
>&2 echo "[specify] Created worktree folder: $WORKTREE_FOLDER"
else
>&2 echo "[specify] Error: Cannot create worktree without folder"
exit 1
fi
fi

# Check write permissions (FR-015b)
if [ ! -w "$WORKTREE_FOLDER" ]; then
>&2 echo "[specify] Error: Worktree folder is not writable: $WORKTREE_FOLDER"
>&2 echo "[specify] Check folder permissions and try again"
exit 1
fi

WORKTREE_PATH="$WORKTREE_FOLDER/$BRANCH_NAME"

# Check if worktree path already exists (FR-016)
if [ -e "$WORKTREE_PATH" ]; then
>&2 echo "[specify] Error: Worktree path already exists: $WORKTREE_PATH"
>&2 echo "[specify] "
>&2 echo "[specify] Resolution options:"
>&2 echo "[specify] 1. Remove existing worktree: git worktree remove $BRANCH_NAME"
>&2 echo "[specify] 2. Use a different branch name with --short-name"
>&2 echo "[specify] 3. Manually delete the directory: rm -rf '$WORKTREE_PATH'"
>&2 echo "[specify] "
>&2 echo "[specify] To list all worktrees: git worktree list"
exit 1
fi

# Create worktree with new branch
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" || {
>&2 echo "[specify] Error: Failed to create worktree"
exit 1
Comment on lines +355 to +358
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When git worktree add -b fails after creating the branch but before completing the worktree setup (e.g., due to filesystem issues), the branch may be left dangling without a corresponding worktree. The error handler at line 356-358 doesn't attempt to clean up the branch in such cases.

Consider adding cleanup logic to remove the newly created branch if worktree creation fails, or at least document this potential state in the error message.

Suggested change
# Create worktree with new branch
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" || {
>&2 echo "[specify] Error: Failed to create worktree"
exit 1
# Track whether the branch existed before creating the worktree
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
BRANCH_ALREADY_EXISTS=true
else
BRANCH_ALREADY_EXISTS=false
fi
# Create worktree with new branch
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" || {
worktree_status=$?
>&2 echo "[specify] Error: Failed to create worktree at: $WORKTREE_PATH"
# If the branch did not exist before, but exists now, attempt cleanup
if [ "$BRANCH_ALREADY_EXISTS" = "false" ]; then
if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then
>&2 echo "[specify] Attempting to delete dangling branch '$BRANCH_NAME' created during failed worktree setup..."
if ! git branch -D "$BRANCH_NAME" >/dev/null 2>&1; then
>&2 echo "[specify] Warning: Failed to delete dangling branch '$BRANCH_NAME'."
>&2 echo "[specify] You may need to delete it manually: git branch -D \"$BRANCH_NAME\""
fi
fi
fi
exit "$worktree_status"

Copilot uses AI. Check for mistakes.
}

Comment on lines +356 to +360
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message "Failed to create worktree" is too generic. If the branch name already exists, Git will return a specific error, but this handler suppresses that detail. Users won't know whether the failure is due to:

  • Branch name already exists
  • Filesystem/permission issues
  • Invalid Git state
  • Other Git errors

Consider capturing and displaying the actual Git error message to help users diagnose the problem.

Suggested change
git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" || {
>&2 echo "[specify] Error: Failed to create worktree"
exit 1
}
if ! output=$(git worktree add -b "$BRANCH_NAME" "$WORKTREE_PATH" 2>&1); then
>&2 echo "[specify] Error: Failed to create worktree"
>&2 echo "[specify] Git reported:"
>&2 echo "$output"
exit 1
fi
# Re-emit git output on success (if any)
if [ -n "$output" ]; then
echo "$output"
fi

Copilot uses AI. Check for mistakes.
>&2 echo "[specify] Created worktree: $WORKTREE_PATH"
>&2 echo "[specify] Branch: $BRANCH_NAME"

# Change to worktree directory for spec creation
cd "$WORKTREE_PATH" || {
>&2 echo "[specify] Error: Failed to change to worktree directory"
cd "$ORIGINAL_DIR"
exit 1
}
# Update REPO_ROOT to worktree location
REPO_ROOT="$WORKTREE_PATH"

elif [ "$SOURCE_MODE" = "none" ]; then
# None mode: skip Git operations
>&2 echo "[specify] Git operations disabled (mode: none)"
else
# Branch mode: traditional branch creation
git checkout -b "$BRANCH_NAME"
fi
else
>&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
# Warn user if source mode expects Git but Git is unavailable
if [ "$SOURCE_MODE" = "worktree" ] || [ "$SOURCE_MODE" = "branch" ]; then
>&2 echo "[specify] Warning: Git repository not detected but source mode is set to '$SOURCE_MODE'"
>&2 echo "[specify] Creating spec in main repository instead of using Git-based workflow"
>&2 echo "[specify] To use $SOURCE_MODE mode, initialize Git with: git init"
else
>&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
fi
fi

# Update SPECS_DIR if we're in a worktree
if [ "$SOURCE_MODE" = "worktree" ] && [ "$HAS_GIT" = true ]; then
SPECS_DIR="$REPO_ROOT/specs"
fi

Comment on lines +391 to 395
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line appears to be redundant. The code only reaches this point in worktree mode if Git is available (checked at line 303), and REPO_ROOT has already been updated to WORKTREE_PATH at line 371. So this line is just setting SPECS_DIR to $WORKTREE_PATH/specs, which is already the correct value. The condition at line 392 should never be false when this code is reached in worktree mode, making this update unnecessary.

Suggested change
# Update SPECS_DIR if we're in a worktree
if [ "$SOURCE_MODE" = "worktree" ] && [ "$HAS_GIT" = true ]; then
SPECS_DIR="$REPO_ROOT/specs"
fi

Copilot uses AI. Check for mistakes.
FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
mkdir -p "$FEATURE_DIR"
mkdir -p "$FEATURE_DIR" || {
>&2 echo "[specify] Error: Failed to create feature directory: $FEATURE_DIR"
cd "$ORIGINAL_DIR"
exit 1
}

TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After creating a worktree and changing directory to it, REPO_ROOT is updated to the worktree path (line 371). This causes the template lookup at line 403 to search for .specify/templates/spec-template.md inside the worktree directory rather than the main repository. Since .specify/ doesn't exist in worktrees, the template will never be found, and an empty spec.md file will be created instead.

Consider preserving the original repository root in a separate variable (e.g., MAIN_REPO_ROOT) so that the template can be found regardless of the current working directory.

Suggested change
TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
# Use the main repository root when resolving the template path so that
# worktree mode still finds the shared .specify directory in the main repo.
if [ "$SOURCE_MODE" = "worktree" ] && [ "$HAS_GIT" = true ]; then
MAIN_REPO_ROOT="$ORIGINAL_DIR"
else
MAIN_REPO_ROOT="$REPO_ROOT"
fi
TEMPLATE="$MAIN_REPO_ROOT/.specify/templates/spec-template.md"

Copilot uses AI. Check for mistakes.
SPEC_FILE="$FEATURE_DIR/spec.md"
if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
if [ -f "$TEMPLATE" ]; then
cp "$TEMPLATE" "$SPEC_FILE" || {
>&2 echo "[specify] Error: Failed to copy template file"
cd "$ORIGINAL_DIR"
exit 1
}
else
touch "$SPEC_FILE" || {
>&2 echo "[specify] Error: Failed to create spec file"
cd "$ORIGINAL_DIR"
exit 1
}
fi

# Set the SPECIFY_FEATURE environment variable for the current session
export SPECIFY_FEATURE="$BRANCH_NAME"

if $JSON_MODE; then
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s","SOURCE_MODE":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM" "$SOURCE_MODE"
else
# Feature 001: Display source management mode
case "$SOURCE_MODE" in
"worktree") echo "MODE: Worktree mode active" ;;
"none") echo "MODE: No Git mode" ;;
*) echo "MODE: Branch mode active" ;;
esac
echo "BRANCH_NAME: $BRANCH_NAME"
echo "SPEC_FILE: $SPEC_FILE"
echo "FEATURE_NUM: $FEATURE_NUM"
Expand Down
Loading
Loading