Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webhubworks/ai

Shared AI assets for webhub GmbH — guidelines, Skills, and slash-commands used across our Laravel and Craft CMS projects, and uploaded to our claude.ai Team workspace.

TL;DR — install/update in one line

cd into your dev directory first (~/reps, ~/code, whatever you use), then run:

[ -d ai ] || git clone https://github.com/webhubworks/ai.git && cd ai && git pull && ./bootstrap.sh

Clones webhubworks/ai into the current directory if it isn't already there, pulls the latest, then runs bootstrap.sh to wire commands and guidelines into ~/.claude. Safe to re-run any time — it's the update path too.

Layout

ai/
├── bootstrap.sh       # One-shot installer that links this repo into ~/.claude
├── hooks/
│   └── session-start.sh      # Claude Code SessionStart hook: detects the stack,
│                             # injects the matching guideline(s), throttled auto-pull
├── guidelines/        # Plain-markdown guidelines
│   ├── README.md
│   ├── webhub.md                     # stack-agnostic webhub baseline
│   ├── webhub-laravel.md             # Laravel/PHP
│   ├── webhub-laravel.digest.md      # the small subset the hook injects
│   ├── webhub-craft-cms.md           # Craft CMS (scaffold)
│   ├── webhub-nativephp.digest.md    # NativePHP always-on deviations (no full guideline - see the nativephp skill)
│   └── laravel-php-guidelines.md     # Spatie's Laravel/PHP standards, mirrored from spatie.be
├── skills/            # Skills — linked into ~/.claude/skills by bootstrap.sh,
│   │                  # and each subfolder also zips up into one claude.ai Skill
│   ├── laravel/
│   │   ├── SKILL.md             # thin wrapper - the rules live in the guideline
│   │   └── reference.md         # → ../../guidelines/webhub-laravel.md (symlink)
│   ├── craft-cms/
│   │   ├── SKILL.md             # thin wrapper - the rules live in the guideline
│   │   └── reference.md         # → ../../guidelines/webhub-craft-cms.md (symlink)
│   ├── craft-upgrade/        # Craft major-version upgrade playbook
│   │   ├── SKILL.md          # orchestrator (only its description loads per session)
│   │   ├── upgrading-across-multiple-major-versions.md
│   │   ├── v2-to-v3/ v3-to-v4/ v4-to-v5/   # per-leg docs, read on demand
│   │   └── v5-to-v6/         # placeholder until the first 5→6 upgrade
│   ├── laravel-browser-testing/   # self-contained playbook (Pest browser tests + ddev)
│   │   └── SKILL.md
│   ├── pest-v5-upgrade/           # self-contained playbook (Pest 5 upgrade + PCOV/Tia)
│   │   └── SKILL.md
│   └── nativephp/                 # self-contained playbook (NativePHP desktop apps)
│       └── SKILL.md
└── commands/          # Slash-commands for Claude Code
    ├── laravel/                       # → /webhub:laravel:<name>
    │   ├── commit-and-simplify.md
    │   └── simplify.md
    ├── plan-issue.md                  # → /webhub:plan-issue
    └── security-review.md             # → /webhub:security-review

How distribution works (read this first)

Everything is served from your local clone of this repo, so a single git pull updates every project on your machine — no composer update, nothing committed into project repos.

