@ketchao/nextup 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +153 -2
  2. package/dist/cli.js +6509 -0
  3. package/package.json +27 -4
package/README.md CHANGED
@@ -1,3 +1,154 @@
1
- # Temporary Holding Version
1
+ # nextup (nombre provisional)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Menú de "siguientes pasos" para agentes de código. MVP: **Claude Code** y **Codex** (mismo protocolo de hooks).
4
+
5
+ > El nombre es un placeholder. Ojo: la captura de referencia es de un producto llamado "Then", así que conviene no usar ese nombre.
6
+
7
+ Al terminar cada turno sustancial, muestra hasta 4 opciones contextuales (con indicador de consumo). El usuario responde escribiendo el número en la caja normal de Claude Code.
8
+
9
+ ```
10
+ ◆ ¿Cómo seguimos? Escribe un número · +1 2 = varias
11
+ consumo ▾
12
+ 1 Hacer commit ★ sugerida ■□□ bajo
13
+ 2 Revisar mis cambios ■■□ medio
14
+ 3 Escribir pruebas ■■■ alto
15
+ 4 Dejarlo así □□□ nada
16
+ 5 Otra cosa (libre)
17
+ ```
18
+
19
+ ## Probarlo (5 minutos)
20
+
21
+ ```bash
22
+ npm install
23
+ npm test # 76 pruebas
24
+ npm run preview # ver el menú sin Claude (itera el diseño aquí)
25
+ npm run preview -- --scenario failed --width 60
26
+ npm run build
27
+
28
+ # en un repo de prueba, desde el paquete publicado:
29
+ npm install -g @ketchao/nextup
30
+ nextup init --agent codex
31
+ claude # pide un cambio pequeño y mira qué pasa al terminar
32
+ ```
33
+
34
+ `init --user` instala los hooks globalmente; `init --remove` los quita. Hace un backup `settings.json.nextup.bak` la primera vez.
35
+
36
+ Probar un hook sin Claude:
37
+
38
+ ```bash
39
+ cat fixtures/stop.json | NEXTUP_ALWAYS=1 node dist/cli.js hook stop
40
+ cat fixtures/prompt-submit.json | node dist/cli.js hook prompt-submit
41
+ ```
42
+
43
+ ## Probar con Codex (experimental)
44
+
45
+ Los comandos `hook stop` y `hook prompt-submit` leen y escriben el mismo formato JSON que usa Codex, así que no hay adaptador nuevo: solo cambia dónde se registran.
46
+
47
+ ```bash
48
+ node dist/cli.js init --agent codex # escribe .codex/hooks.json (o --user para ~/.codex/hooks.json)
49
+ codex # luego escribe /hooks y aprueba (trust) los 2 hooks de nextup
50
+ ```
51
+
52
+ Notas:
53
+ - Codex ignora los hooks nuevos o modificados hasta que los revisas con `/hooks`.
54
+ - En Windows nativo (Codex CLI 0.166.0, cmd) los hooks **sí se ejecutan**. El `systemMessage` aparece como "Hook · ..." con los colores ANSI y la alineación intactos.
55
+ - El lector de transcript (`transcript.ts`) es *best effort* y entiende los formatos de Claude Code y de Codex. Solo lee lo ocurrido en el turno actual (el hook `UserPromptSubmit` anota dónde empieza). Si algo no cuadra, activa `debug` y revisa `debug.jsonl`: la entrada `stop-signals` muestra los comandos y códigos de salida detectados, y un resumen de las líneas leídas.
56
+ - Codex ejecuta los hooks desde un servidor en segundo plano que **no hereda tus variables de entorno**: usa `~/.nextup/config.json` (ver abajo) o abre `codex --no-daemon`.
57
+
58
+ ## Configuración
59
+
60
+ Variables de entorno **o** el archivo `~/.nextup/config.json` (las variables mandan sobre el archivo):
61
+
62
+ ```json
63
+ {
64
+ "language": "es",
65
+ "suggestions": 4,
66
+ "showCustomOption": true,
67
+ "showTokenEstimation": true,
68
+ "autoSuggest": true,
69
+ "backgroundCheck": true,
70
+ "consumption": "measured",
71
+ "providers": { "claude": true, "codex": true, "opencode": true },
72
+ "debug": false,
73
+ "theme": "default"
74
+ }
75
+ ```
76
+
77
+ `suggestions` es el tope de filas, contando "Dejarlo así" (1–4). `showCustomOption` es la fila "Otra cosa". `showTokenEstimation` es la columna de consumo. `autoSuggest: false` deja de mostrar menús nuevos; un menú que ya está en pantalla sigue aceptando el número. `backgroundCheck` corre `npm test` (y `npm run lint` si existe) antes de armar el menú, con un tope de unos segundos: si 3 pruebas fallan, la fila dice «3 pruebas fallan, arreglarlas». `false` lo apaga. `consumption` es `measured` (el tiempo real: `1.5s`, o `—` si esa acción todavía no se midió) o `estimated` (bajo, medio, alto, nada). `providers` apaga un agente: Codex se reconoce por la ruta `.codex` del transcript. OpenCode todavía no tiene adaptador, así que su flag se guarda y no corta nada. `language` es el idioma cuando el prompt no alcanza para saberlo (un número, un «ok» o una mezcla). Si el prompt es una frase en inglés, el menú sale en inglés; si es en español, en español. Siguen valiendo `lang`, `mode`, `color`, `width`, `always` y `disabled`. El entorno manda sobre el archivo.
78
+
79
+ Para verlo o cambiarlo sin editar el JSON:
80
+
81
+ ```
82
+ nextup config
83
+ nextup config set autoSuggest false
84
+ nextup config set providers.codex false
85
+ nextup config set showCustomOption true
86
+ nextup config set suggestions 3
87
+ nextup config set theme blue
88
+ nextup config set language es
89
+ nextup config set consumption estimated
90
+ ```
91
+
92
+ Los interruptores aceptan `true`/`false` (también `on`/`off` y `si`/`no`). En la caja del agente, sin salir de Codex y sin tener `nextup` en el PATH:
93
+
94
+ ```
95
+ nextup theme blue
96
+ nextup config set consumption estimated
97
+ ```
98
+
99
+ El cambio se guarda y el agente no lo ejecuta. Se ve en el menú siguiente. `color` y `default` pintan cada fila según el consumo. `blue`, `green`, `amber`, `pink`, `teal` y `violet` pintan todo el menú de un color. `mono` lo deja sin color. También valen `azul`, `ambar`, `rosa` y `cian`. `nextup init` crea el archivo con todo activo si todavía no existe, y no pisa el que ya tengas.
100
+
101
+ Con `"debug": true`, cada hook guarda lo que recibió y devolvió en `~/.nextup/state/debug.jsonl` (contiene rutas y texto de tu sesión; es solo local). Aparte, cada menú deja una línea en `~/.nextup/state/choices.jsonl`: si elegiste un número, si lo dejaste así, o si escribiste otra cosa. No guarda la frase. Si una fila sale tres veces en turnos parecidos y no la eliges, baja.
102
+
103
+ ## Cómo funciona
104
+
105
+ 1. **Hook `Stop`**: lee el payload, junta señales baratas (cambios en `git status`, comandos `Bash` del turno en el transcript, mensaje final), genera el menú y lo muestra con `systemMessage`. Guarda el menú pendiente en `~/.nextup/state/<session_id>.json`.
106
+ 2. El usuario escribe el número de la fila (`2`) o varios a la vez (`+2 4`, `1 3`, `1 y 3`). El `+` es opcional.
107
+ 3. **Hook `UserPromptSubmit`**: si hay menú pendiente y la respuesta es una selección, inyecta las instrucciones como `additionalContext` (el hook no puede reescribir el prompt; Claude recibe "3" + el contexto que lo explica). "Dejarlo así" y "Otra cosa" bloquean el prompt y no gastan tokens. Cualquier otro texto descarta el menú y pasa intacto.
108
+
109
+ Decisiones de diseño (vienen de la crítica a la maqueta):
110
+ - **No sugiere lo que ya pasó**: si las pruebas ya pasaron, no ofrece correrlas otra vez.
111
+ - **No repite lo que acabas de elegir** (solo para el menú siguiente) **ni ofrece correr pruebas si el repo no tiene ninguna configurada**: en su lugar sugiere el commit.
112
+ - **0 a 4 opciones, y a veces ninguna**: no hay menú si no hubo cambios, o si el agente terminó con una pregunta.
113
+ - **La sugerida nunca es saliente**: el esquema (`SuggestionSchema`) rechaza `recommended` + `outward` (push, deploy...).
114
+ - **El menú por defecto pinta la fila**: verde, ámbar, rojo o gris según el consumo, y "Otra cosa" en azul. El número va en una pastilla más clara. `blue`, `green`, `amber`, `pink`, `teal` y `violet` pintan todo el menú de un solo color. `mono` y `color: false` lo dejan en texto plano. El `☐` no se marca: se elige con el número. En la caja del agente, sin barra: `nextup theme blue` (también `verde`, `azul`, `ambar`, `rosa`, `cian`). La barra es de Codex y rechaza `/nextup`.
115
+
116
+ ## Spike: lo que hay que verificar primero
117
+
118
+ Estas cuatro cosas **no están confirmadas**; todo el diseño depende de ellas:
119
+
120
+ | # | Pregunta | Cómo probarla | Si falla |
121
+ |---|----------|---------------|----------|
122
+ | 1 | ¿Se ve el `systemMessage` de un Stop sin bloqueo? | Correr `claude`, pedir un cambio, mirar al terminar | Usar `NEXTUP_MODE=block` |
123
+ | 2 | ¿Respeta ANSI y saltos de línea? | Comparar con `NEXTUP_COLOR=0` | Dejar color apagado por defecto |
124
+ | 3 | ¿Claude actúa bien con `"3"` + contexto inyectado? | Elegir opciones varias veces | Reforzar el texto de `additionalContext` |
125
+ | 4 | ¿El ancho detectado es correcto? | Redimensionar la terminal; probar `NEXTUP_WIDTH` | Ancho fijo o más compacto |
126
+
127
+ Además: mide la latencia real del turno (el hook arranca en ~60 ms; las reglas son locales, así que hoy no hay llamada a un modelo) y prueba también en la extensión de VS Code/Cursor, cuya interfaz puede mostrar los hooks distinto a la terminal.
128
+
129
+ ## Límites conocidos
130
+
131
+ - El menú mira solo los archivos cuyo diff cambió en este turno (baseline guardado en `UserPromptSubmit`). Si esa marca no está, cae al `git status` completo.
132
+ - El transcript JSONL no es un contrato público: `transcript.ts` es *best effort* y degrada a "sin señales".
133
+ - Detección de pruebas: usa los comandos y códigos de salida del transcript (formato real de Codex verificado con `fixtures/codex-rollout-sample.jsonl`). Si el fallo parece del entorno (EPERM, "Access is denied"...), se trata como *bloqueado*, no como "pruebas rotas": la sugerida pasa a ser revisar el diff. Sin código de salida, cae a una heurística sobre el mensaje final.
134
+ - Sin detección de ejecuciones headless (`claude -p`); si más adelante llamas a `claude -p` desde el hook, exporta `NEXTUP_INNER=1` en esa llamada para evitar recursión.
135
+ - Claude y Codex comparten el protocolo de hooks (`systemMessage` / `additionalContext`). OpenCode necesita un presentador propio (añadir al prompt).
136
+
137
+ ## Siguientes pasos
138
+
139
+ 1. Pasar el spike (tabla de arriba) y usarlo una semana propia; registrar qué opciones se eligen.
140
+ 2. `llm.ts`: 1 o 2 sugerencias específicas con un modelo pequeño (API key o `claude -p`), manteniendo las reglas deterministas como base.
141
+ 3. Consumo medido (duración real de la última corrida de pruebas) en vez de fijo por tipo de acción.
142
+ 4. Presentador de OpenCode (añadir al prompt). Claude y Codex ya comparten `src/adapters/shared/`.
143
+
144
+ ## Estructura
145
+
146
+ ```
147
+ src/core/ independiente del agente: tipos (zod), reglas, render, parser, estado
148
+ src/adapters/shared/ protocolo de hooks: payloads, transcript, contexto, Stop y UserPromptSubmit
149
+ src/adapters/claude/ instalación en .claude/settings.json
150
+ src/adapters/codex/ instalación en .codex/hooks.json (timeoutSec)
151
+ src/cli/ preview, init, config, entrada de los hooks
152
+ test/ parse, suggest, render, hooks (con repo git temporal), adaptadores
153
+ fixtures/ payloads de ejemplo
154
+ ```