Skip to content

aaronsb/claude-code-config

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Code Config

A domain-agnostic guidance framework for Claude Code. Injects relevant knowledge just-in-time based on what you're doing.

The Idea

Ways = automated, contextual guidance triggered by keywords, commands, and file patterns.

This repo ships with software development ways, but the mechanism is general-purpose. You could have ways for:

  • Excel/Office productivity
  • AWS operations
  • Financial analysis
  • Research workflows
  • Anything with patterns Claude should know about

What It Does

You: "let's discuss the architecture"
→ ADR way loads (architecture decision format, workflow)

You: "there's a bug in the auth"
→ Debugging way + Security way load

Claude runs: git commit
→ Commits way loads (conventional commit format)

Ways load once per session when triggered. No manual invocation needed.

Quick Start

# Backup existing config if any
[ -d ~/.claude ] && mv ~/.claude ~/.claude-backup-$(date +%Y%m%d)

# Clone
git clone https://github.com/aaronsb/claude-code-config ~/.claude

# Make hooks executable
chmod +x ~/.claude/hooks/**/*.sh ~/.claude/hooks/*.sh 2>/dev/null

# Restart Claude Code - ways are now active

How It Works

core.md loads at session start with:

  • Behavioral guidance: Collaboration style, communication norms, uncertainty handling
  • Operational rules: File operation constraints, attribution settings
  • Ways index: Dynamic table of all available ways (generated by macro)

Then, as you work:

  1. UserPromptSubmit scans your message for pattern matches
  2. PostToolUse scans commands, file paths, and descriptions
  3. Matching ways inject via additionalContext - Claude sees them
  4. Each way loads once per session - marker files prevent re-triggering

Once-Per-Session Gating

Ways don't continuously re-hook. When a way triggers:

First match  → Output guidance + create marker file
Second match → Marker exists → No-op (silent)

Markers live in /tmp/.claude-way-{domain}-{wayname}-{session_id}. This prevents noise - you see each way once, when first relevant, then it stays quiet.

See docs/architecture.md for detailed Mermaid diagrams of the trigger flow and state machine.

~/.claude/hooks/ways/
├── core.md                      # Loads at startup (static guidance)
├── macro.sh                     # Generates dynamic ways table
├── show-core.sh                 # Combines macro + core.md
├── check-prompt.sh              # Keyword + semantic matching
├── check-bash-post.sh           # Command matching
├── check-file-post.sh           # File path matching
├── show-way.sh                  # Once-per-session gating
├── semantic-match.sh            # Gzip NCD similarity scoring
└── {domain}/                    # Domain directories
    └── {wayname}/
        ├── way.md               # Frontmatter + guidance
        └── macro.sh             # Optional dynamic context

Configuration

Ways config lives in ~/.claude/ways.json:

{
  "disabled": ["itops"]
}
Field Purpose
disabled Array of domain names to skip (e.g., ["itops", "softwaredev"])

Disabled domains are completely ignored - no pattern matching, no output.

Creating a Way

Each way is self-contained with YAML frontmatter:

---
match: regex
pattern: pattern1|pattern2|regex.*
files: \.tsx$|components/.*
commands: npm\ run\ build
macro: prepend
---
# Way Name

## Guidance
- Compact, actionable points

Create a directory in ~/.claude/hooks/ways/{domain}/{wayname}/ and add way.md. For project-local: $PROJECT/.claude/ways/{domain}/{wayname}/way.md.

Frontmatter Fields

Field Purpose
match: regex (default) or semantic
pattern: Regex matched against user prompts
files: Regex matched against file paths (Edit/Write)
commands: Regex matched against bash commands
macro: prepend or append - run macro.sh for dynamic context
description: Reference text for NCD similarity (semantic mode)
vocabulary: Domain words for keyword counting (semantic mode)
threshold: NCD similarity threshold (default 0.58, lower = stricter)

Semantic Matching

For ambiguous triggers like "design" (software design vs UI design), ways can use semantic matching instead of regex:

---
match: semantic
description: software system design architecture patterns database schema
vocabulary: design architecture pattern schema api component factory
threshold: 0.55  # Optional: stricter matching (default 0.58)
---

Semantic matching combines two techniques:

  1. Keyword counting - how many domain-specific words appear in the prompt
  2. Gzip NCD - compression-based similarity (Normalized Compression Distance)
Match if: domain_keywords >= 2 OR ncd_similarity < 0.58

This correctly distinguishes:

  • ✓ "design the database schema" → triggers (software design)
  • ✗ "button design looks off" → no trigger (UI design)

Zero dependencies - uses only bash, gzip, bc, grep (universal on all distros).

Way Macros

Static guidance can't know your environment. Macros add dynamic state detection:

Way    = guidance (the "how")
Macro  = state detection (the "what is")
Output = contextual guidance (the "how, given what is")

Example: github.macro.sh detects solo vs team project:

#!/bin/bash
gh repo view &>/dev/null || { echo "**Note**: Not a GitHub repo"; exit 0; }
CONTRIBUTORS=$(timeout 2 gh api repos/:owner/:repo/contributors --jq 'length' 2>/dev/null)
if [[ "$CONTRIBUTORS" -le 2 ]]; then
  echo "**Context**: Solo project - PR optional"
else
  echo "**Context**: Team project - PR recommended"
fi

Macros are optional. Ways without macros work as pure static guidance.

See ADR-004 for full macro documentation.

Project-Local Ways

Projects can have custom ways in .claude/ways/{domain}/{wayname}/:

Security Note: Project-local macros are disabled by default. Static way content (way.md) always loads, but macro.sh scripts only run for trusted projects. To trust a project:

echo "/path/to/your/project" >> ~/.claude/trusted-project-macros

This prevents malicious repositories from executing code via way macros.

your-project/.claude/ways/
└── myproject/
    ├── api/
    │   └── way.md       # Project API conventions
    ├── deployment/
    │   ├── way.md       # How we deploy
    │   └── macro.sh     # Query deployment status
    └── testing/
        └── way.md       # Override global testing way

Project ways override global ways with the same path. A template is auto-created on first session.

Built-in Ways (Software Dev)

This repo ships with 20 development-focused ways:

Way Triggers On
adr docs/adr/*.md, "architect", "decision"
api "endpoint", "rest", "graphql"
commits git commit, "push to remote"
config .env, "environment variable"
debugging "bug", "broken", "investigate"
deps npm install, "dependency", "package"
docs README.md, "documentation"
errors "error handling", "exception"
github gh, "pull request", "issue"
knowledge .claude/ways/*.md, "ways"
migrations "migration", "schema"
patches *.patch, "git apply"
performance "slow", "optimize", "profile"
quality "refactor", "code review", "solid"
release "deploy", "version", "changelog"
security "auth", "secret", "token"
ssh ssh, scp, "remote server"
subagents "delegate", "subagent"
testing pytest, jest, "coverage", "tdd"
tracking .claude/todo-*.md, "multi-session"

Replace these entirely if your domain isn't software dev. The framework doesn't care.

Also Included

  • 6 specialized subagents for complex tasks (requirements, architecture, planning, review, workflow, organization)
  • ADR-driven workflow guidance
  • GitHub-first patterns (auto-detects gh availability)
  • Status line with git branch and API usage

Ways vs Skills

Claude Code has built-in Skills (semantically-discovered knowledge bundles). How do ways compare?

Aspect Skills Ways
Discovery Semantic (Claude decides based on intent) Pattern (regex on prompts/tools/files)
Trigger User asks something matching skill description Hook events (tool use, file edit, keywords)
Invocation Claude requests permission to use Automatic injection (no permission needed)
Frequency Per semantic match Once per session (marker-gated)
Dynamic context Via bundled scripts Via macro.sh
Tool restriction allowed-tools field Not supported

They complement each other:

  • Skills = "Teach Claude how to do X" (semantic, on-demand knowledge)
  • Ways = "Remind Claude when doing Y" (event-driven, just-in-time guidance)

Use Skills for:

  • Semantic discovery ("explain this code" → explaining-code skill)
  • Tool restrictions (read-only security review)
  • Multi-file reference docs with progressive disclosure

Use Ways for:

  • Tool-triggered guidance (git commit → commit format reminder)
  • File-triggered guidance (editing .env → config best practices)
  • Session-gated delivery (show once, not repeatedly)
  • Dynamic context (query GitHub API for contributor count)

Skills can't detect tool execution. Ways now support semantic matching via gzip NCD (see above). Together they cover both intent-based and event-based guidance.

Philosophy

An extensible macro framework for contextual guidance - lightweight, portable, deterministic.

Feature Why It Matters
Pattern matching Predictable, debuggable (no semantic black box)
Shell macros Dynamic context from any source (APIs, files, system state)
Zero dependencies Bash + jq - runs anywhere
Domain-agnostic Swap software dev ways for finance, ops, research, anything
Fully hackable Plain text files, fork and customize in minutes

The string matching is intentionally simple - it keeps the system portable and transparent. The power comes from macros that can query anything and inject real-time context.

Updating

cd ~/.claude && git pull

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages