agentleFS
gabriellstgabriellst/codm/.claude/skills/clean-branch/SKILL.md

clean-branch

Skill4 starsChanged 2 months agoMITView on GitHub

Update the `clean` branch by rebasing from `dev` and stripping all domain-specific code. Use when `dev` has architectural changes that should be reflected in the generic boilerplate. Use this skill to maintain the clean boilerplate branch.

  • Deletes or force-pushes

We split this skill into the rules it gives an agent

35 rules. About 0 are common, 17 are distinctive, and 18 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈17

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 18

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If rebase has conflicts, resolve them favoring the clean side for stripped files and dev side for infrastructure files.

    line 76
  2. Distinctive:

    Run discovery to find what needs stripping:

    line 80
  3. Distinctive:

    Remove import for deleted context routers

    line 114
  4. Very specific:

    Remove their entries from the ROUTERS map and from CONTEXTS (the satisfies Record<ContextModule, Router> check fails until both agree — …

    line 115
  5. Very specific:

    Keep only the template contexts: SharedRouter, AuthRouter, BillingRouter, OwnerRouter, QuotaRouter, NotificationsRouter, UiRouter (shared, …

    line 116
  6. Very specific:

    Remove all import statements from deleted contexts (usecases, repositories)

    line 121
  7. Very specific:

    Remove all container.registerSingleton() calls for deleted repos

    line 122
  8. Very specific:

    Update AllUseCases type and allUseCases object to only include auth + ui use cases

    line 123
  9. Distinctive:

    Remove exports for deleted context schemas

    line 126
  10. Very specific:

    Keep only: export * from './authentication' and export * from './ui'

    line 127
  11. Distinctive:

    Remove exports for domain-specific enums

    line 130
  12. Very specific:

    Keep only generic enums: BrazilianState, Country, Language, NotificationLevel, RoleType

    line 131
  13. Distinctive:

    Remove all event exports (events are domain-specific)

    line 134
  14. Distinctive:

    Remove imports from deleted context error types

    line 138
  15. Distinctive:

    Remove error entries for deleted contexts

    line 139
  16. Distinctive:

    Keep: shared, auth, UI, BetterAuth error entries

    line 140
  17. Very specific:

    Update packages/api/typescript/src/ui/controllers/index.ts to only export generic controllers (notifications, onboarding, user details)

    line 154
  18. Very specific:

    Remove enums that only exist for domain UI (e.g., PatientListTab, ServiceStatus, AuditLogType)

    line 157
  19. Very specific:

    Remove domain-specific fields (e.g., type property for user categories)

    line 167
  20. Very specific:

    Default step should be WELCOME

    line 168
  21. Distinctive:

    Delete all domain-specific route directories:

    line 172
  22. Distinctive:

    Remove all SDK imports, replace with static data

    line 199
  23. Distinctive:

    Remove domain-specific navigation items, mode selectors, context selectors

    line 203
  24. Distinctive:

    Remove SDK imports for notifications/user data

    line 208
  25. Very specific:

    Create local types.ts for Notification interface if needed

    line 210
  26. Distinctive:

    Remove domain-specific form fields (e.g., document, language, mode selector)

    line 214
  27. Very specific:

    Remove domain-specific session fields (e.g., mode)

    line 229
  28. Distinctive:

    Keep only generic user fields

    line 230
  29. Very specific:

    Ensure all references use @monorepo namespace (not the project-specific name):

    line 242
  30. Very specific:

    If found, replace with @monorepo equivalents:

    line 249
  31. Very specific:

    Verify the generated SQL only contains authentication and ui schema tables.

    line 264
  32. Distinctive:

    Ensure README.md is generic boilerplate (not domain-specific).

    line 273
  33. Distinctive:

    Search for any remaining domain-specific references:

    line 299
  34. Distinctive:

    Commit in logical batches or as a single squashed commit:

    line 313
  35. Very specific:

    After deleting frontend routes, always run cd packages/app && bun tsr generate before committing.

    line 340

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Update Clean Branch

Synchronizes the clean branch with dev by rebasing and then stripping all domain-specific code, leaving a generic fullstack TypeScript boilerplate.

Why This Exists

The clean branch serves as a reusable starting point for new projects. Whenever dev gains architectural improvements (new patterns, infrastructure, tooling), clean should inherit those improvements without any domain-specific code.

When to Use

  • dev has new architectural changes (infrastructure, tooling, shared patterns) that clean should inherit
  • New bounded contexts were added to dev that need to be stripped from clean
  • New frontend routes/pages were added that are domain-specific
  • Shared utilities or enums were added that are domain-specific

When NOT to Use

  • Changes on dev are purely domain-specific with no architectural value
  • The clean branch doesn't exist yet (create it first with a full initial strip)
  • You only need to fix a bug on clean (just fix it directly)

Prerequisites

  • The clean branch exists and was previously stripped
  • You understand which bounded contexts are domain-specific vs. generic
  • Working directory is clean (no uncommitted changes)

What Gets Kept vs. Stripped

Always Keep (Generic Infrastructure)

CategoryWhat
Backend contextsshared, auth, ui
Shared enumsCountry, Language, BrazilianState, NotificationLevel, RoleType
Shared infraDI container, error handling, OpenAPI, mediator, services
AuthBetterAuth setup, session, sign-in/sign-up controllers
UI contextOnboarding (generic), user details, notifications
FrontendLanding page (generic), sign-in, sign-up, reset-password, dashboard (generic)
ComponentsNavbar (Dashboard only), Header (breadcrumbs + notifications), all primitives
Skills & AgentsAll .claude/skills/ and .claude/agents/ (with @monorepo namespace)
DocsBACKEND.md, FRONTEND.md, COMPONENTS.md

Always Strip (Domain-Specific)

CategoryWhat
Backend contextsAny context beyond shared, auth, ui (e.g., clinic, doctor, patient, service, agent)
Domain enumsEnums tied to business logic (e.g., AppointmentStatus, MemberType, ExternalPlatform)
Domain schemasDrizzle schema files beyond authentication.ts and ui.ts
Domain eventsAll event files (events are domain-specific by nature)
Frontend routesAny route beyond /dashboard, /sign-in, /sign-up, /reset-password, / (landing)
Domain componentsDashboard sections beyond generic overview, domain-specific dialogs/forms
Project docsSYSTEM.md, PRD.md, .plans/, docs/reviews/, prompts/

Process

Step 0: Preparation

# Ensure clean working directory
git status

# Switch to clean branch
git checkout clean

# Rebase onto dev
git rebase dev

If rebase has conflicts, resolve them favoring the clean side for stripped files and dev side for infrastructure files. If too many conflicts, consider git checkout clean && git reset --hard dev and re-stripping from scratch.

Step 1: Identify What's New on dev

Run discovery to find what needs stripping:

# List all backend contexts (directories under packages/api/typescript/src/ with index.ts)
ls -d packages/api/typescript/src/*/

# List all Drizzle schema files
ls packages/api/typescript/src/shared/db/drizzle/schema/

# List all frontend route directories
ls -d packages/app/src/routes/*/
ls -d packages/app/src/routes/\(app\)/*/

# List all shared enums
ls packages/api/typescript/src/shared/enums/

# List all shared events
ls packages/api/typescript/src/shared/events/

# Search for domain-specific routers in the composition root
grep "import.*Router.*from" packages/api/typescript/src/routers.ts

Compare against the "Always Keep" list above. Everything else is a candidate for stripping.

Step 2: Strip Backend Contexts

For each domain-specific context directory:

rm -rf packages/api/typescript/src/<context>/

Then update packages/api/typescript/src/routers.ts and the CONTEXTS manifest (packages/api/typescript/src/shared/contexts.ts):

  • Remove import for deleted context routers
  • Remove their entries from the ROUTERS map and from CONTEXTS (the satisfies Record<ContextModule, Router> check fails until both agree — same for CONTEXT_REGISTRIES in shared/registry.ts)
  • Keep only the template contexts: SharedRouter, AuthRouter, BillingRouter, OwnerRouter, QuotaRouter, NotificationsRouter, UiRouter (shared, auth, billing, owner, quota, notifications, ui)

Step 3: Clean Shared References

packages/api/typescript/src/shared/index.ts (DI container):

  • Remove all import statements from deleted contexts (usecases, repositories)
  • Remove all container.registerSingleton() calls for deleted repos
  • Update AllUseCases type and allUseCases object to only include auth + ui use cases

packages/api/typescript/src/shared/db/drizzle/schema/index.ts:

  • Remove exports for deleted context schemas
  • Keep only: export * from './authentication' and export * from './ui'

packages/api/typescript/src/shared/enums/index.ts:

  • Remove exports for domain-specific enums
  • Keep only generic enums: BrazilianState, Country, Language, NotificationLevel, RoleType

packages/api/typescript/src/shared/events/index.ts:

  • Remove all event exports (events are domain-specific)
  • Replace with: // Domain events will be added here as contexts are created

packages/api/typescript/src/shared/utils/GlobalErrorMapper.ts:

  • Remove imports from deleted context error types
  • Remove error entries for deleted contexts
  • Keep: shared, auth, UI, BetterAuth error entries

Delete domain-specific shared files:

  • packages/api/typescript/src/shared/db/drizzle/schema/<context>.ts for each deleted context
  • packages/api/typescript/src/shared/enums/<DomainEnum>.ts for domain enums
  • packages/api/typescript/src/shared/events/<DomainEvent>.ts for all events
  • packages/api/typescript/src/shared/schemas/<domain>.ts for domain schemas

Step 4: Clean UI Context

The ui context often accumulates domain-specific BFF controllers and enums.

Delete domain-specific UI controllers:

  • Any controller directory under packages/api/typescript/src/ui/controllers/ that serves domain pages (e.g., dashboard/, patients/, services/)
  • Update packages/api/typescript/src/ui/controllers/index.ts to only export generic controllers (notifications, onboarding, user details)

Delete domain-specific UI enums:

  • Remove enums that only exist for domain UI (e.g., PatientListTab, ServiceStatus, AuditLogType)
  • Simplify OnboardingStep to: { WELCOME, COMPLETED }

Simplify UI use cases:

  • CompleteOnboarding: Remove domain entity creation (e.g., doctor/clinic), just mark as completed
  • GetUserDetails: Remove domain queries, return basic user info only
  • SaveOnboardingState: Remove domain-specific schema fields
  • GetOnboarding: Remove domain-specific type fields

Simplify Onboarding entity:

  • Remove domain-specific fields (e.g., type property for user categories)
  • Default step should be WELCOME

Step 5: Strip Frontend Routes

Delete all domain-specific route directories:

# Delete domain-specific app routes
rm -rf packages/app/src/routes/\(app\)/<domain-route>/

# Delete domain-specific standalone routes
rm -rf packages/app/src/routes/<domain-route>/

# Delete domain-specific dashboard sections
rm -rf "packages/app/src/routes/(app)/dashboard/-components/<DomainSection>/"

Keep only:

  • packages/app/src/routes/(app)/dashboard/ (with generic OverviewSection only)
  • packages/app/src/routes/(index)/ (landing page)
  • packages/app/src/routes/sign-in/
  • packages/app/src/routes/sign-up/
  • packages/app/src/routes/reset-password/
  • packages/app/src/routes/(app)/route.tsx (layout)

Step 6: Simplify Frontend Components

Dashboard (packages/app/src/routes/(app)/dashboard/):

  • Rewrite index.tsx to only render <OverviewSection />
  • Rewrite -components/index.tsx to only export OverviewSection + OverviewSectionSkeleton
  • Simplify OverviewSection to show a welcome message and generic placeholder stats
  • Remove all SDK imports, replace with static data

Navbar (packages/app/src/components/Navbar/index.tsx):

  • Single NAVIGATION_ITEMS with only Dashboard
  • Remove domain-specific navigation items, mode selectors, context selectors
  • Remove SDK imports
  • Generic logo ("App" with IconLayoutDashboard)

Header (packages/app/src/components/Header/):

  • Remove SDK imports for notifications/user data
  • Replace with mock data + // TODO: Replace with real data hooks when SDK is available
  • Create local types.ts for Notification interface if needed

Auth pages (sign-in, sign-up, reset-password):

  • Replace SDK schema imports with inline zod schemas
  • Remove domain-specific form fields (e.g., document, language, mode selector)
  • Generic sidebar content (no domain branding)
  • Navigation should go to / or /dashboard, not domain-specific routes

Landing page (packages/app/src/routes/(index)/index.tsx):

  • Replace all domain content with generic SaaS boilerplate in English
  • Placeholder features, stats, testimonials
  • Generic "App" branding

Frontend lib files:

  • packages/app/src/lib/labels.ts: Empty with export {}
  • packages/app/src/lib/consts.ts: Empty with export {}
  • packages/app/src/lib/errors.ts: Remove SDK error imports, keep generic error utilities

Vite env types (packages/app/src/vite-env.d.ts):

  • Remove domain-specific session fields (e.g., mode)
  • Keep only generic user fields

Step 7: Regenerate Route Tree

cd packages/app && bun tsr generate

This removes deleted routes from routeTree.gen.ts.

Step 8: Namespace Check

Ensure all references use @monorepo namespace (not the project-specific name):

# Search for project-specific namespace
grep -ri "<project-name>" --include="*.ts" --include="*.tsx" --include="*.json" --include="*.md" -l .

If found, replace with @monorepo equivalents:

  • Package names: @monorepo/api, @monorepo/app, @monorepo/sdk
  • SDK imports: @monorepo/sdk/app, @monorepo/sdk/http, @monorepo/sdk/api
  • Skills/agents: @monorepo/sdk references

Step 9: Fresh Database Migration

# Delete old migrations
rm -rf packages/api/typescript/src/shared/db/drizzle/migrations

# Generate fresh migration from current clean schema
bun migrate:create

Verify the generated SQL only contains authentication and ui schema tables.

Step 10: Clean Project Docs

rm -f SYSTEM.md PRD.md
rm -rf docs/reviews .plans prompts

Ensure README.md is generic boilerplate (not domain-specific). Ensure CLAUDE.md uses "Monorepo Boilerplate" title.

Step 11: Verify Build

# Type check
bun tsc

# Lint
bun lint

# Tests
bun test

# Full build (optional but recommended)
bun build

Fix any errors. Common issues:

  • Empty files that aren't modules (add export {})
  • Unused imports from deleted code
  • Missing error entries in GlobalErrorMapper
  • Route tree referencing deleted routes

Step 12: Final Sweep

Search for any remaining domain-specific references:

# Search for domain terms in source files
grep -ri "clinic\|patient\|doctor\|appointment\|specialty" --include="*.ts" --include="*.tsx" -l packages/app/src/ packages/api/typescript/src/

# Search for project-specific name
grep -ri "<project-name>" --include="*.ts" --include="*.tsx" --include="*.json" --include="*.md" -l .

Fix any remaining references. Then commit.

Step 13: Commit

Commit in logical batches or as a single squashed commit:

git add -A
git commit -m "chore: update clean branch from dev - strip domain-specific code"

Critical Rules

Always Run Type Check Before Committing

The pre-commit hook runs bun tsc, bun test, and full build. Deleting contexts without fixing dangling imports will fail the commit. Fix ALL references atomically — don't try to commit partial deletions.

Backend DI Container Is the Hub

packages/api/typescript/src/shared/index.ts registers ALL repositories and use cases. When deleting a context, you MUST remove its registrations here or the build will fail.

GlobalErrorMapper Must Be Exhaustive

The GlobalErrorMapper Record type requires entries for ALL error types across all remaining contexts. If you remove an error type from a context but it's still referenced by another context's error union, you'll get a type error. Either remove the reference or keep the entry.

BetterAuth May Have Deep Coupling

Auth hooks (e.g., afterSignInHook, customSession) may reference domain-specific types/repos. Review packages/api/typescript/src/auth/services/Authentication/BetterAuth.ts carefully and remove domain-specific plugins/hooks.

Route Tree Must Be Regenerated

After deleting frontend routes, always run cd packages/app && bun tsr generate before committing. The generated routeTree.gen.ts will reference deleted routes and cause build failures.

Events Are Always Domain-Specific

Domain events should be completely removed. The shared events barrel (packages/api/typescript/src/shared/events/index.ts) should be empty. Event handlers go away with their contexts.

UI Context Accumulates Domain Code

Even though ui is a kept context, it often has domain-specific BFF controllers, enums, and use case logic that reference deleted contexts. Always audit packages/api/typescript/src/ui/ thoroughly.

Checklist

  • Rebased clean onto latest dev
  • Identified all new domain-specific contexts since last sync
  • Deleted domain-specific backend context directories
  • Cleaned packages/api/typescript/src/routers.ts (ROUTERS map) + the CONTEXTS manifest
  • Cleaned packages/api/typescript/src/shared/index.ts DI registrations
  • Cleaned shared schemas, enums, events, errors
  • Cleaned GlobalErrorMapper
  • Cleaned UI context (controllers, enums, use cases)
  • Deleted domain-specific frontend routes
  • Simplified dashboard to generic overview
  • Simplified navbar (Dashboard only, no mode/context selectors)
  • Simplified header (mock data, no SDK imports)
  • Simplified auth pages (inline schemas, no domain fields)
  • Genericized landing page
  • Cleaned frontend lib (labels, consts, errors)
  • Cleaned vite-env.d.ts (no domain session fields)
  • Regenerated route tree (cd packages/app && bun tsr generate)
  • Verified namespace is @monorepo everywhere
  • Generated fresh database migration
  • Cleaned project docs (no SYSTEM.md, PRD.md, plans, reviews)
  • bun tsc passes
  • bun test passes
  • bun lint passes
  • No remaining domain-specific terms in source files
  • Committed changes

References

  • docs/BACKEND.md - Backend conventions
  • docs/FRONTEND.md - Frontend conventions
  • packages/api/typescript/src/shared/index.ts - DI container (central hub for registrations)
  • packages/api/typescript/src/shared/utils/GlobalErrorMapper.ts - Error mapping (must be exhaustive)
  • packages/api/typescript/src/shared/db/drizzle/schema/index.ts - Schema barrel exports

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.