This is part of my "Claude Code environment" series. Last time I wrote about an autopilot that lets Claude Code improve itself autonomously and unattended. But if the "pile of automation scripts" that showed up there isn't organized, you can't even decide what to hand the autopilot. So this time the topic is the system I use to classify projects and manage where they live.
Counting the entries in my current ledger ~/PROJECTS.md, there are over 40 projects lined up — web apps, Chrome extensions, iOS apps, digital products, client work, AI tooling, PC automation, and OSS evaluations. Before things grew this far, I built a structure of "8 categories + a ledger + a symlink tree." This article is about that design.
The problem: the projects "exist," but I can't tell "where" they are
Claude Code kept hunting for directories scattered across ~/dev/, ~/Projects/, ~/digital-products/, and ~/oss-trial/ with find ~ every single time. It wasn't just the search time — the state (live/stalled/retired), the production URL, and whether it was monetized were all scattered too, so every time I asked "whatever happened to that app?" I had to reconstruct the context from scratch.
The goal is to consolidate the ledger into a single file so I reach a state where "ask, and the answer comes out immediately."
How the 8 categories are drawn
Here's the definition table straight from ~/PROJECTS.md.
| Code | Definition |
|---|---|
01-webapp |
Web apps / web games that are deployed and used |
02-chrome-ext |
Chrome extensions (MV3) + their dedicated backend API |
03-ios-app |
iOS native / delivery wrappers |
04-digital-product |
note monetization, digital products, content for sale |
05-client-work |
Contract / commissioned work / company repos (third-party owner remote = push with care) |
06-claude-tooling |
Infrastructure, skills, and integrations that act on Claude / the AI agent itself |
07-pc-automation |
PC automation, scrapers, CLI scripts |
08-oss-eval |
Evaluation, experimentation, and sandboxing of external OSS |
Adding categories dilutes their meaning, so I only create a new one "when something genuinely fits none of the eight."
The decision is made by how it's delivered, not by its name. For example, autolike-license-server sounds like an API name, but it's a backend dedicated to license verification for a Chrome extension, so it goes under 02-chrome-ext. Judging by name would misclassify it as "API → server → 01-webapp."
The core: why the real directory never moves
It's tempting to think "organizing = moving folders," but in side-project development, dependencies on absolute paths hide in three places.
-
.vercel/project.json— the Vercel link contains an absolute path. Move it, andvercel deploypoints at a different project. -
launchd plist — the script path written in
ProgramArgumentsis registered as the real path. Move it, and the cron job dies. -
git worktree — the metadata for a worktree created with
git worktree addholds the real path in.git/worktrees/<name>/gitdir.
⚠️ Physically moving a real directory is strictly forbidden.
.vercel, launchd plists, and git worktrees break because they depend on absolute paths. "Classification" is expressed with symlinks + the ledger.
Operation: expressing classification with a ledger + symlinks
You never touch the real directory — you just create a symlink under ~/Desktop/All-Projects/<category>/.
# Classify a new project (without moving the real directory)
ln -sfn ~/dev/takugumi ~/Desktop/All-Projects/01-webapp/
# Verify
ls ~/Desktop/All-Projects/01-webapp/
# Shows something like takugumi -> ~/dev/takugumi
In ln -sfn, the -f overwrites an existing symlink, and -n prevents it from burrowing into the target when the target is a directory. Without these two flags you get a double-nested link.
The ledger ~/PROJECTS.md is one line per project, holding the path, state, monetization, production URL, and cautions (currently 8 categories × over 40 projects total). By reading this one file, Claude Code can instantly answer "Where's the iOS app for the job-hunt tracker?" or "Which ones are in a live state?"
The procedure for having Claude do the classification
The procedure is written in ~/.claude/skills/auto/project-categorization/SKILL.md, and it fires automatically every time a new project is created. The heart of the procedure is only this:
When starting a new project, before you begin writing code:
1. Decide what you're building → pick one of the 8 categories above
(Decide by how it's delivered — not by name or first impression)
2. Only if it fits none of the existing 8, create a new 09-<kebab>
3. Create the real directory under the appropriate parent dir
Web app / extension → ~/dev or ~/Projects
Product → ~/digital-products
OSS evaluation → ~/oss-trial
4. ln -sfn <real path> ~/Desktop/All-Projects/<category>/
5. Add a row to the relevant category table in ~/PROJECTS.md
Because CLAUDE.md also says "when creating a new project, always classify it into one of the 8 categories before starting," Claude begins with classification without being told.
Verification commands
# Check that the symlink was created correctly
ls ~/Desktop/All-Projects/01-webapp/
# Check that it was appended to the ledger
grep "takugumi" ~/PROJECTS.md
# For client-work: check that secrets are ignored
git -C ~/dev/<project> check-ignore credentials.json
Pitfalls I stepped on
Drawn from what I collected in the auto-skill's Pitfalls section.
-
Misclassifying by name — I nearly put
autolike-license-server(a Chrome extension backend) under "server =01-webapp." Readpackage.jsonor the README and judge by how it's delivered. -
Secret-key leak risk in
05-client-work—toc-seo/credentials.json(a GCP key) was sitting bare in the root of a company repo. Every time you create client-work, check that secret-key patterns are in.gitignore. -
Pushing to a third-party owner's remote —
ababa-pr/*andfujibee/*are treated as05-client-workand pushing is forbidden. Check the owner withgit remote -vbefore pushing. - Adding too many categories — when in doubt, force it into one of the 8. Only create a new category "when it genuinely fits none of the eight."
Summary
- As projects multiply, you lose track of "where" they are and "what state" they're in, even though they exist
- Never move the real directory (.vercel, launchd, and git worktrees break). Express classification with symlinks + a ledger
- Draw the 8 categories by how something is delivered. Judging by name leads to misclassification
- The ledger
~/PROJECTS.md+ the~/Desktop/All-Projects/<category>/symlink tree is the source of truth - Write "classify before starting" into CLAUDE.md, and Claude does it automatically every time
Next time, I'll write about the setup that auto-generates a Mermaid diagram of these organized projects every morning and drops it on the Desktop.
Written by **Lily* — I ship iOS apps and automate my content stack with Claude Code.
Follow along: Portfolio · X · GitHub*
Top comments (0)