There are two layers, both wired up by bootstrap.sh:

  1. Stack-agnostic baselineguidelines/webhub.md is @-imported into ~/.claude/CLAUDE.md. The import points at the live file in this clone, so it's in context for every session in every project, and updates the moment you pull.
  2. Stack-specific guidelines — a Claude Code SessionStart hook (hooks/session-start.sh) runs at the start of every session. It:
    • detects the project type from the working directory (composer.jsoncraftcms/cms = Craft, nativephp/* = NativePHP desktop, laravel/framework = Laravel; falls back to artisan / craft marker files). NativePHP is tested before Laravel, since those projects require laravel/framework too and would otherwise be told to use ddev, which this stack cannot use,
    • reads the matching guideline(s) straight from this clone (webhub-laravel.digest.md for Laravel; that plus webhub-nativephp.digest.md for NativePHP; webhub-craft-cms.md for Craft) and injects them as session context, prefixed with the detected project type and an instruction naming the skill(s) to invoke for the full standards,
    • runs a throttled background git pull of this clone (at most once/hour, fully detached, offline-safe) so edits you push here reach every developer's next session automatically.

So Claude opens every session already knowing the stack and with the right rules loaded — in any repo, including Craft and non-PHP repos — and guideline edits propagate on their own.

One-time per developer: the hook can't install itself — bootstrap.sh is what wires it into ~/.claude/settings.json. After that single git pull && ./bootstrap.sh, it's hands-off: the hook keeps the clone fresh and serves the latest guidelines with no further action. You only need to re-run bootstrap.sh if the wiring itself changes (a new globally-imported guideline, or a change to how the hook is registered) — never for ordinary guideline or hook-script edits.

Onboarding — bootstrap.sh (recommended)

See the one-liner above. What bootstrap.sh does, idempotently:

  • Symlinks commands/ into ~/.claude/commands/webhub/, so every slash-command in this repo is available as /webhub:<name> (subdirs add namespace segments — e.g. /webhub:laravel:simplify).
  • Symlinks each skills/<name>/ folder into ~/.claude/skills/<name>/, so every skill is discoverable in Claude Code — available as /<name> and auto-invoked from its description. Only the description loads each session; a skill's body and any bundled reference docs are read on demand. A pre-existing non-symlink ~/.claude/skills/<name> is left untouched (your personal skills are safe).
  • Appends an @<path> import for the stack-agnostic webhub.md to ~/.claude/CLAUDE.md, so the webhub baseline applies to every session regardless of stack. Existing content in ~/.claude/CLAUDE.md is left untouched.
  • Registers the SessionStart hook (hooks/session-start.sh) in ~/.claude/settings.json under matcher: "*" (fires on startup, resume, clear, compact). Wiring is idempotent and relocation-safe (a moved clone replaces the old entry instead of stacking), and any unrelated SessionStart hooks you have are left intact.

To update: re-run the one-liner from the directory above the clone, or cd into the clone and run git pull && ./bootstrap.sh. In practice the hook's auto-pull keeps the clone fresh on its own; re-running bootstrap.sh is only required when the wiring changes (see the note above).

Onboarding — manual fallback

From inside your clone of this repo, the same effect by hand:

ln -sfn "$PWD/commands" ~/.claude/commands/webhub
echo "@$PWD/guidelines/webhub.md" >> ~/.claude/CLAUDE.md
chmod +x "$PWD/hooks/session-start.sh"
# Then register the SessionStart hook in ~/.claude/settings.json (jq):
jq --arg cmd "$PWD/hooks/session-start.sh" \
  '.hooks.SessionStart = ((.hooks.SessionStart // []) + [{"matcher":"*","hooks":[{"type":"command","command":$cmd,"timeout":30}]}])' \
  ~/.claude/settings.json > /tmp/s.json && mv /tmp/s.json ~/.claude/settings.json

(bootstrap.sh does all of this idempotently and is the recommended path.)

Guidelines

Plain markdown files served to Claude from this clone (never copied into project repos):

  • Stack-agnostic baselinewebhub.md is @-imported into ~/.claude/CLAUDE.md by bootstrap.sh, so it's in context for every session everywhere.
  • Stack-specificwebhub-laravel.md (+ the mirrored laravel-php-guidelines.md) and webhub-craft-cms.md are injected by the SessionStart hook only when it detects that project type. Claude sees Laravel rules in Laravel work, Craft rules in Craft work, nothing extra elsewhere.
  • Because everything resolves to the live files in this clone, a git pull (the hook auto-pulls hourly) updates every project at once. Nothing is committed into consuming repos anymore.

laravel-php-guidelines.md is mirrored from Spatie (https://spatie.be/laravel-php-ai-guidelines.md). It's vendored here so the hook can serve it locally with no network dependency. Refresh it occasionally with:

curl -fsSL -o guidelines/laravel-php-guidelines.md https://spatie.be/laravel-php-ai-guidelines.md

To add a new guideline file, drop it into guidelines/ and:

  • Add it to the GUIDELINES=( … ) array in bootstrap.sh if it should apply user-level to every session (stack-agnostic).
  • Wire it into hooks/session-start.sh's case "$stack" mapping if it should load for a specific stack (and add detection there if it's a new stack).

Skills

Each subfolder under skills/ is one Skill, consumed in two places:

  • Claude Code (local): bootstrap.sh symlinks every skill into ~/.claude/skills/, so they're discoverable automatically — available as /<name> and auto-invoked from their description. Nothing else to do.
  • claude.ai org-wide: upload each as a .zip with SKILL.md (and any bundled files) at the root of the zip — no wrapper directory.
cd skills/laravel        && zip ../laravel.zip       SKILL.md reference.md && cd -   # zip follows the symlink, so the guideline content lands as reference.md
cd skills/craft-cms      && zip ../craft-cms.zip     SKILL.md reference.md && cd -   # same — keeps the upload self-contained
cd skills/craft-upgrade  && zip -r ../craft-upgrade.zip . && cd -   # bundles SKILL.md + reference docs
cd skills/laravel-browser-testing && zip ../laravel-browser-testing.zip SKILL.md && cd -   # self-contained, single file
cd skills/pest-v5-upgrade && zip ../pest-v5-upgrade.zip SKILL.md && cd -   # self-contained, single file
cd skills/nativephp      && zip ../nativephp.zip      SKILL.md && cd -   # self-contained, single file

The laravel and craft-cms skills are thin wrappers: their SKILL.md just points to a bundled reference.md, which is a symlink to the corresponding guidelines/webhub-*.md (the single source of truth). Editing the guideline updates the skill everywhere - locally the symlink resolves live; for claude.ai the zip above dereferences it into the archive. Never duplicate guideline content into SKILL.md.

Then in claude.ai: Settings → Skills → Organization skills → + Add → pick the .zip. Only the org owner can publish org-wide skills.

When a skill grows extra files (examples, scripts, reference docs — like craft-upgrade's per-leg docs), zip the contents of its folder so siblings of SKILL.md sit at the zip root.

Guideline or skill? (decide before you write)

Both layers exist for different shapes of knowledge. Picking wrong costs either context on every session or knowledge that never gets loaded.

Guideline (guidelines/) Skill (skills/)
Shape House style - how we write code. Normative, applies to every line. Playbook - interlocking failure modes, where the symptom presents as an unrelated bug.
Examples webhub-laravel.md: Actions + DTOs, up() only, #[Scope], no $fillable craft-upgrade, laravel-browser-testing, nativephp
Loading Auto-injected by the SessionStart hook for the detected stack. Costs context every session. Only the description loads per session; the body is read on demand. Costs ~nothing until invoked.
Trigger Stack detection (deterministic) Claude matching the description (probabilistic) - so write the description well, see below

Rules of thumb:

  • Don't promote a playbook to a guideline just because it's important. Put the ruinous upfront facts in a small *.digest.md the hook injects, and the diagnosis in the skill. That's the nativephp split: ~2KB digest, ~14KB skill.
  • Don't create a guideline for a stack we've used once. A skill is nearly free when uninvoked; a guideline taxes every session. nativephp is deliberately a skill (n=1 project) even though it holds a lot of hard-won detail.
  • Write descriptions as symptoms, not topics. The description is the entire trigger surface. Name the literal strings a developer will paste: "Playwright is outdated", spawn .../php EACCES, AppleScript error -1743. laravel-browser-testing and nativephp both do this on purpose.
  • Back the description with a hook instruction when the stack is detectable. The injected context leading with "invoke the X skill" turns a judgement call into an instruction - far more reliable than description-matching alone.
  • Push project knowledge up. When a project CLAUDE.md accumulates stack-generic traps, move them into the skill and leave only what is genuinely project-specific behind. Otherwise the next project rediscovers them.

craft-upgrade — keeping it lean

craft-upgrade bundles large per-leg reference docs (Craft's official upgrade docs, plus webhub's pitfalls/protocols). These are not loaded every session: only SKILL.md's description loads at session start. Claude reads the body when an upgrade task begins, and then reads only the version-specific docs matching the from→to versions. That's why a Craft upgrade playbook can live here without bloating every unrelated session.

Editing

  1. Edit the file here.
  2. Commit + push.
  3. It propagates automatically:
    • Guidelines, the hook script, commands, skills: nothing to do. Each developer's SessionStart hook auto-pulls this clone (≤ 1h), and everything resolves to live files/symlinks — so the next session already has the change. A developer who wants it now can git -C ~/reps/ai pull.
    • Wiring changes only (a new globally-imported guideline added to bootstrap.sh, or a change to how the hook is registered): developers re-run git pull && ./bootstrap.sh once.
    • claude.ai Skills: re-zip and re-upload via the admin UI.

Note: webhubworks/laravel-starter no longer publishes guidelines into project repos. The SessionStart hook is the single source for Claude Code; its webhub:post-autoload now removes any stale .ai/guidelines/ copies it finds (and re-runs boost:update) so Boost stops composing outdated rules.

About

Shared AI assets for webhub GmbH — guidelines, claude.ai Skills, and Claude Code slash-commands.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages