LUCIANO CARRIZO
opcode-lucho
Todos los proyectos
Finalizado

opcode-lucho

App de escritorio (Tauri + Rust + React) para gestionar proyectos y sesiones de Claude Code, con dashboard de consumo de tokens. Es un fork de winfunc/opcode (AGPL-3.0) que llevé a workspace propio: navegación rehecha, dashboard de uso reescrito y la CI heredada puesta en verde — 250 commits en features y adaptación.

TauriRustTypeScriptReact
Resumen

Una GUI de escritorio para Claude Code, sobre un codebase que no escribí

opcode-lucho es una aplicación de escritorio (Tauri 2 + Rust en el backend, React 18 + TypeScript en el frontend) que le da interfaz gráfica a Claude Code: gestión de proyectos y sesiones, agentes propios, servidores MCP, checkpoints y un dashboard de consumo de tokens. No es un producto original mío ni un servicio web, y no está afiliado a Anthropic.

Es un fork de winfunc/opcode, licenciado AGPL-3.0. GitHub no lo marca como fork técnico (el repo es independiente, con el historial upstream importado), así que la única forma de que se sepa es decirlo yo: de los 522 commits del repo, 321 son míos (250 sin contar merges, a lo largo de 10 días de trabajo, 2026-07-02 a 2026-07-11). El resto — el concepto de la app, el andamiaje Tauri, los agentes de Claude Code, MCP, checkpoints y buena parte de los componentes — vino del upstream. Cargo.toml sigue acreditando a sus autores originales; no toqué esa línea.

Vista de chat de opcode-lucho: mensajes con conteo de tokens, bloque de código resaltado y selector de modelo/effort
El chat con Claude Code dentro de la app: conteo de tokens por mensaje, selector de modelo y de effort.
El punto de partida

Lo que heredé, tal cual estaba

El fork arranca en el commit 70c16d8 (2025-10-13, el último del upstream antes de mi primer commit propio). El propio README lo dice de frente, con un aviso [!IMPORTANT]:

“This is a fork. opcode-lucho is a personal fork of winfunc/opcode (originally by Asterisk), licensed under AGPL-3.0… do not report issues about this fork upstream.”

Heredé el concepto entero de la app y su andamiaje: Tauri 2 + React, los agentes de Claude Code, MCP, checkpoints, el servidor web (web_server.rs) y la mayoría de src/components/. También heredé la licencia AGPL-3.0 y el crédito de los autores upstream con más volumen (Vivek R, Mufeed VH, Kiran Johns), que dejé intacto en Cargo.toml.

Lo que no heredé fue nada del cómo se mantiene: ni CI en verde, ni documentación propia, ni una navegación que yo entendiera de memoria. Eso es lo que sigue.

Lo que rehice

Navegación y detalle de proyecto, desde cero

01

Sidebar y navegación

LeftSidebar.tsx, archivo nuevo de +1.067 líneas: tab strip por proyecto, titlebar propio estilo Windows y una vista Home que no existía.

02

Detalle de proyecto

ProjectDetail.tsx (nuevo, +502), ProjectFileTree.tsx, SessionAside.tsx y SessionPickerDialog.tsx: la vista que faltaba para entrar a un proyecto y ver sus sesiones sin perderse.

03

Plantillas y backups de CLAUDE.md

claude_templates.rs, claude_backups.rs y claude_fs.rs en el backend, más ClaudeTemplatesView.tsx (+394) en el frontend.

04

Application settings

app_settings.rs + ApplicationSettings.tsx, nuevos los dos, con settings que cablean comportamiento real de la app, no un formulario decorativo.

Nada de esto estaba en el upstream. Cada pieza entró por su propio PR (72 en total, todo el trabajo pasó por revisión antes de mergear a master).

Entender lo que no escribiste

16 documentos para poder tocar código ajeno

Antes de reescribir una vista tenía que entender cómo estaba armada la que ya existía, y el upstream no traía esa documentación. Terminé escribiendo docs/views/: 16 documentos, uno por vista, en inglés, escritos después de construir la feature correspondiente — no como planificación, sino como el mapa que me hubiera ahorrado tiempo si hubiera existido antes.

