@supa-media/claude
v1.0.2
Published
Claude Code configuration templates for Supa apps
Maintainers
Readme
@supa-media/claude
Claude Code configuration for a Supa app, kept in one place and synced in.
Ships a CLAUDE.md, a conservative permissions file, an empty hooks file, and
seven slash-command templates; supa-claude sync copies them into your repo with
your app's name substituted, and never clobbers a file you've edited unless you
ask it to.
Install
pnpm add -D @supa-media/claudeOr run it one-off, without adding a dependency:
npx @supa-media/claude syncUsage
npx @supa-media/claude sync Sync templates and generate CLAUDE.md
npx @supa-media/claude sync --force Overwrite existing files
npx @supa-media/claude sync --dry-run Print the plan, write nothing
npx @supa-media/claude help Show usagesync is the only command (and the default when none is given). --help / -h
work anywhere. The project root is the nearest ancestor of the cwd containing a
package.json.
What it writes
| Path | Source | Substituted |
| --- | --- | --- |
| CLAUDE.md (project root) | templates/CLAUDE.md | yes |
| .claude/settings.json | templates/settings.json | no — copied verbatim |
| .claude/hooks.json | templates/hooks.json | yes |
| .claude/commands/*.md | templates/commands/ | yes |
The seven commands: auto-worker, feature-validate, fix-ci, ios-build,
isolate, lock-up, review-cycle.
Every file follows the same rule: created if absent, skipped if it already
exists, and rewritten only under --force (and then only when the content
actually differs). Each run prints created / updated / skipped / unchanged.
Configuration
Values are read from supa.config.ts, .js, or .mjs in the project root,
falling back to package.json's name for both name fields.
| Value | Substitutes |
| --- | --- |
| appName (or name) | {{APP_NAME}} |
| displayName | {{APP_DISPLAY_NAME}} (defaults to appName) |
| githubOwner (or owner) | the literal word OWNER |
| githubRepo (or repo) | the literal string "REPO" |
The owner/repo tokens exist for the GitHub GraphQL queries in
commands/review-cycle.md; leave them unset and the templates keep their
placeholders with the accompanying "replace OWNER and REPO" notes.
⚠️ The config file is scanned with regexes, not imported. Each pattern takes the first match anywhere in the file, so an unrelated
name:earlier in the config wins. And the GitHub substitution is a blind global replace of the bare wordOWNERand the quoted string"REPO"— an unquotedREPO(e.g. in arepos/OWNER/REPO/...path) is left alone, and any other occurrence of the wordOWNERin a template you add will be replaced too.
Permissions
templates/settings.json ships a deliberately conservative
permissions.allow list — routine, reversible commands only:
- pnpm —
install, and thedev:/build:/test:/lint:/typecheck:/clean:/--filter:prefixes, plusconvex:dashboardandconvex:logs - Convex —
npx convex dev,npx convex run,npx convex logs - Build/test —
npx tsc,node --test - Read-only git and gh —
status,diff,log,show,branch,fetch;gh pr view|list|diff|checks,gh run view|list,gh api graphql - Local git writes —
git add,git commit,git checkout
It also denies reads of .env and .env.*, at the project root and nested.
Everything not listed still prompts — deliberately. That includes git push,
git reset --hard, git clean, gh pr merge, convex deploy, and eas: the
commands that publish, deploy, or destroy work. This is a floor, not a finished
policy. Widen it for your own repo once you know which of those you're
comfortable granting; sync will not overwrite an existing
.claude/settings.json without --force, so your edits survive later syncs.
templates/hooks.json ships empty — a starting point for your own
PreToolUse / PostToolUse / Stop entries. Any command you register must
point at a script that actually exists in your repo; a missing script makes the
hook fail on every invocation.
No tests ship with this package.
Part of the Supa Media framework — https://github.com/Supa-Media/supa-framework. MIT.
