Reorganize: Move all skills to skills/ folder
- Created skills/ directory - Moved 272 skills to skills/ subfolder - Kept agents/ at root level - Kept installation scripts and docs at root level Repository structure: - skills/ - All 272 skills from skills.sh - agents/ - Agent definitions - *.sh, *.ps1 - Installation scripts - README.md, etc. - Documentation Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "git-workflow",
|
||||
"version": "1.0.0",
|
||||
"description": "Enhanced Git workflow automation for Claude Code",
|
||||
"author": "Your Name",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/yourusername/claude-git-workflow",
|
||||
"claude": {
|
||||
"permissions": [
|
||||
"read:files",
|
||||
"write:files",
|
||||
"execute:commands"
|
||||
],
|
||||
"commands": [
|
||||
{
|
||||
"name": "git:smart-commit",
|
||||
"description": "Create an intelligent commit with auto-staging and conventional commits",
|
||||
"handler": "commands/smart-commit.ts",
|
||||
"permissions": ["execute:commands"]
|
||||
},
|
||||
{
|
||||
"name": "git:pr-create",
|
||||
"description": "Create a pull request with AI-generated description",
|
||||
"handler": "commands/pr-create.ts",
|
||||
"permissions": ["execute:commands", "network:request"]
|
||||
},
|
||||
{
|
||||
"name": "git:branch-cleanup",
|
||||
"description": "Clean up merged branches locally and remotely",
|
||||
"handler": "commands/branch-cleanup.ts",
|
||||
"permissions": ["execute:commands"]
|
||||
}
|
||||
],
|
||||
"hooks": [
|
||||
{
|
||||
"event": "PostFileEdit",
|
||||
"handler": "hooks/auto-stage.ts",
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
"event": "SessionEnd",
|
||||
"handler": "hooks/save-work.ts",
|
||||
"priority": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Branch Cleanup Command
|
||||
* Removes merged branches locally and remotely
|
||||
*/
|
||||
|
||||
import { exec } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
export interface BranchCleanupOptions {
|
||||
local?: boolean
|
||||
remote?: boolean
|
||||
exclude?: string[]
|
||||
dryRun?: boolean
|
||||
}
|
||||
|
||||
export async function handle(
|
||||
args: BranchCleanupOptions,
|
||||
context: any
|
||||
): Promise<string> {
|
||||
const { local = true, remote = true, exclude = ['main', 'master', 'develop'], dryRun = false } = args
|
||||
|
||||
const results: string[] = []
|
||||
|
||||
try {
|
||||
// Get current branch
|
||||
const { stdout: currentBranch } = await execAsync('git rev-parse --abbrev-ref HEAD')
|
||||
|
||||
if (local) {
|
||||
// Get merged local branches
|
||||
const { stdout: mergedBranches } = await execAsync('git branch --merged')
|
||||
|
||||
const branchesToDelete = mergedBranches
|
||||
.split('\n')
|
||||
.map((b) => b.trim().replace('*', '').trim())
|
||||
.filter(
|
||||
(branch) =>
|
||||
branch &&
|
||||
branch !== currentBranch.trim() &&
|
||||
!exclude.includes(branch)
|
||||
)
|
||||
|
||||
if (branchesToDelete.length > 0) {
|
||||
if (dryRun) {
|
||||
results.push(`Would delete local branches: ${branchesToDelete.join(', ')}`)
|
||||
} else {
|
||||
for (const branch of branchesToDelete) {
|
||||
await execAsync(`git branch -d ${branch}`)
|
||||
results.push(`✓ Deleted local branch: ${branch}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results.push('No local branches to clean up')
|
||||
}
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
// Get merged remote branches
|
||||
const { stdout: remoteBranches } = await execAsync('git branch -r --merged')
|
||||
|
||||
const branchesToDelete = remoteBranches
|
||||
.split('\n')
|
||||
.map((b) => b.trim().replace('origin/', '').trim())
|
||||
.filter((branch) => branch && branch !== 'HEAD' && !exclude.includes(branch))
|
||||
|
||||
if (branchesToDelete.length > 0) {
|
||||
if (dryRun) {
|
||||
results.push(`Would delete remote branches: ${branchesToDelete.join(', ')}`)
|
||||
} else {
|
||||
for (const branch of branchesToDelete) {
|
||||
await execAsync(`git push origin --delete ${branch}`)
|
||||
results.push(`✓ Deleted remote branch: ${branch}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results.push('No remote branches to clean up')
|
||||
}
|
||||
}
|
||||
|
||||
return results.join('\n')
|
||||
} catch (error: any) {
|
||||
throw new Error(`Branch cleanup failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default { handle }
|
||||
60
skills/plugins/examples/git-workflow/commands/pr-create.ts
Normal file
60
skills/plugins/examples/git-workflow/commands/pr-create.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Pull Request Creation Command
|
||||
* Creates a PR with AI-generated description
|
||||
*/
|
||||
|
||||
import { exec } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
import { readFileSync } from 'fs'
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
export interface PRCreateOptions {
|
||||
title?: string
|
||||
base?: string
|
||||
draft?: boolean
|
||||
reviewers?: string[]
|
||||
}
|
||||
|
||||
export async function handle(args: PRCreateOptions, context: any): Promise<string> {
|
||||
const { title, base = 'main', draft = false, reviewers } = args
|
||||
|
||||
try {
|
||||
// Get current branch
|
||||
const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD')
|
||||
const branch = branchOutput.trim()
|
||||
|
||||
// Get default title from branch name if not provided
|
||||
const prTitle = title || branchToTitle(branch)
|
||||
|
||||
// Get commits for description
|
||||
const { stdout: commits } = await execAsync(`git log ${base}..HEAD --oneline`)
|
||||
|
||||
// Generate description
|
||||
const description = `## Changes\n\n${commits}\n\n## Summary\n\nAutomated PR created from branch ${branch}`
|
||||
|
||||
// Create PR using gh CLI
|
||||
const draftFlag = draft ? '--draft' : ''
|
||||
const reviewersFlag = reviewers ? `--reviewer ${reviewers.join(',')}` : ''
|
||||
|
||||
const { stdout } = await execAsync(
|
||||
`gh pr create --base ${base} --title "${prTitle}" --body "${description}" ${draftFlag} ${reviewersFlag}`
|
||||
)
|
||||
|
||||
return `✓ Pull request created:\n${stdout}`
|
||||
} catch (error: any) {
|
||||
throw new Error(`PR creation failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
function branchToTitle(branch: string): string {
|
||||
return branch
|
||||
.replace(/^(feat|fix|docs|style|refactor|test|chore)\//i, '')
|
||||
.replace(/-/g, ' ')
|
||||
.replace(/_/g, ' ')
|
||||
.split(' ')
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
export default { handle }
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Git Smart Commit Command
|
||||
* Creates intelligent commits with auto-staging and conventional commits
|
||||
*/
|
||||
|
||||
import { exec } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
export interface SmartCommitOptions {
|
||||
message?: string
|
||||
type?: 'feat' | 'fix' | 'docs' | 'style' | 'refactor' | 'test' | 'chore'
|
||||
scope?: string
|
||||
stageAll?: boolean
|
||||
amend?: boolean
|
||||
}
|
||||
|
||||
export async function handle(
|
||||
args: SmartCommitOptions,
|
||||
context: any
|
||||
): Promise<string> {
|
||||
const { message, type = 'feat', scope, stageAll = true, amend = false } = args
|
||||
|
||||
try {
|
||||
// Stage files if requested
|
||||
if (stageAll && !amend) {
|
||||
await execAsync('git add -A')
|
||||
context.sandbox.log('Staged all changes')
|
||||
}
|
||||
|
||||
// Generate commit message if not provided
|
||||
let commitMessage = message
|
||||
|
||||
if (!commitMessage) {
|
||||
// Get diff to generate intelligent message
|
||||
const { stdout: diff } = await execAsync('git diff --cached --stat')
|
||||
|
||||
if (!diff || diff.trim().length === 0) {
|
||||
return 'No changes to commit'
|
||||
}
|
||||
|
||||
// Simple auto-generation based on diff
|
||||
commitMessage = `${type}${scope ? `(${scope})` : ''}: `
|
||||
commitMessage += 'update code based on changes'
|
||||
}
|
||||
|
||||
// Create commit
|
||||
const amendFlag = amend ? '--amend' : ''
|
||||
const { stdout } = await execAsync(
|
||||
`git commit ${amendFlag} -m "${commitMessage}"`
|
||||
)
|
||||
|
||||
return `✓ Committed successfully:\n${stdout}`
|
||||
} catch (error: any) {
|
||||
throw new Error(`Git commit failed: ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Export for CLI usage
|
||||
export default { handle }
|
||||
Reference in New Issue
Block a user