🖥️ Case Study: ClaudeOS (Hermes)
Dissect a real long-term project: a personal AI dashboard with Bun + TanStack/React + Vite + Tailwind, deployed on Cloudflare. V2.3 — May/2026.
1 🗺️ Project Overview
ClaudeOS (codename Hermes) is a personal dashboard read-only for anyone running a local AI stack. It consolidates data from multiple sources into a single interface—without modifying any of them.
Bun 1.1
Runtime
React 19
TanStack Query
Vite 6
+ Tailwind 4
Cloudflare
Pages + wrangler
ClaudeOS architecture: sources → pipeline → JSON → React dashboard
Why this project is a good case study
Applies 5.1
Layered architecture with scripts/src separation. Each folder has a single responsibility.
Applies 5.2
CLAUDE.md with explicit security and privacy restrictions. Onboarding greeting.
Applies 5.3
Structured CHANGELOG since V1. Semver tags for each release. V2.3 in May/2026.
2 ⚙️ scripts/aggregate.ts — the heart of the system
The most important file in ClaudeOS isn't a React component — it's a TypeScript script that runs outside the browser. It reads heterogeneous sources and produces a single JSON file consumed by the dashboard.
// scripts/aggregate.ts
// Lê todas as fontes de dados e gera src/data/live-data.json
// NUNCA modifica as fontes — read-only
import { readdir, readFile, writeFile } from 'fs/promises'
import { join } from 'path'
async function aggregateClaudeHistory() {
const historyDir = join(process.env.HOME!, '.claude', 'history')
// Lê arquivos de sessão dos últimos 30 dias
// Extrai: tokens usados, projetos, modelos
return { sessions: [...], tokenTotal: 0 }
}
async function aggregateObsidian() {
const vaultPath = process.env.OBSIDIAN_VAULT_PATH!
// Percorre .md recursivamente, lê frontmatter
return { notes: [...], recentlyModified: [...] }
}
async function main() {
const [claude, obsidian, openrouter, pinecone] = await Promise.all([
aggregateClaudeHistory(),
aggregateObsidian(),
fetchOpenRouterStats(),
fetchPineconeStats(),
])
const liveData = { claude, obsidian, openrouter, pinecone,
generatedAt: new Date().toISOString() }
await writeFile('src/data/live-data.json',
JSON.stringify(liveData, null, 2))
console.log('✅ live-data.json gerado')
}
main()
✓ Elegant pattern
- • Script separate from src/ (single responsibility)
- • Promise.all for parallel I/O
- • Structured, versionable JSON output
- • Generation timestamp included
- • Never modifies the source files (read-only)
🔁 Reusable for
- • Any metrics dashboard
- • Automated reports
- • Consolidating distributed logs
- • Local data pipelines
- • Static feed generation
The “script → JSON → UI” pattern
Separating data collection from presentation is one of the most resilient architectures for personal projects. You can rebuild the dashboard from scratch without losing data. The pipeline can run on cron without the UI existing.
3 💤 The /dream skill — 24-hour audit
The /dream skill is an example of a skill with structured output. It doesn’t respond in prose—it writes a JSON file that the dashboard renders as action cards.
# Skill /dream
## Propósito
Auditar as últimas 24h do stack de IA em 8 buckets de sinal.
Gerar as 4 prescrições de maior impacto em JSON.
## Buckets de sinal
1. Tokens consumidos vs budget diário
2. Projetos mais ativos (por sessão)
3. Skills mais invocadas
4. Notas Obsidian criadas/modificadas
5. Queries Pinecone (tópicos consultados)
6. Modelos OpenRouter usados
7. Dívidas técnicas registradas hoje
8. Commits e PRs abertos
## Output obrigatório
Ao terminar análise, escrever em src/data/dream-output.json:
{
"generatedAt": "ISO-8601",
"buckets": [ { "id": 1, "signal": "...", "value": "..." } ],
"prescriptions": [
{ "rank": 1, "impact": "high", "action": "...", "rationale": "..." }
]
}
## Regras
- NUNCA exibir dados privados em texto livre
- Máximo 4 prescrições, ordenadas por impacto
- Basear APENAS em dados do live-data.json
The 8 signal buckets
1. Tokens
vs budget
2. Projects
most active
3. Skills
most invoked
4. Obsidian
created/mod
5. Pinecone
topics
6. Models
OpenRouter
7. Debt
registered today
8. Commits
and PRs
4 📜 ClaudeOS CLAUDE.md — real example
ClaudeOS's CLAUDE.md is an example of production-level instructions. Each rule has a clear reason for existing.
# ClaudeOS (Hermes) — Instruções do agente
## Saudação de onboarding
Bem-vindo ao ClaudeOS! Você está trabalhando no dashboard
pessoal de IA. Antes de qualquer task, leia este arquivo.
## O que é este projeto
Dashboard read-only que consolida dados de Claude Code,
Obsidian, OpenRouter e Pinecone para visualização pessoal.
Stack: Bun + React 19 + TanStack Query + Vite + Tailwind 4
Deploy: Cloudflare Pages (wrangler)
## Regras OBRIGATÓRIAS
### Privacidade
- NUNCA ler ou escrever diretamente em ~/.claude/
→ Dados chegam via scripts/aggregate.ts e src/data/live-data.json
- NUNCA enviar dados do usuário para serviços externos
- Anonimização LIGADA — remove PII de outputs
- Sem telemetria — sem analytics, sem tracking
### Arquitetura
- Dashboard é READ-ONLY — NUNCA modificar fontes de dados
- Código novo vai em src/ — scripts de dados vão em scripts/
- Não criar arquivos na raiz do projeto
### Segurança
- API keys SEMPRE via variáveis de ambiente (.env)
- .env está no .gitignore — nunca commit
## Estrutura do projeto
src/
components/ → UI React
data/ → live-data.json (gerado, não editado)
scripts/
aggregate.ts → coleta dados das fontes
setup.ts → setup inicial (roda uma vez)
🔍 Why Each Rule Exists
🧩 Reusable pattern
• Onboarding greeting = immediate context
• Rules by category (privacy, architecture, security)
• Inline justification for each critical constraint
• Folder map with an explicit purpose
5 📦 CHANGELOG V2.3 — history as a mirror
The ClaudeOS CHANGELOG tells the story of a project that evolved from a simple script into a complete dashboard. Each version is a milestone.
Documents Gallery
May 31, 2026Added: Obsidian docs viewer in the dashboard. Filter by vault. aggregate.ts 3x faster (parallel processing).
Skill /personas
Apr 15, 2026Added: local YAML persona pantheon. Persona panel in the dashboard. Changed: Vercel → Cloudflare Pages migration.
Skill /dream
Mar 1, 2026Added: /dream skill with 8 signal buckets. Prescriptions panel in the dashboard.
MVP — Walking Skeleton
Jan 10, 2026Basic aggregate.ts script + minimal React dashboard. Claude Code data only.
What the CHANGELOG reveals
Reading the CHANGELOG, you can see that the project started small (V1.0 was Claude Code only), grew incrementally, moved platforms when it made sense, and each version added one thing at a time. That's healthy growth.
6 🔗 Dashboard Mockup and Lessons for Your Project
Tokens today
84.2k
Obsidian notes
1.847
Pinecone queries
23
Invoked skills
7
💤 /dream prescriptions
#1 High priority
Consolidate 3 inactive projects to reduce context overhead
#2 Medium priority
62% of the budget consumed — consider caching repeated prompts
Generated on 2026-06-01T08:00:00Z · READ-ONLY
⚠️ Illustrative HTML mockup — does not represent real data or a screenshot of the system
✓ Repeatable patterns
- • Generator script + JSON artifact + UI
- • CLAUDE.md with restrictions by category
- • Skills with JSON output (not prose)
- • CHANGELOG since V1
- • Walking skeleton growing incrementally
🚀 Apply It to Your Project
- • Identify what your "aggregate.ts" is
- • Define constraints in CLAUDE.md before coding
- • Start the CHANGELOG at V0.1
- • Separate scripts from src/ from the start
- • Read-only where possible — fewer bugs
Download the project ClaudeOS (Hermes) V2.3 · ~88 MB
The complete source code for this case study: the scanner aggregate.ts, o setup.ts, the skills /dream e /personas, o CLAUDE.md e o CHANGELOG. A real, long-term project to study from start to finish.
📋 Track 5 summary
You completed Track 5. Here's what you've mastered:
- 🏗️ 5.1 Project architecture
- 🧠 5.2 CLAUDE.md and memory
- 📦 5.3 Versioning and CHANGELOG
- 🖥️ 5.4 ClaudeOS case study
Track 6 covers Deploy — how to put your project into production with Cloudflare, GitHub Actions, custom domains, and monitoring.
🚀 Go to Track 6: Deploy →