From 05a86a3f2c11226aeb42455c397f20ea2787959f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:47:30 +0100 Subject: [PATCH 1/6] feat: add install script for Linux Symlinks SKILL.md to ~/.claude/skills/git-workflow/ so the skill stays in sync with the repo. Supports --uninstall to remove. --- scripts/install.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 scripts/install.sh diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..43e2b37 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# Install or uninstall the git-workflow skill for Claude Code (Linux). +# Creates a symlink so the skill stays in sync with the repo. +# +# Usage: +# ./scripts/install.sh # Install +# ./scripts/install.sh --uninstall # Uninstall + +set -euo pipefail + +SKILL_DIR="$HOME/.claude/skills/git-workflow" +SKILL_FILE="$SKILL_DIR/SKILL.md" +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SOURCE="$REPO_ROOT/SKILL.md" + +info() { printf " \033[34mℹ\033[0m %s\n" "$1"; } +pass() { printf " \033[32m✓\033[0m %s\n" "$1"; } +fail() { printf " \033[31m✗\033[0m %s\n" "$1"; } + +uninstall() { + if [[ -L "$SKILL_FILE" ]]; then + rm "$SKILL_FILE" + pass "Removed symlink: $SKILL_FILE" + # Remove directory if empty + rmdir "$SKILL_DIR" 2>/dev/null && info "Removed empty directory: $SKILL_DIR" || true + elif [[ -f "$SKILL_FILE" ]]; then + fail "$SKILL_FILE exists but is not a symlink — remove it manually to avoid data loss" + exit 1 + else + info "Nothing to uninstall — $SKILL_FILE does not exist" + fi + exit 0 +} + +install() { + # Verify source exists + if [[ ! -f "$SOURCE" ]]; then + fail "SKILL.md not found at $SOURCE" + exit 1 + fi + + # Check if already installed + if [[ -L "$SKILL_FILE" ]]; then + current_target="$(readlink -f "$SKILL_FILE")" + if [[ "$current_target" == "$SOURCE" ]]; then + pass "Already installed (symlink points to $SOURCE)" + exit 0 + else + info "Existing symlink points to $current_target — replacing" + rm "$SKILL_FILE" + fi + elif [[ -f "$SKILL_FILE" ]]; then + fail "$SKILL_FILE exists but is not a symlink — remove it manually before installing" + exit 1 + fi + + # Create directory and symlink + mkdir -p "$SKILL_DIR" + ln -s "$SOURCE" "$SKILL_FILE" + pass "Installed: $SKILL_FILE → $SOURCE" + info "The skill will stay in sync with this repo. Restart Claude Code to activate." +} + +# --- Main --- +case "${1:-}" in + --uninstall) uninstall ;; + "") install ;; + *) + echo "Usage: $0 [--uninstall]" + exit 1 + ;; +esac From b7823e63aaca1f20fe975ff11120b154ef098e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:49:09 +0100 Subject: [PATCH 2/6] refactor: rename install.sh to install_linux.sh for clarity Prepares for platform-specific install scripts with consistent naming: install_linux.sh, install_macos.sh, install.ps1. --- scripts/{install.sh => install_linux.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{install.sh => install_linux.sh} (100%) diff --git a/scripts/install.sh b/scripts/install_linux.sh similarity index 100% rename from scripts/install.sh rename to scripts/install_linux.sh From be6dc326d3a8230e0f836a0b1965ef8687e094bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:49:53 +0100 Subject: [PATCH 3/6] feat: add install script for macOS Uses a portable resolve_link function instead of readlink -f which is not available on macOS without coreutils. --- scripts/install_linux.sh | 4 +- scripts/install_macos.sh | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100755 scripts/install_macos.sh diff --git a/scripts/install_linux.sh b/scripts/install_linux.sh index 43e2b37..a8d3eaa 100755 --- a/scripts/install_linux.sh +++ b/scripts/install_linux.sh @@ -4,8 +4,8 @@ # Creates a symlink so the skill stays in sync with the repo. # # Usage: -# ./scripts/install.sh # Install -# ./scripts/install.sh --uninstall # Uninstall +# ./scripts/install_linux.sh # Install +# ./scripts/install_linux.sh --uninstall # Uninstall set -euo pipefail diff --git a/scripts/install_macos.sh b/scripts/install_macos.sh new file mode 100755 index 0000000..6e5bce9 --- /dev/null +++ b/scripts/install_macos.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# +# Install or uninstall the git-workflow skill for Claude Code (macOS). +# Creates a symlink so the skill stays in sync with the repo. +# +# Usage: +# ./scripts/install_macos.sh # Install +# ./scripts/install_macos.sh --uninstall # Uninstall + +set -euo pipefail + +SKILL_DIR="$HOME/.claude/skills/git-workflow" +SKILL_FILE="$SKILL_DIR/SKILL.md" +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SOURCE="$REPO_ROOT/SKILL.md" + +info() { printf " \033[34mℹ\033[0m %s\n" "$1"; } +pass() { printf " \033[32m✓\033[0m %s\n" "$1"; } +fail() { printf " \033[31m✗\033[0m %s\n" "$1"; } + +# macOS readlink does not support -f; resolve symlink manually +resolve_link() { + local target="$1" + while [[ -L "$target" ]]; do + local dir="$(cd "$(dirname "$target")" && pwd)" + target="$(readlink "$target")" + [[ "$target" != /* ]] && target="$dir/$target" + done + echo "$(cd "$(dirname "$target")" && pwd)/$(basename "$target")" +} + +uninstall() { + if [[ -L "$SKILL_FILE" ]]; then + rm "$SKILL_FILE" + pass "Removed symlink: $SKILL_FILE" + # Remove directory if empty + rmdir "$SKILL_DIR" 2>/dev/null && info "Removed empty directory: $SKILL_DIR" || true + elif [[ -f "$SKILL_FILE" ]]; then + fail "$SKILL_FILE exists but is not a symlink — remove it manually to avoid data loss" + exit 1 + else + info "Nothing to uninstall — $SKILL_FILE does not exist" + fi + exit 0 +} + +install() { + # Verify source exists + if [[ ! -f "$SOURCE" ]]; then + fail "SKILL.md not found at $SOURCE" + exit 1 + fi + + # Check if already installed + if [[ -L "$SKILL_FILE" ]]; then + current_target="$(resolve_link "$SKILL_FILE")" + if [[ "$current_target" == "$SOURCE" ]]; then + pass "Already installed (symlink points to $SOURCE)" + exit 0 + else + info "Existing symlink points to $current_target — replacing" + rm "$SKILL_FILE" + fi + elif [[ -f "$SKILL_FILE" ]]; then + fail "$SKILL_FILE exists but is not a symlink — remove it manually before installing" + exit 1 + fi + + # Create directory and symlink + mkdir -p "$SKILL_DIR" + ln -s "$SOURCE" "$SKILL_FILE" + pass "Installed: $SKILL_FILE → $SOURCE" + info "The skill will stay in sync with this repo. Restart Claude Code to activate." +} + +# --- Main --- +case "${1:-}" in + --uninstall) uninstall ;; + "") install ;; + *) + echo "Usage: $0 [--uninstall]" + exit 1 + ;; +esac From 886ec9db14156c840222110bac8532d3a429f97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:51:22 +0100 Subject: [PATCH 4/6] feat: add install script for Windows (PowerShell) Creates symlink if Developer Mode is enabled or terminal is elevated. Falls back to file copy with a warning if symlinks are unavailable. Supports -Uninstall parameter to remove. --- scripts/install_windows.ps1 | 113 ++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 scripts/install_windows.ps1 diff --git a/scripts/install_windows.ps1 b/scripts/install_windows.ps1 new file mode 100644 index 0000000..5b5a0d9 --- /dev/null +++ b/scripts/install_windows.ps1 @@ -0,0 +1,113 @@ +<# +.SYNOPSIS + Install or uninstall the git-workflow skill for Claude Code (Windows). + +.DESCRIPTION + Creates a symlink so the skill stays in sync with the repo. + Symlinks on Windows require either Developer Mode enabled or an + elevated (Administrator) terminal. + +.PARAMETER Uninstall + Remove the skill symlink. + +.EXAMPLE + .\scripts\install_windows.ps1 + .\scripts\install_windows.ps1 -Uninstall +#> + +param( + [switch]$Uninstall +) + +$ErrorActionPreference = "Stop" + +$SkillDir = Join-Path $env:USERPROFILE ".claude\skills\git-workflow" +$SkillFile = Join-Path $SkillDir "SKILL.md" +$RepoRoot = Split-Path -Parent (Split-Path -Parent $PSCommandPath) +$Source = Join-Path $RepoRoot "SKILL.md" + +function Write-Info { param($Msg) Write-Host " i " -ForegroundColor Blue -NoNewline; Write-Host $Msg } +function Write-Pass { param($Msg) Write-Host " ✓ " -ForegroundColor Green -NoNewline; Write-Host $Msg } +function Write-Fail { param($Msg) Write-Host " ✗ " -ForegroundColor Red -NoNewline; Write-Host $Msg } + +function Test-SymlinkSupport { + $testDir = Join-Path $env:TEMP "symlink_test_$(Get-Random)" + $testLink = Join-Path $env:TEMP "symlink_test_link_$(Get-Random)" + try { + New-Item -ItemType Directory -Path $testDir -Force | Out-Null + New-Item -ItemType SymbolicLink -Path $testLink -Target $testDir -ErrorAction Stop | Out-Null + Remove-Item $testLink -Force + Remove-Item $testDir -Force + return $true + } catch { + Remove-Item $testDir -Force -ErrorAction SilentlyContinue + return $false + } +} + +function Invoke-Uninstall { + $item = Get-Item $SkillFile -ErrorAction SilentlyContinue + if ($item -and $item.Attributes -band [IO.FileAttributes]::ReparsePoint) { + Remove-Item $SkillFile -Force + Write-Pass "Removed symlink: $SkillFile" + # Remove directory if empty + if ((Get-ChildItem $SkillDir -ErrorAction SilentlyContinue | Measure-Object).Count -eq 0) { + Remove-Item $SkillDir -Force + Write-Info "Removed empty directory: $SkillDir" + } + } elseif ($item) { + Write-Fail "$SkillFile exists but is not a symlink — remove it manually to avoid data loss" + exit 1 + } else { + Write-Info "Nothing to uninstall — $SkillFile does not exist" + } + exit 0 +} + +function Invoke-Install { + # Verify source exists + if (-not (Test-Path $Source)) { + Write-Fail "SKILL.md not found at $Source" + exit 1 + } + + # Check if already installed + $item = Get-Item $SkillFile -ErrorAction SilentlyContinue + if ($item -and $item.Attributes -band [IO.FileAttributes]::ReparsePoint) { + $currentTarget = $item.Target + if ($currentTarget -eq $Source) { + Write-Pass "Already installed (symlink points to $Source)" + exit 0 + } else { + Write-Info "Existing symlink points to $currentTarget — replacing" + Remove-Item $SkillFile -Force + } + } elseif ($item) { + Write-Fail "$SkillFile exists but is not a symlink — remove it manually before installing" + exit 1 + } + + # Check symlink support + if (-not (Test-SymlinkSupport)) { + Write-Fail "Cannot create symlinks. Enable Developer Mode (Settings > For developers) or run as Administrator." + Write-Info "Falling back to file copy (will not auto-sync with repo)." + New-Item -ItemType Directory -Path $SkillDir -Force | Out-Null + Copy-Item $Source $SkillFile + Write-Pass "Installed (copy): $SkillFile" + Write-Info "Note: This is a copy, not a symlink. Re-run the installer after updates to sync." + exit 0 + } + + # Create directory and symlink + New-Item -ItemType Directory -Path $SkillDir -Force | Out-Null + New-Item -ItemType SymbolicLink -Path $SkillFile -Target $Source | Out-Null + Write-Pass "Installed: $SkillFile → $Source" + Write-Info "The skill will stay in sync with this repo. Restart Claude Code to activate." +} + +# --- Main --- +if ($Uninstall) { + Invoke-Uninstall +} else { + Invoke-Install +} From 8d694c389e3a0d3cb761692a90d9c08a4a0ec920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:53:14 +0100 Subject: [PATCH 5/6] docs: update README installation section with platform-specific scripts Replace manual cp with clone + install script instructions for Linux, macOS, and Windows. Add uninstall and manual fallback sections. --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d2cddc7..916f11e 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,56 @@ A Claude Code skill that enforces a disciplined Gitflow-based development workfl ## Installation -Copy the `SKILL.md` file to your global Claude Code skills directory: +Clone the repo and run the install script for your platform. The script creates a **symlink**, so the skill stays in sync with the repo automatically. + +### Linux + +```bash +git clone https://github.com/qubernetic-org/git-workflow-agent-skill.git +cd git-workflow-agent-skill +./scripts/install_linux.sh +``` + +### macOS + +```bash +git clone https://github.com/qubernetic-org/git-workflow-agent-skill.git +cd git-workflow-agent-skill +./scripts/install_macos.sh +``` + +### Windows (PowerShell) + +```powershell +git clone https://github.com/qubernetic-org/git-workflow-agent-skill.git +cd git-workflow-agent-skill +.\scripts\install_windows.ps1 +``` + +> **Note:** Windows symlinks require Developer Mode enabled or an elevated terminal. The script falls back to a file copy if symlinks are unavailable. + +### Uninstall + +```bash +# Linux +./scripts/install_linux.sh --uninstall + +# macOS +./scripts/install_macos.sh --uninstall +``` + +```powershell +# Windows +.\scripts\install_windows.ps1 -Uninstall +``` + +### Manual Installation + +If you prefer not to use the scripts: ```bash mkdir -p ~/.claude/skills/git-workflow -cp SKILL.md ~/.claude/skills/git-workflow/SKILL.md +ln -s "$(pwd)/SKILL.md" ~/.claude/skills/git-workflow/SKILL.md ``` The skill will be automatically discovered on the next Claude Code session. From e877e323c02ab18efdd195c71269f18dd6cc5b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Attila=20Bir=C3=B3?= Date: Fri, 27 Mar 2026 23:56:11 +0100 Subject: [PATCH 6/6] chore(release): prepare 1.3.0 --- CHANGELOG.md | 15 +++++++++++++++ README.md | 2 +- SKILL.md | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d71f0..3bfe4f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.3.0] - 2026-03-27 + +### Added + +- Install script for Linux — `scripts/install_linux.sh` (#68) +- Install script for macOS — `scripts/install_macos.sh` (#69) +- Install script for Windows — `scripts/install_windows.ps1` (#70) + +### Changed + +- Rename `install.sh` to `install_linux.sh` for consistent cross-platform naming (#69) +- Update README installation section with platform-specific scripts and uninstall instructions (#74) +- Improve CONTRIBUTING.md with development workflow and cross-platform lint guide (#63) + ## [1.2.0] - 2026-03-27 ### Added @@ -93,6 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CONTRIBUTING.md contribution guidelines - GitHub issue and PR templates +[1.3.0]: https://github.com/qubernetic-org/git-workflow-agent-skill/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/qubernetic-org/git-workflow-agent-skill/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/qubernetic-org/git-workflow-agent-skill/compare/v1.0.4...v1.1.0 [1.0.4]: https://github.com/qubernetic-org/git-workflow-agent-skill/compare/v1.0.3...v1.0.4 diff --git a/README.md b/README.md index 916f11e..889672c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Git Workflow — Claude Code Skill -[![Version](https://img.shields.io/badge/version-1.2.0-blue.svg)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-1.3.0-blue.svg)](CHANGELOG.md) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![Claude Code](https://img.shields.io/badge/Claude%20Code-skill-7c3aed.svg)](https://claude.ai/code) [![Conventional Commits](https://img.shields.io/badge/commits-conventional-fe5196.svg?logo=conventionalcommits&logoColor=white)](https://conventionalcommits.org) diff --git a/SKILL.md b/SKILL.md index 5499a6b..7ed323a 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,11 +1,11 @@ --- name: git-workflow description: "Enforce a strict Gitflow-based workflow with conventional commits, semantic versioning, and issue-driven branching. Use when the user asks to commit, create a branch, open a PR, tag a release, or perform any git operation. Also applies when mentions 'commit', 'branch', 'merge', 'release', 'hotfix', 'gitflow', 'conventional commit', 'semantic versioning', or 'semver'." -version: 1.2.0 +version: 1.3.0 license: MIT metadata: author: Qubernetic - version: 1.2.0 + version: 1.3.0 --- # Git Workflow Skill