navigation-model.md es el que más uso: describe cómo se relacionan el sidebar, el tab manager y el titlebar, que es exactamente la parte que reescribí en la zona anterior. Documentar un codebase ajeno terminó siendo tan parte del trabajo como escribir el código nuevo.

El dashboard de uso

Reescribir el backend de métricas, no solo la vista

El dashboard de consumo de tokens venía del upstream, pero terminé reescribiéndolo de punta a punta, y es la pieza en la que más tiempo invertí de las cuatro. src-tauri/src/commands/usage.rs (+1.383 / −329 líneas) es el archivo más tocado de todo el repo — más que cualquiera de la navegación. Del lado del frontend, una carpeta nueva entera, src/components/usage-detail/ (17 archivos), más dashboard/DashboardBento.tsx y la lógica de agregación extraída a lib/usageAggregation.ts (+349).

Dashboard de uso de opcode-lucho: bento de 11 métricas, panel de filtros por modelo y gráfico de actividad temporal
El dashboard hoy: bento de 11 métricas arriba, filtros por modelo y un gráfico de actividad que cruza costo, tokens y sesiones.

Lo que se ve en esa captura es el resultado, no el punto de partida. El upstream traía una vista de uso con métricas sueltas; lo que reescribí fue tanto el cómo se calculan (el backend en Rust, que es donde cayó el grueso del diff) como el cómo se leen: un bento de 11 métricas de un vistazo, un panel de filtros por modelo, y un gráfico de actividad temporal que cruza tres métricas — costo, tokens, sesiones — con tres formas de visualizarlas — barras, velas, línea — en vez de un solo gráfico fijo.

El upstream describe la mejora como “carga mucho más rápida en historiales grandes”. No tengo un antes/después medido de esa afirmación, así que no invento un número acá — pero coincide con por qué me metí a tocar el backend en primer lugar: la vista de uso original no aguantaba bien un historial de sesiones grande, y la reescritura de usage.rs fue la respuesta a eso, no un capricho de diseño.

Separar la lógica de agregación en un módulo puro (usageAggregation.ts) en vez de dejarla mezclada en los componentes fue deliberado: es el mismo criterio que apliqué en los otros 12 módulos nuevos de src/lib/ — la lógica derivada del frontend vive aparte de la vista que la consume.

Cierre

Heredar código también es heredar su infraestructura

Cicatriz

La CI heredada nunca había pasado en verde

El workflow pr-check.yml fallaba en TODOS los PRs, por dos causas apiladas y ninguna del código: primero, nunca instalaba las dependencias de sistema de Tauri en ubuntu-latest ("Package glib-2.0 was not found"), aunque la lista correcta ya existía en otro workflow del mismo repo. Arreglado eso, seguía fallando porque bun run check corre tsc y cargo check, y cargo check necesita dist/index.html (vía include_str! en web_server.rs) — algo que tsc nunca genera, porque solo tipa. Había que compilar el frontend antes de correr cargo check. Hoy pr-check pasa en 7m51s.

Por qué no hay binarios distribuibles

Hay un tag v0.3.1 sobre master, el primer release propio del fork, pero no hay ningún GitHub Release publicado. El workflow de macOS pide 7 secrets de firma y notarización de la cuenta de Apple Developer del proyecto original, que no se heredan al forkear — sin ellos, y sin firma, macOS Gatekeeper bloquea la app. Es una restricción externa, no una carencia técnica.

También protegí master y dev con rulesets sin bypass para nadie, ni para mí como admin: exigen PR y el check bun run check en verde, y bloquean el force-push. Un dato que aprendí en el camino: los rulesets de protección no existen en GitHub Free para repos privados — el orden quedó forzado a público primero, protección después, y así lo hice.

El proyecto está cerrado como versión, no distribuido: lo que siga desde acá van a ser fixes puntuales, no una vuelta a trabajarlo a este ritmo.

Siguiente paso

El caso muestra el código. Hablemos de lo que sigue.

opcode-lucho está documentado end-to-end: arquitectura, decisiones y lo que quedó pendiente. Si tenés preguntas sobre el enfoque, escribime.

Hablemos

o directamente → LuchoC.dev@gmail.com