Skip to content
KevinBAG2001Public

About

Cliente Git gráfico, local y autoalojable para visualizar el DAG, preparar commits y ejecutar flujos Git con seguridad desde el navegador.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Abyssan

Abyssan

El cliente Git que te ayuda a entender qué va a pasar antes de ejecutar — grafo, staging y red de seguridad, en el navegador, en tu máquina, sin suscripción.

Abyssan — cliente gráfico de Git, gratuito y auto-hospedable

Abyssan es un cliente gráfico auto-hospedable. Un backend Node opera los repositorios locales;
una SPA React muestra el DAG, prepara el commit y —en el horizonte Identidad— enseña el efecto de un merge antes de ejecutarlo.

Inicio rápido  ·  Arquitectura  ·  Capacidades  ·  Documentación  ·  Licencia


Por qué existe

Git no se paga por “hacer git”. Los clientes gráficos maduros ya cubren el ratón. Abyssan se juega otra tesis: Git visual + seguridad + comprensión.

Pilar Problema Promesa de Abyssan
Ver historia El log lineal no explica merges, HEAD ni el remoto de un vistazo. Un DAG con lanes, refs y contexto.
Preparar el commit git add -p es potente y frágil. Staging visual, diff inmediato, commit consciente.
Entender antes Un botón Merge no dice qué va a pasar. Preview: mini-DAG, conflictos estimados, cancelar sin costo.
No romper el repo Un reset o un merge mal leído cuesta horas. Confirmación contextual, journal de undo, auditoría.

No es un host de repositorios, un GitHub web, ni un clon de Boards / Insights / Teams. No es un producto de IA. Es un cliente Git local que enseña el efecto de una operación antes de ejecutarla.

Norte del producto. Escalera ya recorrida: local → power → forjas. El siguiente “listo” es Identidad: preview, undo serio, modo aprendizaje y grafo que explica. Después: worktrees y forja como contexto de rama. Distro y plugins más tarde.


Interfaz

Captura del grafo de Abyssan sobre el repo de demo (abyssan-demo)

Grafo DAG del repo abyssan-demo generado por pnpm demo:repo. Layout de tres columnas, tema oscuro, escritorio-first (≥ 1280 px). Si ves un placeholder con «Captura real pendiente», genera la real con los pasos de «Capturas reales» más abajo.

Preview no mutante de merge de fix/choca-con-main hacia main con conflicto detectado

Modal de confirmación con preview no mutante de merge sobre el mismo repo demo: antes de ejecutar, Abyssan muestra la rama, la dirección (fix/choca-con-main → main), los riesgos (incluido el conflicto en src/core/tenant.js) y los cambios que entrarían.

Esquema SVG original (referencia visual pre-captura)

Esquema de la interfaz de Abyssan: sidebar de ramas, grafo DAG y panel de staging

Zona Rol
Barra superior Selector de repositorio, sync (fetch / pull / push) y acciones globales.
Sidebar Ramas locales y remotas, tags, checkout y creación de referencias.
Grafo Historia como DAG: commits, padres múltiples, etiquetas HEAD / rama / tag.
Staging + diff Unstaged / staged, visor de cambios y formulario de commit.

Capacidades

Superficie verificada en el código (no inventario de intenciones). Fases 0–3 cerradas, Fase 4 Identidad en curso. Cada fila declara su estado: Hecho (presente en API y UI), Parcial (parte del flujo cableado, parte pendiente) o Pendiente (no está).

