Cuando hablamos de añadir IA a una aplicación, lo primero que viene a la cabeza es desplegar un modelo. Azure AI Foundry, OpenAI, un endpoint de inferencia… y empezar a hacer llamadas HTTP.

Funciona. Pero hay otro camino que a veces olvidamos.

Quienes llevamos tiempo en esto sabemos que la CLI siempre fue el sitio donde las cosas pasan de verdad. Antes de que existieran los dashboards, los portales y las interfaces gráficas, estaba el terminal. Y sigue estando.

GitHub Copilot CLI es exactamente eso: inteligencia artificial accesible desde la línea de comandos. Sin desplegar modelos, sin configurar endpoints, sin gestionar claves de API de un servicio en la nube.

Y lo interesante es que puedes integrarlo directamente en tus aplicaciones.

LA IDEA

En lugar de montar una infraestructura de IA completa, ¿por qué no usar lo que ya tienes instalado?

Si tienes GitHub CLI con la extensión Copilot, ya tienes un LLM disponible en tu máquina. Solo necesitas un proceso hijo que lo invoque.

La arquitectura es deliberadamente simple:

[Tu aplicación] → [Servidor Node.js] → [Copilot CLI] → [Respuesta IA]

Sin Azure AI Foundry. Sin claves de API rotando. Sin costes por token.

Copilot CLI como backend de IA para prototipado rápido y herramientas internas.

Obviamente, para producción a escala, querrás un servicio gestionado. Pero para herramientas internas, demos, prototipos y flujos de trabajo de equipo, este enfoque es sorprendentemente potente.

EL CASO PRÁCTICO: UN PLUGIN DE POWERPOINT

Para demostrarlo, he construido un Add-in de PowerPoint que genera presentaciones a partir de Markdown, con Copilot CLI como motor de generación de contenido.

El flujo es:

  1. El usuario escribe un prompt: «5 diapositivas sobre computación cuántica»
  2. El servidor invoca `copilot.exe` con ese prompt
  3. Copilot devuelve Markdown estructurado
  4. El plugin parsea el Markdown y genera las slides

Pero lo interesante no es el plugin en sí. Es cómo se integra Copilot CLI en el backend.

INVOCANDO COPILOT CLI DESDE NODE.JS

La pieza central es un servidor Express que actúa como proxy hacia el binario de Copilot:
const { execFile } = require("child_process");
const path = require("path");
const os = require("os");

let cachedGhToken = null;

function getGhToken() {
  return new Promise((resolve, reject) => {
    const ghPath = "C:\\Program Files\\GitHub CLI\\gh.exe";
    execFile(ghPath, ["auth", "token"], { timeout: 10000 }, (err, stdout) => {
      if (err) {
        reject(new Error("Ejecuta 'gh auth login' primero."));
        return;
      }
      resolve(stdout.trim());
    });
  });
}

function runCopilotCli(prompt) {
  return new Promise(async (resolve, reject) => {
    if (!cachedGhToken) {
      cachedGhToken = await getGhToken();
    }

    const copilotPath = path.join(
      os.homedir(),
      "AppData", "Local", "GitHub CLI", "copilot", "copilot.exe"
    );

    execFile(
      copilotPath,
      ["-p", prompt, "-s", "--no-ask-user"],
      {
        timeout: 120000,
        maxBuffer: 1024 * 1024,
        env: { ...process.env, GH_TOKEN: cachedGhToken },
      },
      (error, stdout, stderr) => {
        if (error) {
          reject(new Error(stderr || error.message));
          return;
        }
        resolve(stdout.trim());
      }
    );
  });
}

Puntos clave:

– No usamos `gh copilot`. Invocamos directamente el binario `copilot.exe` que la extensión instala en `AppData/Local/GitHub CLI/copilot/`.
– El token se obtiene de `gh auth token` y se cachea. El binario necesita `GH_TOKEN` como variable de entorno para autenticarse.
– Flags: `-p` para modo no interactivo, `-s` para salida limpia (solo la respuesta), `–no-ask-user` para que no haga preguntas de vuelta.

AGENTS Y SKILLS: DANDO PERSONALIDAD A LA IA

Tener un LLM disponible está bien. Pero la diferencia entre una respuesta genérica y una respuesta útil es el contexto.

Aquí es donde entra el concepto de Agents y Skills.

Un Agent es una personalidad predefinida con instrucciones de sistema. Un Skill es una capacidad concreta que se inyecta en el prompt.

En el servidor, se definen así:

const AGENTS = {
  "profesor-secundaria": {
    name: "🎓 Profesor de Secundaria",
    systemPrompt: `Eres un profesor de secundaria carismático y didáctico. 
Tu objetivo es que los alumnos de 12 a 16 años entiendan cualquier tema.
- Usa lenguaje sencillo y cercano
- Incluye ejemplos del día a día
- Usa analogías divertidas y memorables
- Añade datos curiosos: "¿Sabías que...?"
- Incluye preguntas retóricas para fomentar la reflexión`,
  },
  "storyteller": {
    name: "📖 Storyteller",
    systemPrompt: `Eres un narrador que convierte cualquier tema en una historia.
Usa arcos narrativos: problema, desarrollo, conclusión.
Haz que cada diapositiva sea un capítulo.`,
  },
};

