Killer

Explorador de archivos desktop (Tauri + Solid + Go + Rust)

Aplicación desktop con Tauri 2 + SolidJS donde el filesystem real vive en Go (sidecar) y Rust actúa como puente IPC por stdio con JSON line-delimited. Incluye ListDir, ReadFile, Tree, Stat, Write y cache reactivo con fallback a mock en modo web. Documentada en README, ARCHITECTURE.md y go/README.md.

2026 · En desarrollo

Captura de Killer
Killer — captura del proyecto.
01

Contexto y propósito

Killer es mi proyecto más “sistemas”: un explorador de archivos desktop con Tauri 2 + SolidJS donde el filesystem real está en Go y Rust solo es el puente IPC. Nació del template Tauri + Solid + TS y evolucionó a arquitectura tri-lenguaje documentada en ARCHITECTURE.md y go/README.md.

Para un reclutador: demuestra IPC real, manejo de procesos hijo, tipos compartidos entre 3 lenguajes y estrategia de fallback web vs desktop.

Propósito declarado: Explorar el filesystem real desde una app desktop ligera, separando responsabilidades: Go para I/O, Rust para IPC seguro y SolidJS para UI reactiva.

02

Arquitectura

SolidJS --invoke--> Rust (Tauri go_bridge) --stdio JSON--> Go (internal/fs). Go expone ping/list_dir/read_file/tree/stat/write/delete; Rust lo spawnea como hijo y expone comandos fs_*; frontend usa fsService + fsCache con fallback a mock.

┌──────────────┐ invoke("fs_*") ┌──────────────┐ stdin JSON ┌──────────────┐
│ SolidJS (TS) │ ────────────────▶ │ Rust (Tauri)   │ ───────────▶ │ Go (fs.SVC)    │
│ fsService +  │ ◀──────────────── │ go_bridge/     │ ◀─────────── │ internal/fs +  │
│ fsCache      │   JSON Response   │ sidecar.rs     │ stdout JSON  │ internal/ipc   │
└──────────────┘                   └──────────────┘              └──────────────┘
         └────────────── TÚNEL IPC stdio (sin HTTP ni sockets) ──────────────┘
stderr solo logs humanos [go]/[rust].
  • Go (killer/go): Service stateless con ListDir, ReadFile (límite 10 MB, detección binarios), Tree recursivo con MaxDepth, Stat, WriteFile, Exists, EnsureDir, Delete. Tipos Directory/FileDeck/File/Stat idénticos a src/types/fs.ts.
  • Rust (src-tauri/src/go_bridge): GoBridge spawnea el binario (busca en binaries/killer-go*, ../go/killer-go, /tmp/killer-go o KILLER_GO_BIN), mantiene Child + pipes con Mutex para llamadas secuenciales; comandos fs_ping/list_dir/read_file/stat/tree/write/delete son proxies delgados. build.rs compila Go automáticamente.
  • Frontend (src/): fsService (invoke + isTauri), fileService híbrido real/mock, fsCache reactivo, mock en cache/file.ts (archs) para vite dev. App.tsx carga mock y luego reemplaza con árbol real.
03

Stack detallado

CapaTecnologíaDetalle
UISolidJS 1.9 + Vite 6Signals; lucide-react icons
DesktopTauri 2 + Tokio + UUIDCommands, setup con manage(), opener plugin
FilesystemGo 1.22+ (os/filepath)Sin dependencias pesadas; JSON line-delimited
Contratotypes/fs.ts ↔ types.goMismo JSON; trailing slash en dirs
Buildpnpm + cargo + go buildTriple linux-gnu para sidecar
05

Endpoints principales

MétodoRutaQué haceAuth
invokefs_pingHealth del túnelTauri
invokefs_list_dir {path}Un nivel de carpetaTauri
invokefs_read_file {path}Contenido o placeholder binarioTauri
invokefs_tree {root,maxDepth,showHidden}Árbol recursivo limitadoTauri
invokefs_stat · fs_write_file · fs_deleteMetadata y escrituraTauri
06

Datos y conexiones

Request Rust→Go (stdin, una línea):
{"id":"uuid","method":"list_dir","params":{"path":"/src"}}
Response Go→Rust (stdout, una línea):
{"id":"uuid","result":{"type":"dir","path":"/src/","name":"src",...},"error":null}
  • Sin sockets ni HTTP: el sidecar es hijo del proceso Tauri y muere con él (SIGINT/SIGTERM).
  • Subdirs inaccesibles se saltean sin tumbar el tree completo.
09

Despliegue

Dónde: Desktop Linux/Win/Mac (Tauri bundle) + modo web mock en Vite

  • go vet ./... && go build -o src-tauri/binaries/killer-go ./go
  • cp a killer-go-x86_64-unknown-linux-gnu para el bundler
  • pnpm tauri dev (real) vs pnpm dev (mock web en :1420)
10

Metodología y decisiones

  • Contrato primero: tipos TS y Go se escriben a la par y se prueban con echo JSON por pipe antes de tocar UI.
  • Fallback como feature: la app siempre arranca (web o sin Go) y degrada a mock documentado.
  • Docs vivas: README + ARCHITECTURE.md + go/README.md con comandos copiables.
11

Retos y soluciones

Orden de respuestas por stdioMutex call_lock en Rust; Go procesa secuencial.
Binarios gigantesLimitReader 10 MB + detección NUL/UTF-8 → placeholder "[binary N bytes]".
Sidecar no encontradoBúsqueda en 4 rutas + env KILLER_GO_BIN + build.rs que lo compila solo.
12

Qué aprendí

  • IPC por stdio entre Rust y Go.
  • Empaquetado Tauri con binarios externos.
  • Diseño tolerante a fallos con mocks.
13

Ejecutar en local

cd killer && pnpm install && pnpm dev (mock web → :1420)
Con Go real: cd killer/go && go build -o ../src-tauri/binaries/killer-go . && cp a triple linux-gnu
cd killer && pnpm tauri dev
Probar Go solo: echo '{"id":"1","method":"ping","params":{}}' | /tmp/killer-go
14

Próximos pasos

  • Búsqueda full-text y watcher de cambios.
  • Permisos y operaciones batch.
  • Firmado y auto-update Tauri.
↗

Seguir explorando