diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..6313b56c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 27fe556c..efb95fc0 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,2 +1,3 @@
# Global code owner
* @localden
+
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 92e81a5e..b2811b43 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -65,3 +65,4 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0bede837..9ad20874 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -57,3 +57,4 @@ jobs:
run: |
chmod +x .github/workflows/scripts/update-version.sh
.github/workflows/scripts/update-version.sh ${{ steps.get_tag.outputs.new_version }}
+
diff --git a/.github/workflows/scripts/check-release-exists.sh b/.github/workflows/scripts/check-release-exists.sh
index 161bf208..88ef174f 100644
--- a/.github/workflows/scripts/check-release-exists.sh
+++ b/.github/workflows/scripts/check-release-exists.sh
@@ -18,4 +18,4 @@ if gh release view "$VERSION" >/dev/null 2>&1; then
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Release $VERSION does not exist, proceeding..."
-fi
\ No newline at end of file
+fi
diff --git a/.github/workflows/scripts/create-github-release.sh b/.github/workflows/scripts/create-github-release.sh
index f67ee3df..1125f510 100644
--- a/.github/workflows/scripts/create-github-release.sh
+++ b/.github/workflows/scripts/create-github-release.sh
@@ -43,4 +43,4 @@ gh release create "$VERSION" \
.genreleases/spec-kit-template-q-sh-"$VERSION".zip \
.genreleases/spec-kit-template-q-ps-"$VERSION".zip \
--title "Spec Kit Templates - $VERSION_NO_V" \
- --notes-file release_notes.md
\ No newline at end of file
+ --notes-file release_notes.md
diff --git a/.github/workflows/scripts/create-release-packages.sh b/.github/workflows/scripts/create-release-packages.sh
index 3e7211ec..5462a14f 100644
--- a/.github/workflows/scripts/create-release-packages.sh
+++ b/.github/workflows/scripts/create-release-packages.sh
@@ -237,3 +237,4 @@ done
echo "Archives in $GENRELEASES_DIR:"
ls -1 "$GENRELEASES_DIR"/spec-kit-template-*-"${NEW_VERSION}".zip
+
diff --git a/.github/workflows/scripts/generate-release-notes.sh b/.github/workflows/scripts/generate-release-notes.sh
index a26d16b8..eba2340b 100644
--- a/.github/workflows/scripts/generate-release-notes.sh
+++ b/.github/workflows/scripts/generate-release-notes.sh
@@ -33,4 +33,4 @@ This is the latest set of releases that you can use with your agent of choice. W
EOF
echo "Generated release notes:"
-cat release_notes.md
\ No newline at end of file
+cat release_notes.md
diff --git a/.github/workflows/scripts/get-next-version.sh b/.github/workflows/scripts/get-next-version.sh
index 2be0b6cf..9770b9fd 100644
--- a/.github/workflows/scripts/get-next-version.sh
+++ b/.github/workflows/scripts/get-next-version.sh
@@ -21,4 +21,4 @@ PATCH=$((PATCH + 1))
NEW_VERSION="v$MAJOR.$MINOR.$PATCH"
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
-echo "New version will be: $NEW_VERSION"
\ No newline at end of file
+echo "New version will be: $NEW_VERSION"
diff --git a/.github/workflows/scripts/update-version.sh b/.github/workflows/scripts/update-version.sh
index b0dc0e67..12bd9cd1 100644
--- a/.github/workflows/scripts/update-version.sh
+++ b/.github/workflows/scripts/update-version.sh
@@ -20,4 +20,4 @@ if [ -f "pyproject.toml" ]; then
echo "Updated pyproject.toml version to $PYTHON_VERSION (for release artifacts only)"
else
echo "Warning: pyproject.toml not found, skipping version update"
-fi
\ No newline at end of file
+fi
diff --git a/.gitignore b/.gitignore
index 42a1fbbf..94bed859 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,4 +42,4 @@ env/
# Spec Kit-specific files
.genreleases/
*.zip
-sdd-*/
\ No newline at end of file
+sdd-*/
diff --git a/AGENTS.md b/AGENTS.md
index 51df2266..62bbe1e0 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -326,3 +326,4 @@ When adding new agents:
---
*This documentation should be updated whenever new agents are added to maintain accuracy and completeness.*
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 219a4cb9..3ca2ee00 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,29 @@ All notable changes to the Specify CLI and templates are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.0.20] - 2025-10-14
+
+### Added
+
+- **Intelligent Branch Naming**: `create-new-feature` scripts now support `--short-name` parameter for custom branch names
+ - When `--short-name` provided: Uses the custom name directly (cleaned and formatted)
+ - When omitted: Automatically generates meaningful names using stop word filtering and length-based filtering
+ - Filters out common stop words (I, want, to, the, for, etc.)
+ - Removes words shorter than 3 characters (unless they're uppercase acronyms)
+ - Takes 3-4 most meaningful words from the description
+ - **Enforces GitHub's 244-byte branch name limit** with automatic truncation and warnings
+ - Examples:
+ - "I want to create user authentication" → `001-create-user-authentication`
+ - "Implement OAuth2 integration for API" → `001-implement-oauth2-integration-api`
+ - "Fix payment processing bug" → `001-fix-payment-processing`
+ - Very long descriptions are automatically truncated at word boundaries to stay within limits
+ - Designed for AI agents to provide semantic short names while maintaining standalone usability
+
+### Changed
+
+- Enhanced help documentation for `create-new-feature.sh` and `create-new-feature.ps1` scripts with examples
+- Branch names now validated against GitHub's 244-byte limit with automatic truncation if needed
+
## [0.0.19] - 2025-10-10
### Added
@@ -143,3 +166,4 @@ N/A
### Changed
N/A
+
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index a1f82f0d..6dc4b121 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -71,4 +71,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
\ No newline at end of file
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b5488c80..947480d0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -108,3 +108,4 @@ Please be respectful to maintainers and disclose AI assistance.
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
- [GitHub Help](https://help.github.com)
+
diff --git a/LICENSE b/LICENSE
index 28a50fa2..a0eb787a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
diff --git a/README.md b/README.md
index 8234231e..80f451ba 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
- An effort to allow organizations to focus on product scenarios rather than writing undifferentiated code with the help of Spec-Driven Development.
+ An open source toolkit that allows you to focus on product scenarios and predictable outcomes instead of vibe coding every piece from scratch.
@@ -42,7 +42,7 @@ Spec-Driven Development **flips the script** on traditional software development
## ⚡ Get Started
-### 1. Install Specify
+### 1. Install Specify CLI
Choose your preferred installation method:
@@ -623,3 +623,4 @@ This project is heavily influenced by and based on the work and research of [Joh
## 📄 License
This project is licensed under the terms of the MIT open source license. Please refer to the [LICENSE](./LICENSE) file for the full terms.
+
diff --git a/SECURITY.md b/SECURITY.md
index 4279c87f..67a9cbf2 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -28,4 +28,4 @@ This information will help us triage your report more quickly.
## Policy
-See [GitHub's Safe Harbor Policy](https://docs.github.com/en/site-policy/security-policies/github-bug-bounty-program-legal-safe-harbor#1-safe-harbor-terms)
\ No newline at end of file
+See [GitHub's Safe Harbor Policy](https://docs.github.com/en/site-policy/security-policies/github-bug-bounty-program-legal-safe-harbor#1-safe-harbor-terms)
diff --git a/SUPPORT.md b/SUPPORT.md
index 791d0104..c75ce9bd 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -17,3 +17,4 @@ For help or questions about using this project, please:
## GitHub Support Policy
Support for this project is limited to the resources listed above.
+
diff --git a/docs/.gitignore b/docs/.gitignore
index 614670d9..68fec76e 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -6,3 +6,4 @@ obj/
# Temporary files
*.tmp
*.log
+
diff --git a/docs/README.md b/docs/README.md
index 5501adf0..7a155cfa 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -31,3 +31,4 @@ To build the documentation locally:
## Deployment
Documentation is automatically built and deployed to GitHub Pages when changes are pushed to the `main` branch. The workflow is defined in `.github/workflows/docs.yml`.
+
diff --git a/docs/docfx.json b/docs/docfx.json
index c59dedbe..dca3f0f5 100644
--- a/docs/docfx.json
+++ b/docs/docfx.json
@@ -68,3 +68,4 @@
}
}
}
+
diff --git a/docs/index.md b/docs/index.md
index 9a10e7ca..e134404e 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -60,3 +60,4 @@ Please see our [Contributing Guide](https://github.com/github/spec-kit/blob/main
## Support
For support, please check our [Support Guide](https://github.com/github/spec-kit/blob/main/SUPPORT.md) or open an issue on GitHub.
+
diff --git a/docs/installation.md b/docs/installation.md
index 253e5b8b..d4dfaa3d 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -87,3 +87,4 @@ git config --global credential.helper manager
echo "Cleaning up..."
rm gcm-linux_amd64.2.6.1.deb
```
+
diff --git a/docs/local-development.md b/docs/local-development.md
index 58f174be..bed67b3d 100644
--- a/docs/local-development.md
+++ b/docs/local-development.md
@@ -166,3 +166,4 @@ rm -rf .venv dist build *.egg-info
- Open a PR when satisfied
- (Optional) Tag a release once changes land in `main`
+
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 06d6e04c..0ad5f6e3 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -120,3 +120,4 @@ implement specs/002-create-taskify/plan.md
- Read the complete methodology for in-depth guidance
- Check out more examples in the repository
- Explore the source code on GitHub
+
diff --git a/docs/toc.yml b/docs/toc.yml
index ecabd185..082bb8c8 100644
--- a/docs/toc.yml
+++ b/docs/toc.yml
@@ -15,3 +15,4 @@
items:
- name: Local Development
href: local-development.md
+
diff --git a/media/bootstrap-claude-code.gif b/media/bootstrap-claude-code.gif
index ba3a7e98..bf845175 100644
Binary files a/media/bootstrap-claude-code.gif and b/media/bootstrap-claude-code.gif differ
diff --git a/media/logo_large.webp b/media/logo_large.webp
index 209e3dee..ce095f72 100644
Binary files a/media/logo_large.webp and b/media/logo_large.webp differ
diff --git a/media/logo_small.webp b/media/logo_small.webp
index 95b5efc3..e256f4ed 100644
Binary files a/media/logo_small.webp and b/media/logo_small.webp differ
diff --git a/media/spec-kit-video-header.jpg b/media/spec-kit-video-header.jpg
index 783eee9c..9a7fa84f 100644
Binary files a/media/spec-kit-video-header.jpg and b/media/spec-kit-video-header.jpg differ
diff --git a/media/specify_cli.gif b/media/specify_cli.gif
index 70aae2d6..555baa9b 100644
Binary files a/media/specify_cli.gif and b/media/specify_cli.gif differ
diff --git a/memory/constitution.md b/memory/constitution.md
index 1ed8d77a..a4670ff4 100644
--- a/memory/constitution.md
+++ b/memory/constitution.md
@@ -47,4 +47,4 @@
**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE]
-
\ No newline at end of file
+
diff --git a/pyproject.toml b/pyproject.toml
index f1a79030..567d48cd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "specify-cli"
-version = "0.0.19"
+version = "0.0.20"
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
requires-python = ">=3.11"
dependencies = [
@@ -21,3 +21,4 @@ build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/specify_cli"]
+
diff --git a/scripts/bash/check-prerequisites.sh b/scripts/bash/check-prerequisites.sh
index 354f3f11..54f32ec3 100644
--- a/scripts/bash/check-prerequisites.sh
+++ b/scripts/bash/check-prerequisites.sh
@@ -163,4 +163,4 @@ else
if $INCLUDE_TASKS; then
check_file "$TASKS" "tasks.md"
fi
-fi
\ No newline at end of file
+fi
diff --git a/scripts/bash/common.sh b/scripts/bash/common.sh
index 04e368d4..6931eccc 100644
--- a/scripts/bash/common.sh
+++ b/scripts/bash/common.sh
@@ -153,3 +153,4 @@ EOF
check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }
+
diff --git a/scripts/bash/create-new-feature.sh b/scripts/bash/create-new-feature.sh
index 5cb17fab..510f6204 100644
--- a/scripts/bash/create-new-feature.sh
+++ b/scripts/bash/create-new-feature.sh
@@ -3,18 +3,46 @@
set -e
JSON_MODE=false
+SHORT_NAME=""
ARGS=()
-for arg in "$@"; do
+i=0
+while [ $i -lt $# ]; do
+ arg="${!i}"
case "$arg" in
- --json) JSON_MODE=true ;;
- --help|-h) echo "Usage: $0 [--json] "; exit 0 ;;
- *) ARGS+=("$arg") ;;
+ --json)
+ JSON_MODE=true
+ ;;
+ --short-name)
+ if [ $((i + 1)) -ge $# ]; then
+ echo 'Error: --short-name requires a value' >&2
+ exit 1
+ fi
+ i=$((i + 1))
+ SHORT_NAME="${!i}"
+ ;;
+ --help|-h)
+ echo "Usage: $0 [--json] [--short-name ] "
+ echo ""
+ echo "Options:"
+ echo " --json Output in JSON format"
+ echo " --short-name Provide a custom short name (2-4 words) for the branch"
+ echo " --help, -h Show this help message"
+ echo ""
+ echo "Examples:"
+ echo " $0 'Add user authentication system' --short-name 'user-auth'"
+ echo " $0 'Implement OAuth2 integration for API'"
+ exit 0
+ ;;
+ *)
+ ARGS+=("$arg")
+ ;;
esac
+ i=$((i + 1))
done
FEATURE_DESCRIPTION="${ARGS[*]}"
if [ -z "$FEATURE_DESCRIPTION" ]; then
- echo "Usage: $0 [--json] " >&2
+ echo "Usage: $0 [--json] [--short-name ] " >&2
exit 1
fi
@@ -67,9 +95,84 @@ fi
NEXT=$((HIGHEST + 1))
FEATURE_NUM=$(printf "%03d" "$NEXT")
-BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//')
-WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//')
-BRANCH_NAME="${FEATURE_NUM}-${WORDS}"
+# Function to generate branch name with stop word filtering and length filtering
+generate_branch_name() {
+ local description="$1"
+
+ # Common stop words to filter out
+ local stop_words="^(i|a|an|the|to|for|of|in|on|at|by|with|from|is|are|was|were|be|been|being|have|has|had|do|does|did|will|would|should|could|can|may|might|must|shall|this|that|these|those|my|your|our|their|want|need|add|get|set)$"
+
+ # Convert to lowercase and split into words
+ local clean_name=$(echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g')
+
+ # Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
+ local meaningful_words=()
+ for word in $clean_name; do
+ # Skip empty words
+ [ -z "$word" ] && continue
+
+ # Keep words that are NOT stop words AND (length >= 3 OR are potential acronyms)
+ if ! echo "$word" | grep -qiE "$stop_words"; then
+ if [ ${#word} -ge 3 ]; then
+ meaningful_words+=("$word")
+ elif echo "$description" | grep -q "\b${word^^}\b"; then
+ # Keep short words if they appear as uppercase in original (likely acronyms)
+ meaningful_words+=("$word")
+ fi
+ fi
+ done
+
+ # If we have meaningful words, use first 3-4 of them
+ if [ ${#meaningful_words[@]} -gt 0 ]; then
+ local max_words=3
+ if [ ${#meaningful_words[@]} -eq 4 ]; then max_words=4; fi
+
+ local result=""
+ local count=0
+ for word in "${meaningful_words[@]}"; do
+ if [ $count -ge $max_words ]; then break; fi
+ if [ -n "$result" ]; then result="$result-"; fi
+ result="$result$word"
+ count=$((count + 1))
+ done
+ echo "$result"
+ else
+ # Fallback to original logic if no meaningful words found
+ echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//' | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//'
+ fi
+}
+
+# Generate branch name
+if [ -n "$SHORT_NAME" ]; then
+ # Use provided short name, just clean it up
+ BRANCH_SUFFIX=$(echo "$SHORT_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//')
+else
+ # Generate from description with smart filtering
+ BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION")
+fi
+
+BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}"
+
+# GitHub enforces a 244-byte limit on branch names
+# Validate and truncate if necessary
+MAX_BRANCH_LENGTH=244
+if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
+ # Calculate how much we need to trim from suffix
+ # Account for: feature number (3) + hyphen (1) = 4 chars
+ MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4))
+
+ # Truncate suffix at word boundary if possible
+ TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH)
+ # Remove trailing hyphen if truncation created one
+ TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
+
+ ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
+ BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}"
+
+ >&2 echo "[specify] Warning: Branch name exceeded GitHub's 244-byte limit"
+ >&2 echo "[specify] Original: $ORIGINAL_BRANCH_NAME (${#ORIGINAL_BRANCH_NAME} bytes)"
+ >&2 echo "[specify] Truncated to: $BRANCH_NAME (${#BRANCH_NAME} bytes)"
+fi
if [ "$HAS_GIT" = true ]; then
git checkout -b "$BRANCH_NAME"
@@ -94,4 +197,4 @@ else
echo "SPEC_FILE: $SPEC_FILE"
echo "FEATURE_NUM: $FEATURE_NUM"
echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
-fi
+fi
\ No newline at end of file
diff --git a/scripts/bash/setup-plan.sh b/scripts/bash/setup-plan.sh
index 654ba50d..740a1438 100644
--- a/scripts/bash/setup-plan.sh
+++ b/scripts/bash/setup-plan.sh
@@ -58,3 +58,4 @@ else
echo "BRANCH: $CURRENT_BRANCH"
echo "HAS_GIT: $HAS_GIT"
fi
+
diff --git a/scripts/bash/update-agent-context.sh b/scripts/bash/update-agent-context.sh
index 1a7da11a..ba10ec2f 100644
--- a/scripts/bash/update-agent-context.sh
+++ b/scripts/bash/update-agent-context.sh
@@ -736,3 +736,4 @@ main() {
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
+
diff --git a/scripts/powershell/check-prerequisites.ps1 b/scripts/powershell/check-prerequisites.ps1
index d8ccd1d5..91667e9e 100644
--- a/scripts/powershell/check-prerequisites.ps1
+++ b/scripts/powershell/check-prerequisites.ps1
@@ -145,4 +145,4 @@ if ($Json) {
if ($IncludeTasks) {
Test-FileExists -Path $paths.TASKS -Description 'tasks.md' | Out-Null
}
-}
\ No newline at end of file
+}
diff --git a/scripts/powershell/common.ps1 b/scripts/powershell/common.ps1
index c8e34b26..b0be2735 100644
--- a/scripts/powershell/common.ps1
+++ b/scripts/powershell/common.ps1
@@ -134,3 +134,4 @@ function Test-DirHasFiles {
return $false
}
}
+
diff --git a/scripts/powershell/create-new-feature.ps1 b/scripts/powershell/create-new-feature.ps1
index 0f1f5912..83e286ac 100644
--- a/scripts/powershell/create-new-feature.ps1
+++ b/scripts/powershell/create-new-feature.ps1
@@ -3,20 +3,39 @@
[CmdletBinding()]
param(
[switch]$Json,
+ [string]$ShortName,
+ [switch]$Help,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$FeatureDescription
)
$ErrorActionPreference = 'Stop'
+# Show help if requested
+if ($Help) {
+ Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] "
+ Write-Host ""
+ Write-Host "Options:"
+ Write-Host " -Json Output in JSON format"
+ Write-Host " -ShortName Provide a custom short name (2-4 words) for the branch"
+ Write-Host " -Help Show this help message"
+ Write-Host ""
+ Write-Host "Examples:"
+ Write-Host " ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'"
+ Write-Host " ./create-new-feature.ps1 'Implement OAuth2 integration for API'"
+ exit 0
+}
+
+# Check if feature description provided
if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) {
- Write-Error "Usage: ./create-new-feature.ps1 [-Json] "
+ Write-Error "Usage: ./create-new-feature.ps1 [-Json] [-ShortName ] "
exit 1
}
+
$featureDesc = ($FeatureDescription -join ' ').Trim()
# Resolve repository root. Prefer git information when available, but fall back
# to searching for repository markers so the workflow still functions in repositories that
-# were initialised with --no-git.
+# were initialized with --no-git.
function Find-RepositoryRoot {
param(
[string]$StartDir,
@@ -72,9 +91,82 @@ if (Test-Path $specsDir) {
$next = $highest + 1
$featureNum = ('{0:000}' -f $next)
-$branchName = $featureDesc.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', ''
-$words = ($branchName -split '-') | Where-Object { $_ } | Select-Object -First 3
-$branchName = "$featureNum-$([string]::Join('-', $words))"
+# Function to generate branch name with stop word filtering and length filtering
+function Get-BranchName {
+ param([string]$Description)
+
+ # Common stop words to filter out
+ $stopWords = @(
+ 'i', 'a', 'an', 'the', 'to', 'for', 'of', 'in', 'on', 'at', 'by', 'with', 'from',
+ 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
+ 'do', 'does', 'did', 'will', 'would', 'should', 'could', 'can', 'may', 'might', 'must', 'shall',
+ 'this', 'that', 'these', 'those', 'my', 'your', 'our', 'their',
+ 'want', 'need', 'add', 'get', 'set'
+ )
+
+ # Convert to lowercase and extract words (alphanumeric only)
+ $cleanName = $Description.ToLower() -replace '[^a-z0-9\s]', ' '
+ $words = $cleanName -split '\s+' | Where-Object { $_ }
+
+ # Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
+ $meaningfulWords = @()
+ foreach ($word in $words) {
+ # Skip stop words
+ if ($stopWords -contains $word) { continue }
+
+ # Keep words that are length >= 3 OR appear as uppercase in original (likely acronyms)
+ if ($word.Length -ge 3) {
+ $meaningfulWords += $word
+ } elseif ($Description -match "\b$($word.ToUpper())\b") {
+ # Keep short words if they appear as uppercase in original (likely acronyms)
+ $meaningfulWords += $word
+ }
+ }
+
+ # If we have meaningful words, use first 3-4 of them
+ if ($meaningfulWords.Count -gt 0) {
+ $maxWords = if ($meaningfulWords.Count -eq 4) { 4 } else { 3 }
+ $result = ($meaningfulWords | Select-Object -First $maxWords) -join '-'
+ return $result
+ } else {
+ # Fallback to original logic if no meaningful words found
+ $result = $Description.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', ''
+ $fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3
+ return [string]::Join('-', $fallbackWords)
+ }
+}
+
+# Generate branch name
+if ($ShortName) {
+ # Use provided short name, just clean it up
+ $branchSuffix = $ShortName.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', ''
+} else {
+ # Generate from description with smart filtering
+ $branchSuffix = Get-BranchName -Description $featureDesc
+}
+
+$branchName = "$featureNum-$branchSuffix"
+
+# GitHub enforces a 244-byte limit on branch names
+# Validate and truncate if necessary
+$maxBranchLength = 244
+if ($branchName.Length -gt $maxBranchLength) {
+ # Calculate how much we need to trim from suffix
+ # Account for: feature number (3) + hyphen (1) = 4 chars
+ $maxSuffixLength = $maxBranchLength - 4
+
+ # Truncate suffix
+ $truncatedSuffix = $branchSuffix.Substring(0, [Math]::Min($branchSuffix.Length, $maxSuffixLength))
+ # Remove trailing hyphen if truncation created one
+ $truncatedSuffix = $truncatedSuffix -replace '-$', ''
+
+ $originalBranchName = $branchName
+ $branchName = "$featureNum-$truncatedSuffix"
+
+ Write-Warning "[specify] Branch name exceeded GitHub's 244-byte limit"
+ Write-Warning "[specify] Original: $originalBranchName ($($originalBranchName.Length) bytes)"
+ Write-Warning "[specify] Truncated to: $branchName ($($branchName.Length) bytes)"
+}
if ($hasGit) {
try {
@@ -115,3 +207,4 @@ if ($Json) {
Write-Output "HAS_GIT: $hasGit"
Write-Output "SPECIFY_FEATURE environment variable set to: $branchName"
}
+
diff --git a/scripts/powershell/setup-plan.ps1 b/scripts/powershell/setup-plan.ps1
index d0ed582f..db6e9f2d 100644
--- a/scripts/powershell/setup-plan.ps1
+++ b/scripts/powershell/setup-plan.ps1
@@ -59,3 +59,4 @@ if ($Json) {
Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
Write-Output "HAS_GIT: $($paths.HAS_GIT)"
}
+
diff --git a/scripts/powershell/update-agent-context.ps1 b/scripts/powershell/update-agent-context.ps1
index c1a40bf5..2fb4abe4 100644
--- a/scripts/powershell/update-agent-context.ps1
+++ b/scripts/powershell/update-agent-context.ps1
@@ -434,3 +434,4 @@ function Main {
}
Main
+
diff --git a/spec-driven.md b/spec-driven.md
index 0e546ff3..13edc9e3 100644
--- a/spec-driven.md
+++ b/spec-driven.md
@@ -401,3 +401,4 @@ By embedding these principles into the specification and planning process, SDD e
This isn't about replacing developers or automating creativity. It's about amplifying human capability by automating mechanical translation. It's about creating a tight feedback loop where specifications, research, and code evolve together, each iteration bringing deeper understanding and better alignment between intent and implementation.
Software development needs better tools for maintaining alignment between intent and implementation. SDD provides the methodology for achieving this alignment through executable specifications that generate code rather than merely guiding it.
+
diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py
index 12c3eeef..56a7bf6e 100644
--- a/src/specify_cli/__init__.py
+++ b/src/specify_cli/__init__.py
@@ -1123,3 +1123,4 @@ def main():
if __name__ == "__main__":
main()
+
diff --git a/templates/agent-file-template.md b/templates/agent-file-template.md
index 2301e0ea..f7349979 100644
--- a/templates/agent-file-template.md
+++ b/templates/agent-file-template.md
@@ -20,4 +20,4 @@ Auto-generated from all feature plans. Last updated: [DATE]
[LAST 3 FEATURES AND WHAT THEY ADDED]
-
\ No newline at end of file
+
diff --git a/templates/checklist-template.md b/templates/checklist-template.md
index 806657da..1c8b11a1 100644
--- a/templates/checklist-template.md
+++ b/templates/checklist-template.md
@@ -38,3 +38,4 @@
- Add comments or findings inline
- Link to relevant resources or documentation
- Items are numbered sequentially for easy reference
+
diff --git a/templates/commands/analyze.md b/templates/commands/analyze.md
index 473339fc..82957e5e 100644
--- a/templates/commands/analyze.md
+++ b/templates/commands/analyze.md
@@ -185,3 +185,4 @@ Ask the user: "Would you like me to suggest concrete remediation edits for the t
## Context
{ARGS}
+
diff --git a/templates/commands/checklist.md b/templates/commands/checklist.md
index 036988d0..0900e33a 100644
--- a/templates/commands/checklist.md
+++ b/templates/commands/checklist.md
@@ -288,3 +288,4 @@ Sample items:
- Correct: Validation of requirement quality
- Wrong: "Does it do X?"
- Correct: "Is X clearly specified?"
+
diff --git a/templates/commands/clarify.md b/templates/commands/clarify.md
index 4eb8e7cd..65f2536f 100644
--- a/templates/commands/clarify.md
+++ b/templates/commands/clarify.md
@@ -177,3 +177,4 @@ Behavior rules:
- If quota reached with unresolved high-impact categories remaining, explicitly flag them under Deferred with rationale.
Context for prioritization: {ARGS}
+
diff --git a/templates/commands/constitution.md b/templates/commands/constitution.md
index f6f8b243..dc079345 100644
--- a/templates/commands/constitution.md
+++ b/templates/commands/constitution.md
@@ -75,3 +75,4 @@ If the user supplies partial updates (e.g., only one principle revision), still
If critical info missing (e.g., ratification date truly unknown), insert `TODO(): explanation` and include in the Sync Impact Report under deferred items.
Do not create a new template; always operate on the existing `/memory/constitution.md` file.
+
diff --git a/templates/commands/implement.md b/templates/commands/implement.md
index 8e8e0efe..c4e7c17b 100644
--- a/templates/commands/implement.md
+++ b/templates/commands/implement.md
@@ -129,3 +129,4 @@ You **MUST** consider the user input before proceeding (if not empty).
- Report final status with summary of completed work
Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/tasks` first to regenerate the task list.
+
diff --git a/templates/commands/plan.md b/templates/commands/plan.md
index 42bb6023..2891e221 100644
--- a/templates/commands/plan.md
+++ b/templates/commands/plan.md
@@ -84,3 +84,4 @@ You **MUST** consider the user input before proceeding (if not empty).
- Use absolute paths
- ERROR on gate failures or unresolved clarifications
+
diff --git a/templates/commands/specify.md b/templates/commands/specify.md
index 7f5f1799..a75ad280 100644
--- a/templates/commands/specify.md
+++ b/templates/commands/specify.md
@@ -19,11 +19,32 @@ The text the user typed after `/speckit.specify` in the triggering message **is*
Given that feature description, do this:
-1. Run the script `{SCRIPT}` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
- **IMPORTANT** You must only ever run this script once. The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
-2. Load `templates/spec-template.md` to understand required sections.
+1. **Generate a concise short name** (2-4 words) for the branch:
+ - Analyze the feature description and extract the most meaningful keywords
+ - Create a 2-4 word short name that captures the essence of the feature
+ - Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug")
+ - Preserve technical terms and acronyms (OAuth2, API, JWT, etc.)
+ - Keep it concise but descriptive enough to understand the feature at a glance
+ - Examples:
+ - "I want to add user authentication" → "user-auth"
+ - "Implement OAuth2 integration for the API" → "oauth2-api-integration"
+ - "Create a dashboard for analytics" → "analytics-dashboard"
+ - "Fix payment processing timeout bug" → "fix-payment-timeout"
-3. Follow this execution flow:
+2. Run the script `{SCRIPT}` from repo root **with the short-name argument** and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
+
+ **IMPORTANT**:
+
+ - Append the short-name argument to the `{SCRIPT}` command with the 2-4 word short name you created in step 1
+ - Bash: `--short-name "your-generated-short-name"`
+ - PowerShell: `-ShortName "your-generated-short-name"`
+ - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot")
+ - You must only ever run this script once
+ - The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for
+
+3. Load `templates/spec-template.md` to understand required sections.
+
+4. Follow this execution flow:
1. Parse user description from Input
If empty: ERROR "No feature description provided"
@@ -49,9 +70,9 @@ Given that feature description, do this:
7. Identify Key Entities (if data involved)
8. Return: SUCCESS (spec ready for planning)
-4. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
+5. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
-5. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
+6. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
a. **Create Spec Quality Checklist**: Generate a checklist file at `FEATURE_DIR/checklists/requirements.md` using the checklist template structure with these validation items:
@@ -143,7 +164,7 @@ Given that feature description, do this:
d. **Update Checklist**: After each validation iteration, update the checklist file with current pass/fail status
-6. Report completion with branch name, spec file path, checklist results, and readiness for the next phase (`/speckit.clarify` or `/speckit.plan`).
+7. Report completion with branch name, spec file path, checklist results, and readiness for the next phase (`/speckit.clarify` or `/speckit.plan`).
**NOTE:** The script creates and checks out the new branch and initializes the spec file before writing.
@@ -209,3 +230,4 @@ Success criteria must be:
- "Database can handle 1000 TPS" (implementation detail, use user-facing metric)
- "React components render efficiently" (framework-specific)
- "Redis cache hit rate above 80%" (technology-specific)
+
diff --git a/templates/commands/tasks.md b/templates/commands/tasks.md
index 05b2effe..96464009 100644
--- a/templates/commands/tasks.md
+++ b/templates/commands/tasks.md
@@ -130,3 +130,4 @@ Every task MUST strictly follow this format:
- Each phase should be a complete, independently testable increment
- **Final Phase**: Polish & Cross-Cutting Concerns
+
diff --git a/templates/plan-template.md b/templates/plan-template.md
index 70fa8f97..43460c32 100644
--- a/templates/plan-template.md
+++ b/templates/plan-template.md
@@ -102,3 +102,4 @@ directories captured above]
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
+
diff --git a/templates/spec-template.md b/templates/spec-template.md
index c67d9149..9a83ac68 100644
--- a/templates/spec-template.md
+++ b/templates/spec-template.md
@@ -113,3 +113,4 @@
- **SC-002**: [Measurable metric, e.g., "System handles 1000 concurrent users without degradation"]
- **SC-003**: [User satisfaction metric, e.g., "90% of users successfully complete primary task on first attempt"]
- **SC-004**: [Business metric, e.g., "Reduce support tickets related to [X] by 50%"]
+
diff --git a/templates/tasks-template.md b/templates/tasks-template.md
index 66fdd810..eea131fd 100644
--- a/templates/tasks-template.md
+++ b/templates/tasks-template.md
@@ -248,3 +248,4 @@ With multiple developers:
- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence
+
diff --git a/templates/vscode-settings.json b/templates/vscode-settings.json
index 388adcec..d454aa6d 100644
--- a/templates/vscode-settings.json
+++ b/templates/vscode-settings.json
@@ -11,3 +11,4 @@
".specify/scripts/powershell/": true
}
}
+