const SKILLS = {
  "analogias-cotidianas": {
    name: "🔄 Analogías Cotidianas",
    instruction: `Para cada concepto, añade una analogía cotidiana.
Ejemplo: "La CPU es como el cerebro: procesa todas las decisiones".
Usa objetos que un adolescente conoce: móviles, videojuegos, redes sociales.`,
  },
  "quiz-interactivo": {
    name: "❓ Quiz Interactivo",
    instruction: `Al final, añade una slide de "Quiz Rápido" con 3-5 preguntas.
Incluye verdadero/falso, opción múltiple, completar la frase.`,
  },
  "datos-curiosos": {
    name: "🤯 Datos Curiosos",
    instruction: `Incluye al menos un dato sorprendente por diapositiva.
Formato: "🤯 ¿Sabías que...?" — datos verificables que generen "wow".`,
  },
};
Cuando el usuario hace una petición a Copilot, el servidor construye el prompt completo inyectando el agente activo y los skills seleccionados:
function buildSystemContext() {
  const agent = AGENTS[activeAgentId];
  let context = "";

  if (agent) {
    context += `=== AGENTE: ${agent.name} ===\n${agent.systemPrompt}\n\n`;
  }

  for (const skillId of activeSkillIds) {
    const skill = SKILLS[skillId];
    if (skill) {
      context += `[${skill.name}]\n${skill.instruction}\n`;
    }
  }

  return context;
}

El prompt final que llega a Copilot CLI tiene esta estructura:
=== AGENTE: 🎓 Profesor de Secundaria ===
Eres un profesor de secundaria carismático y didáctico...

[🔄 Analogías Cotidianas]
Para cada concepto, añade una analogía cotidiana...

[🤯 Datos Curiosos]
Incluye al menos un dato sorprendente por diapositiva...

=== INSTRUCCIONES DE FORMATO ===
Genera contenido en formato Markdown para una presentación.
Usa # para título, ## para diapositivas, - para puntos.

Solicitud del usuario: 5 diapositivas sobre computación cuántica

El resultado: el mismo prompt del usuario genera contenido completamente diferente según el agente y los skills activos.

Un prompt sin contexto es una pregunta al aire. Un prompt con agente y skills es una instrucción precisa.

LA INTERFAZ: SELECCIÓN EN TIEMPO REAL

En el panel lateral del Add-in (aquí volvemos a ver como el UI ya cambia con respecto a los clic-clic habituales), el usuario selecciona el agente con un dropdown y activa/desactiva skills con chips interactivos. La configuración se sincroniza con el servidor en tiempo real:

async function syncConfig() {
  const agentId = document.getElementById("agent-select").value;
  const skillIds = Array.from(
    document.querySelectorAll(".skill-chip.active")
  ).map((el) => el.dataset.skillId);

  await fetch(`${SERVER_URL}/api/config`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ agentId, skillIds }),
  });
}

Cada vez que el usuario cambia de agente o toca un skill, la siguiente petición a Copilot CLI ya lleva el nuevo contexto.

No hay página de configuración separada. No hay guardado manual. Cambias, generas, ves el resultado.

CÓMO PROBARLO

Requisitos:

  • Node.js 18+
  • GitHub CLI con la extensión Copilot: `gh extension install github/gh-copilot`
  • PowerPoint desktop (Windows)
  • Y este repositorio:
# Clonar e instalar
git clone <repositorio>
cd pptx_maker_with_gc_cli
npm install

# Levantar servidores (webpack + backend)
npm run dev

# Cargar el Add-in en PowerPoint
npx office-addin-debugging start manifest.xml

Ese último comando es clave. Abre PowerPoint directamente con el Add-in cargado. Sin buscar menús de sideloading, sin copiar manifiestos a carpetas compartidas.

Una vez abierto:

  1. Selecciona un agente (Profesor de Secundaria viene por defecto)
  2. Activa los skills que quieras
  3. Escribe un prompt: «Explica el ciclo del agua para mi clase de 2º ESO»
  4. Click en «Generar con Copilot CLI»
  5. Las slides aparecen en la vista previa
  6. Click en «Crear Presentación» para generarlas en PowerPoint

POR QUÉ ESTE ENFOQUE ES INTERESANTE

Azure AI Foundry es la opción correcta para producción. No hay discusión.

Pero no siempre estás en producción.

A veces necesitas:

  • una demo rápida que funcione sin infraestructura cloud
  • una herramienta interna para un equipo pequeño
  • un prototipo para validar una idea antes de invertir en servicios
  • enseñar a alguien cómo funciona la IA aplicada, sin que tenga que crear una cuenta en Azure
  • y saliendo a cosa más serias:
    • podrás crear una presentación con los issues asociados a tu proyecto de GitHub sin tener que conectarte a las apis.
    • listar todos los commits y llevarlos a la presentación de power point.
    • la imaginación es tu límite.

Copilot CLI cubre todos esos escenarios.

Y el patrón de Agents + Skills es reutilizable. Hoy genera presentaciones. Mañana puede generar informes, emails, documentación técnica o cualquier otro contenido que necesite contexto y personalidad.

La inteligencia no está solo en el modelo. Está en cómo lo invocas.

LO QUE SIEMPRE SUPIMOS

La línea de comandos fue el primer lugar donde automatizamos cosas. Pipes, scripts, procesos encadenados.

Ahora la línea de comandos tiene IA dentro.

Y la forma de integrarla en tus aplicaciones es exactamente la misma que siempre usamos: un `exec`, unas flags, y un resultado por stdout.

No es glamuroso. Pero funciona.

Y a veces, eso es todo lo que necesitas.