I built 30 AI plugins for Claude Code, and then I threw away the architecture that held them together. Not because it didn't work. Because it worked in a way that couldn't scale.
This is the technical story behind Founder OS's biggest pivot: how 33 separate plugins became one, why 32 Notion databases became 22, and what the namespace pattern looks like in practice. If you're building Claude Code plugins or thinking about plugin architecture, this is what I wish I'd known on day one.
Key Takeaways
- 33 separate Claude Code plugins consolidated into 1 namespace-based plugin, reducing code by 229 lines
- The Type column pattern merged 32 Notion databases into 22 interconnected ones under a single hub
- Namespace routing (
/founder-os:namespace:action) replaced 33 separate manifests with one directory convention- Claude Code's plugin loader ignores symlinked directories, which forced the entire restructure
- Adding a new namespace now requires only creating a directory, with zero config changes
Why Did 33 Separate Plugins Stop Working?
The Claude Code plugin ecosystem now features 72+ plugins across 24 categories (Claude Marketplaces, 2026). Most are single-purpose tools. Founder OS tried to be 33 of them at once, each in its own directory with its own manifest. That's where the trouble started.
Each plugin had its own .claude-plugin/plugin.json, its own .mcp.json, its own skills directory, its own commands. The installation mechanism used symlinks: create a link from ~/.claude/plugins/ to each plugin directory. Architecturally clean. Practically broken.
Here's what I discovered: Claude Code's plugin loader ignores symlinked directories. The path through ~/.claude/plugins/marketplaces/ is for marketplace-installed plugins only. Symlinked directories were invisible to the loader, making commands, skills, and agents unreachable after installation.
I'd built 30 plugins that couldn't be installed. The official Claude Code plugin documentation (Anthropic, 2026) confirms that plugins require a plugin.json at the repository root. Symlinks don't count. The fix wasn't a patch. It was a rethink.
What Does a Single-Plugin Architecture Look Like?
84% of developers now use or plan to use AI tools in their development workflow (Stack Overflow, 2025). But most AI plugin systems assume one plugin does one thing. Founder OS needed one plugin to do 82 things. The answer was namespaces.
The restructure placed a single plugin.json at the repository root. Instead of 33 manifests, there's one. Instead of 33 installation steps, there's one directory. The magic happens in the folder structure:
founderOS/
.claude-plugin/
plugin.json # One manifest for everything
commands/
inbox/
triage.md # /founder-os:inbox:triage
drafts-approved.md # /founder-os:inbox:drafts-approved
briefing/
briefing.md # /founder-os:briefing:briefing
review.md # /founder-os:briefing:review
prep/
prep.md # /founder-os:prep:prep
today.md # /founder-os:prep:today
...32 namespace directories
skills/
inbox/
email-prioritization/SKILL.md
briefing/
task-curation/SKILL.md
...
agents/
inbox/
triage-agent.md
action-agent.md
...
The naming convention is the routing system. commands/inbox/triage.md becomes /founder-os:inbox:triage. No routing table. No registration step. Drop a markdown file in the right directory and it becomes a command.
Why Markdown?
Everything in the plugin is markdown. Commands are markdown files describing slash command behavior. Skills are markdown files containing domain knowledge. Agents are markdown files defining roles and tool access. No compiled code. No build step. No API to learn.
This matters because it makes plugins writable by AI. Claude Code can read, modify, and create plugin components because they're all in the format it understands natively. The factory system that built 30 plugins in 6 days only worked because the target format was markdown.
How Do You Merge 32 Databases Without Losing Data?
MCP Tool Search reduces context usage by up to 95%, making it practical to install 10+ MCP servers without performance degradation (Claude Code Changelog, 2026). But Founder OS's problem wasn't MCP servers. It was Notion databases. 32 of them.
Each of the original 30 plugins created its own databases. Plugin 01 (Inbox Zero) had an Email Tasks database. Plugin 04 (Action Items) had an Action Items database. Plugin 06 (Follow-Up Tracker) had a Follow-Ups database. Three separate databases for things that are fundamentally the same: tasks with different types.
The consolidation used what I call the Type column pattern. Notion's select property allows a single column to hold one value from a predefined list (Notion Developers, 2026). Instead of separate databases, you create one shared database with a Type select property. Each plugin writes its own Type value:
[FOS] Tasks (single database)
Type = "Email Task" -> written by P01 Inbox Zero
Type = "Action Item" -> written by P04 Action Items
Type = "Follow-Up" -> written by P06 Follow-Up Tracker
Same database. Different views. Each plugin sees only its own records through a filtered view. But the data is queryable together. Want to see all open items across email, action items, and follow-ups? One database query.
The Full Consolidation Map
The pattern applied across the entire system:
| Consolidated Database | Merged From | Type Values |
|---|---|---|
| Tasks | P01 + P04 + P06 | Email Task, Action Item, Follow-Up |
| Briefings | P02 + P05 + P19 + P22 | Daily Briefing, Weekly Review, Slack Digest, Morning Sync |
| Finance | P11 + P16 | Invoice, Expense |
| Content | P01 + P08 + P24 + P33 | Email Draft, Newsletter, LinkedIn Post, Content Atom |
| Deliverables | P12 + P13 + P14 | Proposal, Contract, SOW |
| Research | P08 + P15 | Newsletter Research, Competitive Analysis |
| Reports | P09 + P16 + P25 + P33 | Business Report, Expense Report, ROI Report, Content Report |
32 databases became 22. But the real win was the hub-and-spoke model.
The Hub-and-Spoke CRM Model
The [FOS] Companies database sits at the center. Every client-facing database links back to it through Notion relation properties. When Inbox Zero processes an email from a client, it matches the sender's domain to a Company record and populates the relation. When CRM Sync logs a meeting, it links to the same Company. When Invoice Processor extracts a vendor name, same link.
The result: open any Company page in Notion and see every email task, meeting, proposal, invoice, and follow-up associated with that client. One page. Zero manual linking. No orphaned records in forgotten databases. For a walkthrough of the 82+ commands that write to these databases, see the Founder OS feature tour.
Real-World Example: How the Morning Sync Traverses the System
The hub-and-spoke model and Type column pattern sound clean in theory. Here is what they look like when an actual command runs. Consider /founder-os:morning:sync, the command I run every day before my first meeting.
When the Morning Sync fires, it needs to answer three questions: what happened overnight, what's on the calendar today, and what's overdue. That means reading from three consolidated databases in a single execution.
First, it queries [FOS] Briefings with a filter for Type = "Daily Briefing" and Date = yesterday. This pulls the previous day's briefing so it can summarize anything unresolved. The same database holds Weekly Reviews, Slack Digests, and other briefing types, but the Type filter ensures Morning Sync only sees its own lane.
Next, it queries [FOS] Tasks with a compound filter: Status != "Done" AND Due Date <= today. This returns overdue items regardless of whether they originated from Inbox Zero (Type = "Email Task"), the Action Items extractor (Type = "Action Item"), or the Follow-Up Tracker (Type = "Follow-Up"). Before consolidation, this would have required three separate database queries and a manual merge of results. Now it is one query.
Then it pulls today's calendar events via the gws CLI (Google Workspace CLI for Gmail, Calendar, and Drive access) and cross-references them against [FOS] Meetings to check for existing prep notes. If a meeting has a linked Company record, the sync pulls that company's health scores directly from [FOS] Companies, the hub of the spoke model. One relation lookup replaces what used to be a separate Client Context command.
The output is a single Briefing page written back to [FOS] Briefings with Type = "Morning Sync". It links to the relevant Company records, references the overdue Tasks by ID, and includes calendar context. All of this happens in one command execution touching four consolidated databases.
The key insight: because Tasks, Briefings, and Meetings all relate back to Companies, the Morning Sync can build a client-aware daily summary without any namespace needing to know about any other namespace's internal data model. Each namespace writes its Type. The consolidated database handles the rest.
This pattern repeats across the system. The Weekly Review (/founder-os:review:weekly) queries the same Briefings database but filters for Type = "Daily Briefing" over the past seven days, then enriches with Tasks completed that week. The Client Health Dashboard reads Communications, Tasks, and Finance records for a single Company. Every command operates independently, but the shared schema means their outputs compose naturally.
What Happened to the 393 Files?
The restructure touched 393 files in a single operation. 304 insertions, 533 deletions. Net result: -229 lines of code. The system got simpler, not more complex.
Here's the breakdown of what actually moved:
- 32 namespace command directories created under
commands/ - 97 skill files migrated from per-plugin skill directories to
skills/[namespace]/ - 33 plugin.json manifests replaced by 1 root manifest
- 33 .mcp.json files consolidated into 1 shared MCP configuration
- All agent definitions reorganized under
agents/[namespace]/
The old structure required updating a manifest, an MCP config, an installation script, and documentation every time you added a plugin. The new structure requires creating a directory. That's it.
The Three-Step Database Discovery Pattern
Every command in Founder OS finds its target Notion database the same way:
- Search for
[FOS] Tasks(the HQ naming convention) - Fall back to
Founder OS HQ - Tasks(legacy format) - Fall back to the plugin-specific name (backward compatibility)
This three-step pattern means the system works whether you installed the full HQ template or just have individual databases from an earlier version. Graceful degradation built into the discovery layer.
The seven initial test failures in Pillar 2? All came from commands that searched for "Founder OS HQ - Briefings" when the database was actually named [FOS] Briefings. Seventeen files, four plugins, one root cause. Find and replace fixed it. The boring bugs are always the real ones.
How Does This Compare to Other Plugin Architectures?
Monorepo consolidation reduces dependency conflicts by up to 60% compared to multi-repo setups (Spectro Cloud, 2026). Founder OS's restructure followed the same principle. One repository. One manifest. One installation step. Complexity managed through convention rather than configuration.
Most Claude Code plugins are single-purpose. A Git helper. A Notion connector. A code reviewer. They work well alone. But when you need 30 tools that share data, share MCP connections, and share business context, the single-purpose model breaks down.
The namespace pattern solves this by treating each tool as a directory within a shared structure rather than an isolated package. Shared infrastructure lives in _infrastructure/. Shared skills live in skills/. Shared agents live in agents/. Nothing is duplicated. When I update the database discovery pattern, every namespace gets the fix.
The Graceful Degradation Pattern
Not every founder uses every tool. Some don't have Slack. Some skip Gmail and use Outlook. Some run Founder OS purely for Notion-based task management and never touch the email namespaces. The architecture has to handle all of these configurations without breaking.
Every namespace in Founder OS checks for its required MCP servers and external tools at startup. If a tool is missing, the namespace doesn't crash. It returns status: "unavailable" for that data source and continues with whatever it can access. This is the graceful degradation pattern, and it is baked into every single command.
Here is a concrete example. The Daily Briefing (/founder-os:briefing:briefing) uses a Parallel Gathering pattern. It dispatches agents to fetch from Gmail, Google Calendar, Notion, and Slack simultaneously. If the Slack MCP server isn't configured, the Slack agent returns { status: "unavailable", source: "slack" } instead of throwing an error. The lead agent receives results from the three working sources, notes that Slack was unavailable, and assembles the briefing without it. The user sees a complete briefing with a single line noting "Slack digest: unavailable (not configured)."
This matters because the alternative is fragile coupling. In the old 33-plugin architecture, each plugin either worked completely or failed completely. There was no partial execution. If your Slack token expired, the entire Daily Briefing plugin would error out, even though 80% of the briefing had nothing to do with Slack.
The pattern works at the database layer too. If the three-step database discovery finds none of the expected database names, the command doesn't fail. It logs a warning and, for non-HQ users, falls back to lazy database creation. The system adapts to whatever infrastructure exists rather than demanding a perfect setup before it will run.
For solo founders, this is the difference between a tool you actually use daily and a tool that sits broken after your first token refresh. Every optional dependency is truly optional. The core loop always runs.
Is this the right architecture for every plugin? No. Single-purpose plugins should stay single-purpose. But if you're building a suite of related tools that need to share state, the namespace pattern is worth considering.
Frequently Asked Questions
Can I use the namespace pattern for my own Claude Code plugins?
Yes. Create a single plugin.json at your repo root, then organize commands into subdirectories under commands/. Each subdirectory becomes a namespace. The naming convention commands/[namespace]/[action].md maps directly to /your-plugin:namespace:action. No routing configuration needed.
Does the Type column pattern work for large datasets?
It works well up to several thousand records per database, which covers most solo founder and small team use cases. Notion's filtering is fast enough that Type-based views don't add noticeable latency. For enterprise scale, you'd want separate databases with cross-database relations instead.
What happens if I only want some namespaces?
Everything degrades gracefully. Each namespace checks for its required MCP servers at startup. If Gmail isn't configured, the inbox namespace reports "unavailable" and lets you continue with the 20+ namespaces that don't need email access. No crashes. No error chains. Just reduced functionality.
How do I add a new namespace to Founder OS?
Create a directory under commands/ with your namespace name. Add a markdown command file. Optionally add skills under skills/[namespace]/ and agents under agents/[namespace]/. That's the full process. No manifest updates. No installation scripts. The plugin discovers new namespaces automatically.
Lukas Halicki is a software architect with over 15 years of experience building enterprise systems at Swiss banking institutions. He designed Founder OS's namespace architecture after discovering that Claude Code's plugin loader couldn't handle the original 33-plugin structure, and now helps other founders build AI automation through NaluForge.
The Architecture Lesson
Good architecture doesn't always mean more abstraction. Sometimes it means less. The move from 33 plugins to 1 wasn't a compromise. It was an upgrade. Fewer manifests, fewer configs, fewer installation steps, fewer places for bugs to hide. And -229 lines of code to prove it.
The best plugin architecture is the one that gets out of the way. Add a directory. Drop in a markdown file. Ship a command.
npx founder-os@latest --initIf you want to see the namespace pattern in action, install Founder OS and explore the commands/ directory. Or if you'd rather have custom AI automation built for your business, book a call with NaluForge.
Previous: How I Built 30 AI Plugins in 6 Days Using Claude Code Next: I Threw Away My First Day of Code (And It Was the Best Decision I Made)
