Skip to content
Merged
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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions SKILL.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
73 changes: 73 additions & 0 deletions scripts/install_linux.sh
Original file line number Diff line number Diff line change
@@ -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_linux.sh # Install
# ./scripts/install_linux.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
84 changes: 84 additions & 0 deletions scripts/install_macos.sh
Original file line number Diff line number Diff line change
@@ -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
113 changes: 113 additions & 0 deletions scripts/install_windows.ps1
Original file line number Diff line number Diff line change
@@ -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
}