Add Makefile for managing Claude Code config symlinks
- Move commands, scripts, settings to repo root - Add Makefile with install/uninstall/status targets - Symlinks ~/.claude/* to this repo for version control - Update documentation with setup instructions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"$schema": "https://claude.ai/claude-code/settings.schema.json"
|
||||
}
|
||||
25
CLAUDE.md
25
CLAUDE.md
@@ -2,13 +2,28 @@
|
||||
|
||||
This repository contains configurations, prompts, and tools to improve the Claude Code AI workflow.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# Clone and install symlinks
|
||||
git clone ssh://git@code.flowmade.one/flowmade-one/ai.git
|
||||
cd ai
|
||||
make install
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `.claude/` - Claude Code configuration
|
||||
- `commands/` - Custom slash commands (skills)
|
||||
- `prompts/` - Reusable prompt templates
|
||||
- `scripts/` - Automation scripts
|
||||
- `hooks/` - Claude Code hooks (pre/post tool execution)
|
||||
```
|
||||
ai/
|
||||
├── commands/ # Slash commands (/work-issue, /dashboard)
|
||||
├── skills/ # Auto-triggered capabilities
|
||||
├── agents/ # Subagents with isolated context
|
||||
├── scripts/ # Hook scripts (pre-commit, token loading)
|
||||
├── settings.json # Claude Code settings
|
||||
└── Makefile # Install/uninstall symlinks
|
||||
```
|
||||
|
||||
All files symlink to `~/.claude/` via `make install`.
|
||||
|
||||
## Forgejo Integration
|
||||
|
||||
|
||||
54
Makefile
Normal file
54
Makefile
Normal file
@@ -0,0 +1,54 @@
|
||||
.PHONY: install uninstall status
|
||||
|
||||
CLAUDE_DIR := $(HOME)/.claude
|
||||
REPO_DIR := $(shell pwd)
|
||||
|
||||
# Items to symlink
|
||||
ITEMS := commands scripts skills agents settings.json
|
||||
|
||||
install:
|
||||
@echo "Installing Claude Code config symlinks..."
|
||||
@mkdir -p $(CLAUDE_DIR)
|
||||
@for item in $(ITEMS); do \
|
||||
if [ -e "$(REPO_DIR)/$$item" ]; then \
|
||||
if [ -L "$(CLAUDE_DIR)/$$item" ]; then \
|
||||
echo " $$item: already symlinked"; \
|
||||
elif [ -e "$(CLAUDE_DIR)/$$item" ]; then \
|
||||
echo " $$item: backing up existing to $$item.bak"; \
|
||||
mv "$(CLAUDE_DIR)/$$item" "$(CLAUDE_DIR)/$$item.bak"; \
|
||||
ln -s "$(REPO_DIR)/$$item" "$(CLAUDE_DIR)/$$item"; \
|
||||
echo " $$item: symlinked"; \
|
||||
else \
|
||||
ln -s "$(REPO_DIR)/$$item" "$(CLAUDE_DIR)/$$item"; \
|
||||
echo " $$item: symlinked"; \
|
||||
fi \
|
||||
fi \
|
||||
done
|
||||
@echo "Done! Restart Claude Code to apply changes."
|
||||
|
||||
uninstall:
|
||||
@echo "Removing Claude Code config symlinks..."
|
||||
@for item in $(ITEMS); do \
|
||||
if [ -L "$(CLAUDE_DIR)/$$item" ]; then \
|
||||
rm "$(CLAUDE_DIR)/$$item"; \
|
||||
echo " $$item: removed symlink"; \
|
||||
if [ -e "$(CLAUDE_DIR)/$$item.bak" ]; then \
|
||||
mv "$(CLAUDE_DIR)/$$item.bak" "$(CLAUDE_DIR)/$$item"; \
|
||||
echo " $$item: restored backup"; \
|
||||
fi \
|
||||
fi \
|
||||
done
|
||||
@echo "Done!"
|
||||
|
||||
status:
|
||||
@echo "Claude Code config status:"
|
||||
@for item in $(ITEMS); do \
|
||||
if [ -L "$(CLAUDE_DIR)/$$item" ]; then \
|
||||
target=$$(readlink "$(CLAUDE_DIR)/$$item"); \
|
||||
echo " $$item: symlink -> $$target"; \
|
||||
elif [ -e "$(CLAUDE_DIR)/$$item" ]; then \
|
||||
echo " $$item: exists (not symlinked)"; \
|
||||
else \
|
||||
echo " $$item: not found"; \
|
||||
fi \
|
||||
done
|
||||
17
commands/create-issue.md
Normal file
17
commands/create-issue.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
description: Create a new Forgejo issue. Can create single issues or batch create from a plan.
|
||||
argument-hint: [title] or "batch"
|
||||
---
|
||||
|
||||
# Create Issue(s)
|
||||
|
||||
## Single Issue (default)
|
||||
If title provided: `fj issue create "$1" --body "<description>"`
|
||||
|
||||
## Batch Mode
|
||||
If $1 is "batch":
|
||||
1. Ask user for the plan/direction
|
||||
2. Generate list of issues with titles and descriptions
|
||||
3. Show for approval
|
||||
4. Create each: `fj issue create "<title>" --body "<body>"`
|
||||
5. Display all created issue numbers
|
||||
12
commands/dashboard.md
Normal file
12
commands/dashboard.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
description: Show dashboard of open issues, PRs awaiting review, and CI status.
|
||||
---
|
||||
|
||||
# Repository Dashboard
|
||||
|
||||
Run these commands and present a summary:
|
||||
|
||||
1. **Open Issues**: `fj issue search -s open`
|
||||
2. **Open PRs**: `fj pr search -s open`
|
||||
|
||||
Format as tables showing issue/PR number, title, and author.
|
||||
18
commands/review-pr.md
Normal file
18
commands/review-pr.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
description: Review a Forgejo pull request. Fetches PR details, diff, and comments.
|
||||
argument-hint: <pr-number>
|
||||
---
|
||||
|
||||
# Review PR #$1
|
||||
|
||||
1. **View PR details**: `fj pr view $1`
|
||||
2. **Check status**: `fj pr status $1`
|
||||
3. **Get the diff**: `fj pr view $1 diff`
|
||||
|
||||
Review the changes and provide feedback on:
|
||||
- Code quality
|
||||
- Potential bugs
|
||||
- Test coverage
|
||||
- Documentation
|
||||
|
||||
Ask the user if they want to approve, request changes, or comment.
|
||||
14
commands/work-issue.md
Normal file
14
commands/work-issue.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: Work on a Forgejo issue. Fetches issue details and sets up branch for implementation.
|
||||
argument-hint: <issue-number>
|
||||
---
|
||||
|
||||
# Work on Issue #$1
|
||||
|
||||
1. **View the issue**: `fj issue view $1`
|
||||
2. **Create a branch**: `git checkout -b issue-$1-<short-kebab-title>`
|
||||
3. **Plan**: Use TodoWrite to break down the work based on acceptance criteria
|
||||
4. **Implement** the changes
|
||||
5. **Commit** with message referencing the issue
|
||||
6. **Push**: `git push -u origin <branch>`
|
||||
7. **Create PR**: `fj pr create "[Issue #$1] <title>" --body "Closes #$1"`
|
||||
9
scripts/load-forgejo-token.sh
Executable file
9
scripts/load-forgejo-token.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Load Forgejo token from macOS Keychain into Claude Code session
|
||||
if [ -n "$CLAUDE_ENV_FILE" ]; then
|
||||
TOKEN=$(security find-generic-password -a "$USER" -s "forgejo-token" -w 2>/dev/null)
|
||||
if [ -n "$TOKEN" ]; then
|
||||
echo "export FORGEJO_TOKEN=\"$TOKEN\"" >> "$CLAUDE_ENV_FILE"
|
||||
fi
|
||||
fi
|
||||
exit 0
|
||||
50
scripts/pre-commit-checks.sh
Executable file
50
scripts/pre-commit-checks.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
# Pre-commit validation script for Claude Code
|
||||
# Validates YAML, checks for secrets, validates K8s manifests
|
||||
|
||||
set -e
|
||||
|
||||
# Get staged files
|
||||
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for potential secrets in staged files
|
||||
echo "Checking for potential secrets..."
|
||||
SECRET_PATTERN='(password|secret|token|api_key|apikey|private_key).*[=:].{20,}'
|
||||
if echo "$STAGED_FILES" | xargs grep -l -iE "$SECRET_PATTERN" 2>/dev/null | grep -v '.sops.yaml' | grep -v 'secret.*\.enc\.yaml'; then
|
||||
echo "WARNING: Potential secrets detected in staged files (excluding SOPS-encrypted files)"
|
||||
echo "Please verify these are encrypted or not actual secrets."
|
||||
fi
|
||||
|
||||
# Validate YAML syntax
|
||||
echo "Validating YAML syntax..."
|
||||
for file in $(echo "$STAGED_FILES" | grep -E '\.ya?ml$'); do
|
||||
if [ -f "$file" ]; then
|
||||
if ! python3 -c "import yaml; yaml.safe_load(open('$file'))" 2>/dev/null; then
|
||||
echo "ERROR: Invalid YAML syntax: $file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Validate Kubernetes manifests (if kubectl available)
|
||||
if command -v kubectl &>/dev/null; then
|
||||
echo "Validating Kubernetes manifests..."
|
||||
for file in $(echo "$STAGED_FILES" | grep -E '\.ya?ml$'); do
|
||||
if [ -f "$file" ] && grep -q "^kind:" "$file" 2>/dev/null; then
|
||||
# Skip SOPS-encrypted files and kustomization files
|
||||
if echo "$file" | grep -qE '(\.sops\.yaml|\.enc\.yaml|kustomization\.yaml)$'; then
|
||||
continue
|
||||
fi
|
||||
if ! kubectl apply --dry-run=client -f "$file" 2>/dev/null; then
|
||||
echo "WARNING: Kubernetes validation failed: $file (may be expected for partial manifests)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Pre-commit checks passed."
|
||||
exit 0
|
||||
34
settings.json
Normal file
34
settings.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"model": "opus",
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "input=$(cat); current_dir=$(echo \"$input\" | jq -r '.workspace.current_dir'); model=$(echo \"$input\" | jq -r '.model.display_name'); style=$(echo \"$input\" | jq -r '.output_style.name'); git_info=\"\"; if [ -d \"$current_dir/.git\" ]; then cd \"$current_dir\" && branch=$(git branch --show-current 2>/dev/null) && status=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ') && git_info=\" [$branch$([ \"$status\" != \"0\" ] && echo \"*\")]\"; fi; printf \"\\033[2m$(whoami)@$(hostname -s) $(basename \"$current_dir\")$git_info | $model ($style)\\033[0m\""
|
||||
},
|
||||
"enabledPlugins": {
|
||||
"gopls-lsp@claude-plugins-official": true
|
||||
},
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.claude/scripts/load-forgejo-token.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash(git commit:*)",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.claude/scripts/pre-commit-checks.sh",
|
||||
"statusMessage": "Running pre-commit checks..."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user