SOPs
How We Name Anything
What this covers
Section titled “What this covers”Anything that gets a name and persists past the moment it was written: repositories, scripts, launch agent labels and binaries, hooks, skills, markdown docs, folders, plist labels, doodle filenames. Variable names inside a single function are out of scope, that is a code-style call. This SOP is for names that get listed alphabetically somewhere and have to make sense to a future reader staring at them with no context.
For repository naming specifically, see Naming a New Repo. This SOP is the broader principle that repo-naming is one application of.
The Three Tests
Section titled “The Three Tests”Every name must pass all three.
1. The Two-Year Test
Section titled “1. The Two-Year Test”Read the name out loud. With no other context. Two years from now, can you tell what it does?
- Pass:
launch-tailscale-hidden.sh - Fail:
open,script.sh,helper,final
2. The Siblings Test
Section titled “2. The Siblings Test”If you might have five of these next year, does the name leave room?
- Pass:
liveview-ios(leaves room forliveview-chrome,liveview-mac,liveview-web) - Fail:
script.sh(where do the next four go?) - Fail:
crm(which CRM? there are now three of them)
The siblings test is the one that bites later. The repo for “the thing” becomes painful when “the thing” splits into four things and you have to retrofit a namespace into existing references.
3. The Strip-of-Context Test
Section titled “3. The Strip-of-Context Test”Run the name through every tool that displays it: macOS Login Items, Finder, git log, launchctl list, GitHub repo list, your shell prompt. Strip away every parent folder, every breadcrumb, every visual hierarchy. What is left?
If what is left is Open or script or Final-Final, the name failed.
This test catches names that read fine in one tool but become useless in another. The Tailscale launch agent originally pointed at /usr/bin/open, and macOS System Settings showed the helper as just “Open.” The plist label com.user.tailscale-hidden would have read fine in launchctl list, but the binary leaked into the System Settings UI as the generic tool name.
Bad Patterns
Section titled “Bad Patterns”In rough order of how often they bite.
Generic verbs alone
Section titled “Generic verbs alone”open, run, script, helper, utils, misc, common. These are dumping grounds. The siblings test fails immediately. If you have a helper.sh, you will have a helper2.sh within a year and a helper-old.sh within two.
Tool or binary leaks
Section titled “Tool or binary leaks”Pointing a launch agent or systemd unit at /usr/bin/open, /bin/bash -c '...', /usr/bin/python3 directly. The operating system displays the binary name, not your label. The display name becomes “Open” or “bash” or “python3.”
Fix: wrap the command in a named script with a descriptive filename. The OS shows the script name.
Bare abbreviations
Section titled “Bare abbreviations”cc, tms, gkp, ath, mts. These are personal jargon. They mean nothing on their own. Pair them with a descriptive second half: cc-hooks, tms-internal, gkp-website, ath-upload-receiver. Never bare.
Versions in the name
Section titled “Versions in the name”v2, 2026, new, final, final-final, actually-final. Versions rot. If the second version genuinely needs a different repo, rename the old one with -old or -archive. Do not bake the version into the name of the live thing.
Date-only names
Section titled “Date-only names”2026-04-25.md, april-screenshot.png. The date is metadata, not content. Names need a subject. 2026-04-25-tailscale-rename.md works. 2026-04-25.md does not.
Mystery acronyms
Section titled “Mystery acronyms”If the acronym is not expanded somewhere in the file or its parent README, do not use it. RCA is fine because it is documented. A new three-letter abbreviation that only you remember is not.
Junk-drawer words
Section titled “Junk-drawer words”misc, stuff, temp, experimental, playground. These are signals that you did not decide what the thing is yet. Decide first, then name.
Good Patterns by Domain
Section titled “Good Patterns by Domain”Repositories
Section titled “Repositories”Lowercase hyphenated, subject + what it does. See Naming a New Repo for the full standard.
For multi-platform products, the subject stays and the platform varies:
liveview-iosliveview-chromeliveview-macliveview-web
Platform suffix is plain lowercase (ios not iOS). Sorts cleanly alphabetically.
Scripts (shell, Python, Node)
Section titled “Scripts (shell, Python, Node)”verb-object[-modifier].(sh|py|js).
sync-claudemd-html.pylaunch-tailscale-hidden.shverify-deploy.shpost-push-sync.sh
Verb tells you what it does. Object tells you what it acts on. Modifier (optional) narrows the variant.
Launch Agent Labels
Section titled “Launch Agent Labels”Reverse-DNS with a personal namespace: com.jameshurst.<subject>-<verb>.
- Example:
com.jameshurst.tailscale-launch-hidden
Sorts cleanly under jameshurst in launchctl list, separating personal agents from system and third-party agents. The label and the plist filename should match.
Launch Agent ProgramArguments
Section titled “Launch Agent ProgramArguments”Always wrap generic binaries in a named script. Never point a launch agent directly at /usr/bin/open, /bin/bash -c, /usr/bin/python3, etc., unless you accept that macOS will show the System Settings UI as “Open” or “bash” or “python3.”
The wrapper script lives in ~/apps/cc/bin/ or wherever the project naturally puts its scripts, with a name that explains what it does.
Skills
Section titled “Skills”Verb-noun.
create-blog-postreview-logsemail-journal
Verb first so they sort by action when listed.
Markdown Documents
Section titled “Markdown Documents”Subject-first.
how-we-name-anything.mdrepo-naming.mdworking-over-ssh.md
Not naming-rules.md or rules-for-naming.md. Lead with the subject of the document.
Doodles and Images
Section titled “Doodles and Images”Already codified in the super CLAUDE.md: <concept-slug>-v<n>-<provider>-<model>.png. Saved to ~/apps/doodles/<concept-slug>/.
Memory Files
Section titled “Memory Files”Already codified: <type>_<topic>.md in ~/apps/cc/memory/.
Worked Examples
Section titled “Worked Examples”Tailscale Launch Agent (rename)
Section titled “Tailscale Launch Agent (rename)”Before:
- Plist filename:
com.user.tailscale-hidden.plist - Label:
com.user.tailscale-hidden - ProgramArguments:
/usr/bin/open -j -g /Applications/Tailscale.app - macOS Login Items showed it as: “Open”
The label was fine in launchctl list. The binary was wrong everywhere else.
After:
- Plist filename:
com.jameshurst.tailscale-launch-hidden.plist - Label:
com.jameshurst.tailscale-launch-hidden - ProgramArguments:
/Users/ojhurst/apps/cc/bin/launch-tailscale-hidden.sh - Wrapper script internally calls
/usr/bin/open -j -g /Applications/Tailscale.app - macOS Login Items now shows: “launch-tailscale-hidden.sh”
Two changes: the label moved to a personal namespace, and the binary became a named wrapper script. Either change alone was insufficient. Both together make the system self-describing in every tool that displays it.
LiveView Multi-Platform (sibling structure)
Section titled “LiveView Multi-Platform (sibling structure)”A product that exists as a Chrome extension, an iPhone app, possibly a Mac app, possibly a website. The natural early instinct is to name the first repo LiveView (one product, one repo). The siblings test catches it: there will be at least three repos.
The structure:
liveview-iosliveview-chromeliveview-macliveview-web
Subject (liveview) stays constant. Platform suffix differentiates. New platforms slot in without retrofitting a namespace.
If shared code emerges across platforms (a sync protocol, a data model), it gets its own repo: liveview-shared or liveview-protocol. The naming scales.
The Fix-the-Name Reflex
Section titled “The Fix-the-Name Reflex”When you catch yourself thinking “I will name it properly later,” stop. Name it properly now.
Old code with a bad name is the worst kind of debt. By the time someone has the context to rename it, half the codebase references it, three cron jobs depend on the path, and a deploy script greps for the old string. The cost of renaming compounds. The cost of naming it right the first time is two minutes of thought.
The reflex: before you save, before you commit, before you gh repo create, run the three tests. If any fails, fix the name before the keystroke.
Update Protocol
Section titled “Update Protocol”This SOP grows with experience. When a naming dilemma comes up that none of the existing patterns covers, add it as a worked example. The SOP earns its weight by accumulating real cases.
Related
Section titled “Related”- Naming a New Repo for the repo-specific application of these principles
- How We Build Anything for the broader build checklist
- Prove the Checklist for how SOPs work in practice