DEV Community

Lily
Lily

Posted on • Originally published at dev.to

Before Your Side Projects Multiply Into Chaos: An 8-Category Ledger and a Symlink Tree

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.

  1. .vercel/project.json — the Vercel link contains an absolute path. Move it, and vercel deploy points at a different project.
  2. launchd plist — the script path written in ProgramArguments is registered as the real path. Move it, and the cron job dies.
  3. git worktree — the metadata for a worktree created with git worktree add holds 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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." Read package.json or the README and judge by how it's delivered.
  • Secret-key leak risk in 05-client-worktoc-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 remoteababa-pr/* and fujibee/* are treated as 05-client-work and pushing is forbidden. Check the owner with git remote -v before 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)