Dominio Capacidad Estado
Repositorios bajo PROJECTS_ROOT Listado, clone, init; validación con realpath Hecho
Repositorios bajo PROJECTS_ROOT Progreso async de clone/fetch/push/pull vía OperationManager + WS Hecho
Repositorios bajo PROJECTS_ROOT Multi-tab de repos Pendiente (Fase 5)
Grafo DAG Virtualizado, lanes, búsqueda por texto, HEAD con ahead/behind Hecho
Grafo DAG merge-base, comparar A…B (BranchCompareModal) Hecho
Grafo DAG Highlight de camino en modo aprendizaje (semántica cableada) Parcial
Stage / commit Archivo completo, stage-all, amend con detección de commit publicado Hecho
Stage / commit Stage por hunk y por línea Pendiente (Fase 4.x)
Diff Shiki + unified / split, copiar diff, comparación por commit o rango Hecho
Diff «Ver cambios» desde el preview Pendiente
Ramas y tags CRUD, rename, fetch, pull (merge/rebase), delete seguro, tag en commit Hecho
Merge Preview no mutante (clon temporal) con detección de conflictos Hecho
Merge Ejecutar, abort, continuar Hecho
Rebase Pull en modo rebase Parcial — rebase interactivo/visual pendiente
Cherry-pick / Revert / Reset Preview + confirmación tipada en reset hard sucio Hecho
Undo Journal persistente (JournalOperaciones), timeline en UI, recovery ref refs/abyssan/recovery/ para reset Hecho
Aprendizaje Explain Mode con plantillas (PanelExplicacion, sin IA) Hecho
Seguridad validarRutaRepositorio con realpath, token de instancia, rate limit, CORS/Origin, auditoría JSONL Hecho
Forjas OAuth GitHub/GitLab, token cifrado en disco, listar/crear PR/MR, PAT para push HTTPS en Docker Hecho
Blame — Pendiente
Worktrees — Pendiente (Fase 5)
Preview rebase / force-push — Pendiente

Operaciones Git disponibles en API hoy (verificables en GitRoutes y GitUseCases): status, log, diff, stage y unstage (archivo completo), commit, amend, checkout, branch, rename-branch, delete-branch, tag, stash, merge, cherry-pick, revert, reset, fetch, push, pull (merge/rebase), remotos (add/remove/list), conflictos (parseo 3-way), preview no mutante de merge/reset/cherry-pick/revert, forjas (OAuth + PR/MR). No hay endpoints de blame, rebase interactivo ni stage por hunk/línea.


Stack

Monorepo pnpm workspaces. Sin base de datos en v1: estado en memoria, localStorage en el cliente y archivos de configuración locales.

