Git operations, shell scripting, CI/CD pipeline configuration, and terminal automation. Use it for conventional commits, PowerShell/Bash scripting, configuring GitHub Actions, or automating developer tooling workflows.
Comprehensive toolkit for Git workflows, shell scripting, and development automation.
Use symptom -> action triggers: when one matches, apply this skill and verify with the protocol below.
The conventional commit specification provides an easy-to-extend set of rules for creating an explicit commit history.
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
| Type | Purpose | Example |
|-------|---------|---------|
| feat | New feature | feat(auth): add OAuth2 support |
| fix | Bug fix | fix(api): resolve null reference |
| docs | Documentation only | docs(readme): update setup guide |
| style | Formatting/style (no logic) | style(ui): fix indentation |
| refactor | Refactor production code | refactor(svc): extract helpers |
| perf | Performance improvement | perf(db): add index on email |
| test | Adding tests | test(auth): add unit tests |
| build | Build system or deps | build(ci): upgrade Node to v20 |
| ci | CI configuration changes | ci(github): add workflow for PRs |
| chore | Maintenance tasks | chore(deps): update packages |
| revert | Revert previous commit | revert: feat(login) |
Breaking changes must be indicated by ! after the type/scope, or via BREAKING CHANGE in footer:
feat(api)!: remove deprecated v1 endpoint
feat(api): remove deprecated v1 endpoint
BREAKING CHANGE: v1 endpoints are no longer supported. Use v2.
feat(auth): implement JWT refresh tokens
fix(ui): resolve mobile navigation overlap issue
docs(api): add authentication examples
refactor(user): extract validation logic to separate module
perf(images): implement lazy loading
feat(core)!: change data structure from array to object
git checkout -b feature/PROJ-123/user-auth
git checkout develop
git branch -d feature/PROJ-123/user-auth
git push origin --delete feature/PROJ-123/user-auth
git branch -m new-name
git branch -a
git add .
git add file1.ts file2.ts
git add -i
git commit -m "feat(auth): add OAuth2 support"
git commit --amend
git log --oneline --graph --all
git show <commit-hash>
git merge feature/new-feature
git rebase develop
git rebase -i HEAD~3
git rebase --abort
git merge --abort
git rebase --continue
git merge --continue
git status
vim conflicting-file.ts
git add conflicting-file.ts
git commit # for merges
git rebase --continue # for rebases
git stash push -m "Work in progress"
git stash pop
git stash apply stash@{2}
git stash list
git stash drop stash@{2}
git stash clear
git tag -a v1.0.0 -m "Release v1.0.0"
git tag v1.0.0
git tag
git push origin --tags
git push origin v1.0.0
git tag -d v1.0.0
git push origin --delete v1.0.0
git diff
git diff --staged
git diff src/app.ts
git diff HEAD~2 HEAD
git log --oneline v1.0.0..v2.0.0
git diff --stat
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
git config --global init.defaultBranch main
git config --global commit.gpgsign true
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --unset user.name
git config --list
Always enable strict mode at the top of scripts:
#!/bin/bash
set -euo pipefail
-e: Exit on first error-u: Treat unset variables as errors-o pipefail: Surface pipeline failurescleanup() {
# Remove temporary files
if [[ -n "${TEMP_DIR:-}" && -d "$TEMP_DIR" ]]; then
rm -rf "$TEMP_DIR"
fi
# Close connections
if [[ -n "${CONNECTION:-}" ]]; then
echo "Closing connection..."
# connection close logic
fi
}
trap cleanup EXIT
trap 'echo "Interrupted"; cleanup; exit 1' INT TERM
validate_requirements() {
local errors=0
# Check required variables
if [[ -z "${RESOURCE_GROUP:-}" ]]; then
echo "Error: RESOURCE_GROUP environment variable not set" >&2
((errors++))
fi
# Check required commands
for cmd in curl jq az; do
if ! command -v "$cmd" &> /dev/null; then
echo "Error: $cmd is not installed" >&2
((errors++))
fi
done
# Return appropriate exit code
return $errors
}
if ! validate_requirements; then
exit 1
fi
echo "Config: ${CONFIG_FILE:-./config.default.yaml}"
name="World"
echo "Hello, ${name}!"
apps=("app1" "app2" "app3")
for app in "${apps[@]}"; do
echo "Processing: $app"
done
declare -A config
config[host]="localhost"
config[port]="8080"
echo "Connecting to ${config[host]}:${config[port]}"
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "Linux detected"
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo "macOS detected"
else
echo "Unknown OS"
fi
case "$1" in
start)
echo "Starting service..."
;;
stop)
echo "Stopping service..."
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
;;
esac
for i in {1..5}; do
echo "Iteration $i"
done
timeout=30
elapsed=0
while [[ $elapsed -lt $timeout ]]; do
if check_ready; then
echo "Service ready"
break
fi
sleep 1
((elapsed++))
done
result=$(curl -s "https://api.example.com/data")
name=$(echo "$result" | jq -r '.name')
count=$(echo "$result" | jq '.items | length')
first_item=$(echo "$result" | jq -r '.items[0]')
active_users=$(echo "$result" | jq '.users[] | select(.status == "active")')
read -r first_name last_name email <<<$(echo "$result" | jq -r '"\(.firstName) \(.lastName) \(.email)"')
echo "$result" | jq '.count += 1' > updated.json
jq -n \
--arg name "John" \
--arg age "30" \
'{name: $name, age: ($age | tonumber)}'
#!/bin/bash
verbose=0
output_file="output.txt"
config="./config.yaml"
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose)
verbose=1
shift
;;
-o|--output)
output_file="$2"
shift 2
;;
-c|--config)
config="$2"
shift 2
;;
-h|--help)
show_help
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
echo "Config: $config"
echo "Output: $output_file"
echo "Verbose: $verbose"
if [[ -f "$FILE_PATH" ]]; then
echo "File exists"
fi
if [[ ! -d "$DIR_PATH" ]]; then
mkdir -p "$DIR_PATH"
fi
mkdir -p ./dir1/dir2
cp -r source_dir/ dest_dir/
rm -f file.txt # Force delete file
rm -rf directory/ # Recursive delete directory
find . -name "*.py" # All Python files
find . -type f -name "*.js" # All JS files (regular files only)
find . -mtime -7 # Modified in last 7 days
temp_file=$(mktemp)
echo "data" > "$temp_file"
rm -f "$temp_file"
temp_dir=$(mktemp -d)
rm -rf "$temp_dir"
if pgrep -x "nginx" > /dev/null; then
echo "Nginx is running"
else
echo "Nginx is not running"
fi
while pgrep -x "script-name" > /dev/null; do
sleep 1
done
timeout 30s ./long-running-script.sh || echo "Timed out after 30s"
./script.sh &
job_pid=$!
trap "kill $job_pid 2>/dev/null" EXIT
#!/bin/bash
LOG_INFO() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*"
}
LOG_WARN() {
echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}
LOG_ERROR() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2
}
LOG_DEBUG() {
if [[ "${DEBUG:-}" == "1" ]]; then
echo "[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $*"
fi
}
LOG_INFO "Starting deployment"
LOG_WARN "This is a warning"
LOG_ERROR "Deployment failed"
LOG_DEBUG "Detailed debugging info"
Get-ChildItem, not dir)"C:\Path With Spaces\file.txt"ShouldProcess for destructive operations
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
try {
$result = Invoke-RestMethod -Uri "https://api.example.com/data" -Method Get
}
catch [System.Net.WebException] {
Write-Error "Network error occurred: $($_.Exception.Message)"
exit 1
}
catch {
Write-Error "Unexpected error: $($_.Exception.Message)"
exit 1
}
finally {
# Cleanup code always runs
Write-Output "Execution completed"
}
trap {
Write-Error "Script failed: $_"
# Cleanup code
Remove-Variable -Name tempVar -ErrorAction SilentlyContinue
exit 1
}
param(
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$false)]
[string]$Path = ".",
[Parameter(Mandatory=$false)]
[switch]$Verbose,
[ValidateSet("dev", "staging", "prod")]
[string]$Environment = "dev"
)
Write-Output "Name: $Name"
Write-Output "Path: $Path"
Write-Output "Environment: $Environment"
Write-Output "Verbose: $Verbose"
$user = [PSCustomObject]@{
Name = "John"
Age = 30
Email = "john@example.com",
Address = "123 Main St"
}
Write-Output $user.Name
$user | Add-Member -MemberType NoteProperty -Name "City" -Value "Anytown"
$users | Where-Object { $_.Age -gt 25 }
$users | Select-Object Name, Email
$users | Sort-Object Name
$users | Group-Object City
$json = '{"name": "John", "age": 30}'
$obj = $json | ConvertFrom-Json
Write-Output $obj.name
$data = @{ name = "John"; age = 30 }
$json = $data | ConvertTo-Json -Depth 10
Write-Output $json
$config = Get-Content "config.json" | ConvertFrom-Json
$config | ConvertTo-Json -Depth 10 | Set-Content "config.json"
$files = @("file1.txt", "file2.txt", "file3.txt")
$files += "file4.txt"
$filtered = $files | Where-Object { $_ -like "*.txt" }
$config = @{
host = "localhost"
port = 8080
tls = $true
}
Write-Output $config.host
$key = "port"
Write-Output $config[$key]
foreach ($item in $config.GetEnumerator()) {
Write-Output "$($item.Name) = $($item.Value)"
}
if (Test-Path "C:\path\to\file.txt") {
Write-Output "File exists"
}
New-Item -ItemType Directory -Path "C:\new\dir" -Force
Remove-Item "C:\path\to\file.txt" -Force
Remove-Item "C:\path\to\directory" -Recurse -Force
Copy-Item "source.txt" "destination.txt" -Force
Copy-Item "dir\" "backup\" -Recurse
Move-Item "old_name.txt" "new_name.txt"
$content = Get-Content "file.txt"
$content = Get-Content "file.txt" -Raw # As single string
$content | Set-Content "file.txt"
"more content" | Add-Content "file.txt"
$name = "John"
Write-Output "Hello, $name!"
Write-Output ("Hello, {0}! Your score is {1:N2}" -f $name, 95.5)
$string = " Hello World "
$trimmed = $string.Trim()
$replaced = $string.Replace("World", "PowerShell")
if ($string -like "*World*") {
Write-Output "Contains 'World'"
}
if ($string -match "^Hello") {
Write-Output "Starts with 'Hello'"
}
$parts = "a,b,c".Split(",")
name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
workflow_dispatch: # Allow manual trigger
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
build:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: build
- name: Deploy to Azure
run: az webapp up --name myapp --resource-group myrg
trigger:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
packageFolder: '$(build.artifactStagingDirectory)/package'
stages:
- stage: Build
displayName: 'Build stage'
jobs:
- job: Build
displayName: 'Build job'
steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'
- script: |
npm ci
displayName: 'Install dependencies'
- script: |
npm run build
displayName: 'Build application'
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: 'dist'
includeRootFolder: false
archiveType: 'zip'
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Archive build artifacts'
- publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
- stage: Deploy
displayName: 'Deploy stage'
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Deploy
displayName: 'Deploy job'
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'your_subscription_id'
appName: 'your_webapp_name'
package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
set -euo pipefail)This skill is written to stay usable across GitHub Copilot, Claude Code, and Codex.
$CODEX_HOME/skills/devops-tooling and restart Codex after major changes.Preferred MCP Server: GitHub MCP
git, gh, CI logs, and shell automation scripts for repository and pipeline work.Before claiming "skill applied successfully":
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer