Swift Server Skills & Linting
A collection of Claude skills for guidance on Swift (Server) development, along with a linting tool that enforces best practices.
The Technique
Claude, as any LLM (or Human) makes mistakes. When Claude makes a mistake, most people have one of two reactions:
- Tell Claude it sucks, and let it try again.
- Open up some social media, and vent about how Claude sucks.
However, trying the same with Humans has proven extremely ineffective. Humans bite back.
The solution
The solution is a pretty simple feedback loop:
- Whenever you generate code, read it before you commit.
- If you see a mistake, try to articulate what should be improved and why.
- Iterate 2. until you have a rationale Claude can follow easily.
- Add the rationale with a small code sample to a Claude skill, to ensure future iterations have the same context.
And now the critical step: Encode your newfound rule/skill as a linter rule.
This last step ensures that future code generated by Claude will follow these same rules, independently of whether the skill is in the LLM's context window.
Overview
This repository contains two main components:
- Skills - Knowledge bases that provide expert guidance on Swift server topics
- swift-server-lint - A linting tool that enforces best practices from the skills
Setup with Claude Code
1. Install Skills
Clone this repository and symlink the skills into your Claude home directory:
git clone https://github.com/joannis/skills.git
ln -s "$(pwd)/skills" ~/.claude/skills
Claude Code automatically loads skills from ~/.claude/skills/*/SKILL.md.
2. Build the Linter
cd skills/swift-server-lint
swift build
3. Auto-Lint with a Hook
Add a PostToolUse hook to ~/.claude/settings.json so that swift-server-lint runs automatically after every swift build:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/swift-server-lint.sh"
}
]
}
]
}
}
Then create ~/.claude/hooks/swift-server-lint.sh:
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -q 'swift build'; then
LINT_BIN=~/.claude/skills/swift-server-lint/.build/debug/swift-server-lint
if [ -x "$LINT_BIN" ]; then
OUTPUT=$("$LINT_BIN" 2>&1)
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "---"
echo "$OUTPUT"
echo "---"
echo '{"decision": "block", "reason": "swift-server-lint found issues. Fix them before continuing."}'
fi
fi
fi
exit 0
chmod +x ~/.claude/hooks/swift-server-lint.sh
4. Allow the Linter in Permissions
Add the linter to your project's .claude/settings.local.json so Claude can run it without prompting:
{
"permissions": {
"allow": [
"Bash(.build/debug/swift-server-lint:*)"
]
}
}
IDE Integration
- VS Code - Install the "Claude Code" extension from the marketplace. All
~/.claude/configuration (skills, hooks, settings) is shared automatically. - Xcode - No native extension. Use
claudein a terminal alongside Xcode.

