# Skill global: cargar contexto de Docmost al iniciar conversación ## Contexto El usuario quiere que, al iniciar cualquier conversación de Claude Code, se cargue automáticamente el contexto del proyecto actual desde Docmost (MCP `mcp__docmost__*`): listar los spaces, identificar cuál corresponde al proyecto en el que se está trabajando, y leer el contenido completo de todas sus páginas. Investigación realizada (en modo solo-lectura): - No existe ningún CLAUDE.md global ni hook `SessionStart` hoy en `~/.claude/settings.json` (solo hay un hook `Notification` para email vía Gmail). - Las **skills se activan por coincidencia de descripción**, no automáticamente al iniciar sesión. Para que algo corra *siempre* al inicio, el único mecanismo real es un **hook `SessionStart`**, cuyo `stdout` se inyecta como contexto adicional (esto es lo que documenta `hooks-guide.md` de Claude Code, ej. "Re-inject context after compaction"). El hook (bash) no puede llamar herramientas MCP directamente — eso solo lo puede hacer el modelo. Por eso el diseño es: **hook (bash) → inyecta instrucción → skill (markdown) → modelo ejecuta las llamadas MCP reales**. - Ya existe en `background-orchestrator/SKILL.md` una lógica de detección de proyecto reutilizable (`package.json` → `pyproject.toml` → basename del repo git), que se reutiliza aquí tal cual. - Verifiqué en vivo el MCP de Docmost: `list_spaces` devuelve `{id, name, slug, description, ...}`; `list_pages({spaceId})` devuelve el árbol de páginas (`id, title, parentPageId`) sin contenido; `get_page({pageId})` sí devuelve el contenido completo (`content`, markdown). Los nombres de space no siempre calzan literal con el nombre del repo (ej. space "Create React SSR App" vs. un repo en kebab-case), así que el match debe ser normalizado (minúsculas, sin espacios/guiones), no exacto. Algunos spaces ya tienen 30+ páginas con contenido extenso. Decisiones confirmadas con el usuario: 1. **Leer todo siempre** — al detectar el space, leer el contenido completo de todas sus páginas (sin recortar ni resumir antes de cargar). 2. **Si no hay match** — preguntar al usuario (mostrar los spaces disponibles y dejar que elija uno o indique que no corresponde ninguno). 3. **Alcance** — el hook solo actúa si el cwd está dentro de un repo git; fuera de un repo no intenta nada. ## Diseño ### 1. Script del hook — `~/.claude/hooks/docmost-session-start.sh` (nuevo, `chmod +x`) Bash puro, sin llamadas MCP (no puede hacerlas). Solo detecta el proyecto y, si aplica, imprime a stdout una instrucción para que el modelo invoque la skill. Si no está en un repo git, no imprime nada (`exit 0` silencioso → no se inyecta contexto ni se gasta turno en esto). ```bash #!/bin/bash # Solo actuar dentro de un repo git (decisión confirmada con el usuario) git rev-parse --show-toplevel >/dev/null 2>&1 || exit 0 PROJECT_NAME=$(jq -r '.name // empty' package.json 2>/dev/null) [ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(grep -oP '^\s*name\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null | head -1) [ -z "$PROJECT_NAME" ] && PROJECT_NAME=$(basename "$(git rev-parse --show-toplevel)") cat <- Carga el contexto del proyecto actual desde Docmost (MCP) al inicio de una conversación: lista los spaces, identifica cuál corresponde al proyecto del directorio actual, y lee el contenido completo de todas sus páginas. Se activa automáticamente vía el hook SessionStart (ver ~/.claude/hooks/docmost-session-start.sh) — no requiere que el usuario la invoque a mano, aunque también responde a "carga el contexto de Docmost", "lee el proyecto en Docmost", "/docmost-context". effort: medium argument-hint: "[nombre del proyecto, si ya se conoce]" --- ``` Cuerpo (workflow): 1. **Determinar el nombre del proyecto**: usar el argumento recibido si viene; si no, repetir la misma detección de `background-orchestrator` (`package.json` → `pyproject.toml` → basename del repo git). 2. **Listar spaces**: `mcp__docmost__list_spaces`. 3. **Buscar coincidencia** comparando el nombre del proyecto contra `name` y `slug` de cada space, normalizando (minúsculas, sin espacios/guiones/guiones bajos) — match exacto normalizado, no substring débil. - **Una sola coincidencia** → usarla directamente, sin confirmar con el usuario. - **Cero coincidencias** → usar `AskUserQuestion` mostrando la lista de spaces disponibles, dejando elegir uno existente o responder que ninguno corresponde (en ese caso, no cargar nada y continuar la conversación normalmente). - **Varias coincidencias ambiguas** → preguntar igual, mostrando solo los candidatos ambiguos. 4. **Leer el space completo**: `mcp__docmost__list_pages({spaceId})` para obtener todas las páginas, y luego `mcp__docmost__get_page({pageId})` para **cada una** (contenido completo, sin omitir ninguna). 5. **No repetir el dump al usuario**: una vez cargado el contenido al contexto, responder con un mensaje breve (1-2 líneas) indicando qué space y cuántas páginas se cargaron — no transcribir el contenido de las páginas en el chat. 6. Ejecutar esto **una sola vez** por conversación (al primer turno, disparado por el hook); no repetir en turnos siguientes salvo pedido explícito del usuario. ## Verificación 1. `chmod +x ~/.claude/hooks/docmost-session-start.sh` y ejecutarlo manualmente dentro de un repo git y fuera de uno, confirmando que imprime la instrucción solo en el primer caso. 2. Iniciar una conversación nueva (`startup`) dentro de un repo con space conocido (ej. `Ro-ut`) y confirmar que el modelo invoca la skill sin que el usuario lo pida, y que reporta el space/páginas cargadas en 1-2 líneas. 3. Probar dentro de un repo **sin** space coincidente y confirmar que se dispara `AskUserQuestion` con la lista de spaces. 4. Si en la prueba real el `stdout` plano del hook no llega como contexto, usar como fallback el formato JSON documentado: `{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": "..."}}`. 5. Confirmar que `/clear` también dispara la carga, y que `compact` (compactación automática) **no** la repite.