┌─────────────────────────────────────────────────────────────────┐
│                        apps/web  ·  :5174                       │
│         React 19  ·  TypeScript  ·  Vite 6  ·  Tailwind 4       │
│              Lucide  ·  date-fns  ·  WebSocket client           │
└────────────────────────────┬────────────────────────────────────┘
                             │  REST  /api/git/*     WS  REPO_CHANGED
┌────────────────────────────▼────────────────────────────────────┐
│                      apps/server  ·  :3001                      │
│     Node.js  ·  Express  ·  TypeScript  ·  simple-git           │
│              ws  ·  chokidar  ·  validación de rutas            │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
                    filesystem  ⊆  PROJECTS_ROOT
Capa Tecnología Notas
Presentación React 19, Vite 6, Tailwind CSS 4 Tema oscuro #0f111a / paneles #181c2d / acento #10b981
Aplicación (web) Hooks + HttpGitApi Un solo camino HTTP hacia el backend
Dominio (server) Entidades Git + casos de uso DDD ligero: sin Nest, sin GraphQL, sin DB
Infraestructura Git simple-git Prohibido child_process.exec genérico
Tiempo real ws + chokidar El socket notifica cambios; no envía contenido de archivos
Calidad Vitest, oxlint pnpm test · pnpm lint · pnpm build
Empaque Docker Compose SPA + API; volumen de proyectos configurable

Gestor de paquetes: solo pnpm. No usar npm, npx (en el runtime del proyecto) ni otros lockfiles.


Arquitectura

El backend no es un wrapper de comandos. Las mutaciones Git atraviesan un único camino:

HTTP → GitController → GitUseCases → SimpleGitAdapter

flowchart TB
  subgraph web["apps/web"]
    UI["UI: grafo, staging, diff, ramas"]
    Hook["useGitRepository"]
    API["HttpGitApi"]
    UI --> Hook --> API
  end

  subgraph server["apps/server"]
    Rutas["GitRoutes  /api/git"]
    Ctrl["GitController"]
    UC["GitUseCases"]
    Adapter["SimpleGitAdapter"]
    Watch["ChokidarWatcherAdapter"]
    Val["validarRutaRepositorio"]
    Log["InMemoryCommandLog"]
    Rutas --> Ctrl --> UC --> Adapter
    UC --> Log
    Watch -.-> Rutas
    Val -.-> Ctrl
    Val -.-> Watch
  end

  API -->|"REST JSON"| Rutas
  API -->|"WATCH_REPO"| Watch
  Adapter --> FS[("Repos ⊆ PROJECTS_ROOT")]
  Watch --> FS
Loading

Contrato de API

Envelope único. El cliente (HttpGitApi) habla el mismo contrato que el servidor.

{
  "exito": true,
  "mensaje": "Commit creado",
  "datos": {},
  "meta": {}
}

Healthcheck: GET /health → { "status": "ok", ... }.

Estructura del monorepo

Abyssan/
├── apps/
│   ├── web/                 # SPA React
│   │   └── src/
│   │       ├── application/ # hooks de orquestación
│   │       ├── domain/      # modelos
│   │       ├── infrastructure/  # HttpGitApi, WebSocket
│   │       └── components/  # UI de producto
│   └── server/              # API Express
│       └── src/
│           ├── domain/
│           ├── application/
│           ├── infrastructure/  # git · seguridad · watcher · logging
│           └── interfaces/http
├── docs/                    # PRD, plan, assets
├── docker-compose.yml
└── pnpm-workspace.yaml

Inicio rápido

Requisitos

Herramienta Versión
Node.js 22.13 LTS o superior
pnpm 11.25.0 (vía Corepack)
Git En el PATH del sistema
Docker Opcional, para Compose

package.json declara engines.node: ">=22.13.0" y engines.pnpm: ">=11.25.0" para coincidir con lo que exige el packageManager fijado. CI y las imágenes Docker usan node:22-alpine desde Fase 3.

1. Instalar

pnpm install

2. Configurar

Copia .env.example a .env en la raíz y define la raíz de repositorios. Abyssan no opera fuera de ese directorio.

PROJECTS_ROOT=C:\Users\<usuario>\proyectos
PORT=3001
BIND_HOST=127.0.0.1
NODE_ENV=development
VITE_API_URL=http://localhost:3001
VITE_WS_URL=ws://localhost:3001
Variable Rol
PROJECTS_ROOT Única raíz permitida para listar y mutar repos
PORT HTTP y WebSocket del servidor (3001)
BIND_HOST Default 127.0.0.1. Si no es loopback, hay que definir token
ABYSSAN_API_TOKEN Token de instancia (obligatorio fuera de localhost). No se embebe en Vite
VITE_API_URL Origen REST del frontend
VITE_WS_URL Origen WebSocket del frontend

En Linux o dentro de Docker: PROJECTS_ROOT=/workspace/proyectos.

3. Arrancar

Un solo comando levanta API y SPA en paralelo:

pnpm dev           # API :3001 + web :5174

Si necesitas solo uno de los dos:

pnpm dev:server    # http://localhost:3001
pnpm dev:web       # http://localhost:5174

Abre http://localhost:5174, elige un repositorio bajo PROJECTS_ROOT y trabaja sobre el grafo.

Script Qué hace
pnpm dev API + SPA en paralelo (recomendado)
pnpm dev:server Solo API + WebSocket (tsx watch)
pnpm dev:web Solo Vite HMR
pnpm build Compila server y web
pnpm typecheck tsc --noEmit en server y web
pnpm lint oxlint
pnpm test Vitest
pnpm test:seguridad Subconjunto de perímetro de seguridad
pnpm demo:repo Crea abyssan-demo bajo PROJECTS_ROOT (ver abajo)

Repo de demostración

Para evaluar Abyssan sin un repo real a mano, hay un script que genera uno bajo PROJECTS_ROOT:

pnpm demo:repo                # crea abyssan-demo (falla si ya existe)
pnpm demo:repo mi-demo        # elige otro nombre
pnpm demo:repo abyssan-demo --force   # sobreescribe el existente

El repo trae 20 commits en main, rama feature/pagos fusionada con merge-commit, rama fix/choca-con-main con un commit que choca con el final de main, dos tags anotados (v0.1.0 sobre el merge, v0.2.0 sobre HEAD) y, al terminar, un archivo staged y otro unstaged para que el panel de Staging no esté vacío. Útil para capturas, QA manual y para probar el preview de merge en un conflicto reproducible.

Capturas reales

El README muestra placeholders SVG bajo assets/capturas/ para no publicar en el repo imágenes derivadas de proyectos personales. Para generar las capturas reales usando el repo demo:

# 1. Repo de demo bajo PROJECTS_ROOT
pnpm demo:repo

# 2. API + SPA en paralelo (en otra terminal)
pnpm dev

# 3. Chromium para Playwright (primera vez; .npmrc trae ignore-scripts=true)
pnpm --filter @abyssan/web exec playwright install chromium

# 4. Capturas (headless, no muta el repo: el preview es no mutante)
pnpm --filter @abyssan/web capturas

El script apps/web/scripts/capturar-pantallas.mjs abre Chromium a 1280×800, selecciona el repo demo, captura el grafo y después abre el preview de merge de fix/choca-con-main → main. Al terminar deja dos PNG en assets/capturas/grafo.png y assets/capturas/preview-merge.png. Si quieres que el README apunte a las PNG en vez de a los SVG de placeholder, cambia la extensión en los <img> de la sección Interfaz.

Variables opcionales:

Variable Default Qué cambia
ABYSSAN_URL http://localhost:5174 URL base de la SPA
DEMO_REPO abyssan-demo Nombre del repo bajo PROJECTS_ROOT
DEMO_RAMA_ORIGEN fix/choca-con-main Rama que se fusiona en el preview
DEMO_RAMA_BASE main Rama destino del preview
DEMO_TIMEOUT_MS 15000 Timeout por paso en milisegundos

Atajos (Daily Driver)

Atajo Acción
Ctrl+Enter Commit (con el formulario enfocado)
Ctrl+Shift+A Stage all
Ctrl+Shift+P Paleta mínima (fetch / pull / push / commit / PRs)

Deshacer está en el header (hoy: última operación). El horizonte Identidad es un journal persistente + timeline, no una pila Ctrl+Z ciega. El reflog corto vive en el drawer de consola.

Docker Compose

Token de instancia (ABYSSAN_API_TOKEN)

No se obtiene de un servicio externo: lo inventas tú (una contraseña larga y aleatoria). El servidor la exige cuando no escucha solo en localhost; Docker siempre la exige porque dentro del contenedor BIND_HOST=0.0.0.0.

Define el token solo en el servidor. La SPA abre una sesión (POST /api/sesion) y no embebe el secreto:

Variable Quién la usa
ABYSSAN_API_TOKEN Servidor (valida Bearer permanente, o emite una sesión de 12 h)

Generar un secreto (ejemplo):

# Windows (PowerShell)
[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))
# Linux / macOS / Git Bash
openssl rand -base64 32

Pégalo en .env:

ABYSSAN_API_TOKEN=pega-aqui-el-secreto-generado

En Docker/LAN la UI pedirá ese valor una vez. No uses VITE_ABYSSAN_API_TOKEN: todo VITE_* termina en el bundle.

Con pnpm dev en tu máquina (BIND_HOST=127.0.0.1) no suele hacer falta el token. Con docker compose up sí.

Desde la raíz del repositorio:

docker compose down
docker compose up --build

Solo el frontend (más rápido si el API ya está bien):

docker compose up --build -d web

Cuando ya esté reconstruido y solo quieras reiniciar procesos (sin instalar nada nuevo):

docker compose restart web
docker compose restart server

O por nombre de contenedor:

docker restart abyssan-web
docker restart abyssan-server

Ver que existen:

docker compose ps
Servicio URL
Interfaz http://127.0.0.1:5174
API http://127.0.0.1:3001

El contenedor del servidor monta proyectos en PROJECTS_ROOT=/workspace/proyectos en lectura-escritura (ABYSSAN_PROJECTS_HOST, por defecto el checkout). Compose publica los puertos solo en localhost del host. Como el proceso dentro del contenedor escucha 0.0.0.0, hace falta ABYSSAN_API_TOKEN en .env (sin default). No re-publiques los puertos sin 127.0.0.1.


Seguridad

Abyssan ejecuta Git sobre el filesystem del host. El modelo de amenaza de Daily Driver es deliberadamente estrecho.

Control Comportamiento
Sandbox de rutas Todo repoPath pasa por validarRutaRepositorio. Fuera de PROJECTS_ROOT → 403.
Superficie Git Solo operaciones vía simple-git. Sin shell arbitrario.
Operaciones destructivas Confirmación en UI y confirmado: true en el API (reset hard, discard, borrar rama, abortar merge).
CORS / Origin Solo la SPA en :5174 (o CORS_ORIGINS). Mutación con Origin ajeno → 403.
WebSocket Handshake AUTH (sin token en la query). Valida WATCH_REPO y Origin. Progreso acotado al repo vigilado. No emite diffs ni secretos.
Credenciales No se versionan. SSH usa el agent del sistema.
Exposición de red Default localhost. Vite en 127.0.0.1. Si BIND_HOST no es loopback, ABYSSAN_API_TOKEN es obligatorio.

No copies .env al repositorio. No registres diffs completos en logs de producción.


Roadmap

Estimaciones en semanas-persona de trabajo enfocado, no en calendario. Fases 0–3 cerradas.

  0–3 hechas                    Fase 4 Identidad         Fase 5            Fase 6
  higiene · Daily Driver  ──►  preview · undo serio  ──► worktrees    ──► distro
  power · forjas                 explain · grafo           PR contexto      auth / Tauri
                                      ▲
                                      │
                                SIGUIENTE LISTO
                     (entender antes de ejecutar; no más botones)
Fase Entregable Estado
0 Higiene Un env, un cliente HTTP, tests verdes, Docker RW, identidad Abyssan Hecha
1 Daily Driver Clone/init, discard, 3-way, ramas, fetch, undo mínimo, grafo virtualizado Hecha
2 Power Stage por hunk/línea, command palette, tabs, blame, rebase visual Parcial — hunk/línea, blame, tabs y rebase visual siguen pendientes
3 Forjas OAuth GitHub/GitLab y cola de pull/merge requests Hecha
4 Identidad Preview, journal de undo, Explain Mode, grafo que enseña, seguridad Ahora — preview, journal, explain y seguridad en código; highlight de grafo parcial
5 Superficie Worktrees bajo PROJECTS_ROOT; PR/MR como contexto de rama Después
6 Plataforma Compose prod; usuarios/roles si LAN real; Tauri opcional; plugins Después

Fuera de este horizonte: IA, LFS, submódulos, GPG, GitKraken Cloud. Plugins solo en Fase 6 con sandbox.


Principios de ingeniería

  1. Un adaptador Git. SimpleGitAdapter → GitUseCases → GitController. Sin servicios paralelos.
  2. Una raíz. PROJECTS_ROOT es la única frontera del filesystem.
  3. pnpm exclusivo. Lockfile pnpm-lock.yaml.
  4. Español de producto. UI, mensajes y nombres de negocio en español; términos Git de industria se mantienen cuando son estándar.
  5. Confirmación antes de destruir. Hard reset, discard y force-with-lease no son un window.confirm accidental.
  6. Honestidad de estado. Daily Driver + power + forjas ya corren. El siguiente listo no es “más botones”: es entender la operación antes de ejecutarla. El preview no miente (informe Git, no una VM).

Los packages internos usan el scope @abyssan/*. El nombre comercial del producto es Abyssan.


Documentación

La documentación técnica versionada está en docs/wiki/. La política de reporte de vulnerabilidades está en SECURITY.md.

El detalle de producto y fases sigue en docs/PLAN-TRABAJO.md. No trates el roadmap como inventario de funciones ya terminadas.

Licencia

Distribuido bajo MIT. Uso, copia, modificación y redistribución libres, con atribución.

Abyssan — historia legible, operaciones comprendidas, repos intactos.

About

Cliente Git gráfico, local y autoalojable para visualizar el DAG, preparar commits y ejecutar flujos Git con seguridad desde el navegador.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages