Public skills (TitleCase) ship to the world. Private skills (_ALLCAPS) never leave the local repo. Sensitivity is decided by skill name, not by per-file scrubbing at share-time.
The Bright Line
Public skill (TitleCase) — content rule:
ONLY templated, safe, public, ready content. Period.
- ✅ Generic instructions any LifeOS user could follow
- ✅ Templated patterns with placeholders for user-specific values
- ✅ Public API references and dependencies on public tools
- ❌ Real names (people, products, companies, customers)
- ❌ Real domains, hostnames, IPs, internal URLs
- ❌ API keys, tokens, credentials, session cookies, OAuth secrets — even example-looking ones
- ❌ Private repo paths or references (
github.com/<org>/<private-repo>)
- ❌ Customer data, customer-specific workflows, customer engagement context
- ❌ First-person war stories tied to a specific incident, project, or person
- ❌ User-specific filesystem paths (
/Users/<name>/..., /home/<name>/...)
- ❌ Identity-bound preferences (DA name, principal name, partner name, pet name, financial figures, health data)
Private skill (_ALLCAPS) — content rule (2026-07-23 separation directive):
Same publishable-clean standard as public skills. The underscore is still the release boundary (release tooling skips _* — that safety net stays), but it no longer licenses embedding personal content. A private skill's body — SKILL.md, workflows, tools — holds only generic code and instructions; everything sensitive lives under LIFEOS/USER/ and the skill reads it by path:
- Personal data (corpora, inventories, preferences, registries, state) →
LIFEOS/USER/CUSTOMIZATIONS/SKILLS/<SkillName>/ — unless a canonical USER home already owns it (GEAR.md, FINANCES/, TELOS/, CONTACTS.md); then point there, never duplicate.
- Personal config (your domains, account IDs, repo paths, endpoints) → a
Config.md/.yaml in that same CUSTOMIZATIONS dir, loaded by the skill at run time.
- Credentials → env var names in the skill, values in
~/.claude/.env. Never values, never tokens in URLs.
- Prose refers to "the principal," never a real name; no home-path literals (
~-relative or config-resolved paths only).
Why: a private skill in this state is promotable to public with a rename, the whole tree passes one hygiene gate, and a leak of the skills tree leaks no life data. What makes a skill private is that its FUNCTION is personal-scoped (your inbox, your customer, your infra) — not that its files hold your data.
Enforcement: LIFEOS/TOOLS/SkillHygieneGate.ts (deny-list clean, runs inside /ic) + the SystemFileGuard write gate. A new skill is not done while the gate reports violations on it.
The Decision Test
When you find yourself wanting to write any of the following into a skill body, that skill MUST be _ALLCAPS:
| If the skill mentions… |
Skill must be |
| A specific person's name (yours, your partner's, your team's, a customer's) |
_ALLCAPS |
| A specific product name you own or sell |
_ALLCAPS |
| A specific customer or client |
_ALLCAPS |
| A specific paid API account, billing realm, or subscription |
_ALLCAPS |
| A specific private domain, hostname, internal IP, or VPN |
_ALLCAPS |
| A specific private repo, dotfile location, or local infra |
_ALLCAPS |
| A specific business process tied to your company |
_ALLCAPS |
| A specific financial, health, security, or legal context |
_ALLCAPS |
| A specific incident or one-off war story |
_ALLCAPS |
Anything that would be wrong, embarrassing, or unsafe in someone else's ~/.claude/ |
_ALLCAPS |
If none of the above apply and the skill is fully generic — it can be TitleCase (public).
Where Personal Layering Goes for Public Skills
A public skill can be made user-specific at runtime via ~/.claude/LIFEOS/USER/CUSTOMIZATIONS/SKILLS/<SkillName>/PREFERENCES.md. The skill body stays generic; the user's customization file overlays per-instance context. Use this when a skill is fundamentally generic but benefits from per-user tweaks (preferred voice, default formats, personal taste).
Do not use CUSTOMIZATIONS/SKILLS to smuggle private content into a public skill. If the skill requires private context to function (real customer name, real API account, real internal infra), it is a private skill — name it _ALLCAPS and stop.
Allowed in Public Skills
- Generic
~/ paths (~/.claude/skills/, ~/Projects/<tool>/) — resolve per-user
- Public repo URLs for tools the skill depends on
- Public API endpoints that are conventions, not secrets (e.g.,
localhost:31337/notify)
- Example values clearly marked as placeholders (
<url>, <SESSION_ID>, test@example.com)
- Generic env var names (never values):
STRIPE_API_KEY, OPENAI_API_KEY
Pre-Flight Gate (ALL Skills — public and private)
Before shipping or modifying ANY skill, run the hygiene gate:
bun ~/.claude/LIFEOS/TOOLS/SkillHygieneGate.ts --skill <SkillName>
It scans against the canonical deny-list (LIFEOS/USER/SECURITY/DENY_LIST.txt — the list is identity DATA, so it lives in the USER tree) plus home-path shapes. Exit 0 = clean. Any violation = move the data to LIFEOS/USER/CUSTOMIZATIONS/SKILLS/<SkillName>/ (or its canonical USER home) and reference it by path. Since 2026-07-23 there is no private-skill exemption — _ALLCAPS decides where a skill ships (nowhere), not what its files may contain.