Workers locales (CLI)
Resumen
Un worker local es una función en un archivo de su PC. La CLI de 3Min API (paquete npm @3minapi/cli) se ejecuta en ese PC, recoge las tareas que envía su IA, ejecuta la función con la entrada de cada tarea e informa del resultado. La IA y su PC nunca hablan directamente: 3Min API está en medio.
- Sin URL pública ni puertos abiertos. La CLI solo hace solicitudes salientes
- Lo que lee la función se queda en su PC, salvo lo que devuelve
- Un archivo = una función = un worker
Para un servidor en una URL pública, consulte Tareas (workers públicos).
| Término | Significado |
|---|---|
| Host | Un PC que ejecuta la CLI. Añada uno por cada PC en Panel → Tareas → Local |
| Token del host | tm_host_…. Inicia la sesión de la CLI en ese PC. Se muestra una sola vez |
| Carpeta del proyecto | ~/3minapi por defecto: 3minapi.json, workers/, data.db, .gitignore. Una por host |
data.db |
Archivo SQLite del proyecto. Aquí se guarda cada resultado; sus workers pueden guardar sus propios datos |
| Lector de resultados | Un worker local integrado que registra la CLI para que su IA pueda leer los resultados guardados en data.db |
| Tipo | kind en worker_list |
Cómo le llega una tarea | En Free | Llamadas a la API |
|---|---|---|---|---|
| Worker público | "public" |
3Min API la envía por POST a su URL | 1 | Las entregas cuentan 0 |
| Worker local | "local" |
La CLI la recoge (aviso en vivo por defecto, o sondeo) | Ilimitados | En vivo: sin llamadas en reposo. Sondeo: cada recogida cuenta 1, aunque no haya tareas |
Instalar y actualizar
Los comandos se ejecutan en una terminal de su PC: Terminal o PowerShell en Windows (menú Inicio), Terminal en macOS (Aplicaciones → Utilidades).
- Node.js 24.12 o posterior.
node -vmuestra la versión. Si no lo tiene o es más antiguo, instale la versión LTS desde nodejs.org (owinget install OpenJS.NodeJS.LTSen Windows) y abra una terminal nueva - La CLI:
npm install -g @3minapi/cli
3minapi --version
- Windows PowerShell puede negarse con "running scripts is disabled on this system". Escriba
3minapi.cmden lugar de3minapi: funciona sin cambiar nada. Si prefiere permitir los scripts en su propia cuenta,Set-ExecutionPolicy -Scope CurrentUser RemoteSignedlo hace (el ajuste se mantiene hasta que lo revierta) npx @3minapi/cli <command>la ejecuta sin instalarla- Actualice con el mismo comando:
npm install -g @3minapi/cli 3minapi doctorcomprueba Node.js, la configuración, el token, la red y el proxy, y le dice qué corregir. Detrás de un proxy, definaNODE_USE_ENV_PROXY=1
Inicio rápido
El mismo orden que la tarjeta de configuración de la pestaña Local.
npm install -g @3minapi/cli
3minapi init
3minapi worker new hello
3minapi worker run hello --input '{"message":"hi"}'
3minapi login
3minapi start
3minapi initcrea el proyecto en~/3minapi(3minapi init <folder>para elegir otra carpeta). A partir de ahí, los comandos funcionan desde cualquier carpeta3minapi worker new hellocreaworkers/hello.mjsa partir de una plantilla. Edite primero la descripción y luego el handler3minapi worker run hello --input '…'lo ejecuta una vez en su PC, sin tarea ni llamada a la API. Repita hasta que haga lo correcto- Panel → Tareas → Local →
Añadir host, copie el token y luego ejecute3minapi loginy péguelo cuando se lo pida 3minapi startregistra sus archivos de worker como workers locales y ejecuta sus tareas. Su IA ya los ve enworker_listconkind: "local"
start termina de inmediato si no hay ningún archivo de worker.
Comandos
Todos los comandos funcionan desde cualquier carpeta. --json da una salida legible por máquinas; 3minapi help <command> muestra todos los flags.
Host
| Comando | Qué hace |
|---|---|
3minapi init [folder] |
Crea el proyecto del host. Se puede volver a ejecutar sin riesgo. Sin terminal necesita --yes; --move lo traslada |
3minapi login |
Guarda el token del host (entrada oculta). --with-token lo lee de stdin para scripts |
3minapi logout |
Elimina el token guardado solo de este PC |
3minapi start |
Registra los archivos de worker y ejecuta sus tareas hasta que se detenga. --mode poll recoge a intervalos en lugar del modo en vivo por defecto. Ctrl+C lo detiene |
3minapi start --detach |
Lo mismo en segundo plano. No vuelve a arrancar tras un reinicio |
3minapi reload |
Hace que el start en marcha vuelva a leer los archivos de worker y los registre. Las tareas en curso siguen. 1 llamada |
3minapi stop |
Detiene el start de este PC, dondequiera que se haya iniciado |
3minapi status |
Si start está en marcha, los workers locales, las tareas repetidas y la cuota restante. 1 llamada |
3minapi logs [-f] |
El log propio de la CLI: recogidas, paradas, errores |
3minapi doctor |
Comprobación del entorno. No envía el token ni consume cuota |
3minapi paths |
Rutas absolutas de los archivos del proyecto y de las carpetas propias de la CLI |
Workers
| Comando | Qué hace |
|---|---|
3minapi worker new <name> [--ts] |
Crea workers/<name>.mjs (.mts con --ts). Lo registra al instante si start está en marcha (--no-reload lo omite) |
3minapi worker run <name> --input '<json>' |
Lo ejecuta una vez en local. --input-file <file> evita problemas de comillas de la shell en Windows |
3minapi worker list |
Los workers del proyecto, comprobando que cada uno se carga. Sin llamada a la API |
3minapi worker logs <name> [-f] |
El log de un worker: ctx.log, salida de consola, errores con stack trace |
3minapi worker delete <name> |
Elimina el worker local y su historial de tareas de 3Min API, y luego su archivo. No se puede deshacer |
Resultados e historial
| Comando | Qué hace |
|---|---|
3minapi worker results list |
Resultados guardados, los más recientes primero. --worker, --since, -n |
3minapi worker results show <task_id> |
Un resultado guardado completo. --run <n> para una ejecución de una tarea repetida |
3minapi worker results runs <task_id> |
Las ejecuciones de una tarea repetida |
3minapi worker results describe <task_id> |
Las rutas que tiene un resultado. --worker <name> agrupa los resultados de un worker por forma |
3minapi worker results query "<SQL>" |
SQL de solo lectura sobre los resultados guardados. Sin llamada a la API |
3minapi worker results prune --before <date> |
Elimina de data.db los resultados guardados anteriores a esa fecha |
3minapi tasks prune --before <date> |
Elimina el registro de este host de las tareas terminadas antes de esa fecha. Las recientes y las no terminadas se quedan |
3minapi dashboard |
Una página de solo lectura en su navegador: ejecuciones, resultados, workers, logs. Sin inicio de sesión ni llamada a la API |
dashboard --detachlo mantiene en segundo plano;dashboard urlvuelve a mostrar el enlace;dashboard stoplo cierradashboard --lantambién lo sirve a otros dispositivos de su red por HTTP sin cifrar. Úselo solo en una red de confianza- Los comandos destructivos y
--lanpiden confirmación. Sin terminal (o con--json) necesitan--yes
Escribir un worker
Un archivo en workers/ es un worker, con el nombre del archivo.
- Nombre: letras minúsculas, dígitos,
_y-, hasta 50 caracteres, sin empezar por_y sin ser un nombre de dispositivo de Windows (con,aux, …). Único entre todos sus workers (los públicos y los de sus otros PC) sin distinguir mayúsculas .mjs(por defecto) o.mts/.ts: TypeScript se ejecuta sin paso de compilación (sinenumninamespace)
// workers/rename_photos.mjs
export const description =
'Renames the photos in a folder by the date taken. input: { folder: string }';
export const timeoutMs = 10 * 60_000; // opcional — 60 segundos por defecto, como máximo 23 horas
export async function handler(input, ctx) {
await ctx.report('Scanning the folder'); // progreso — task_get lo muestra
if (ctx.signal.aborted) return; // cancelada, o a punto de agotar el tiempo
// … el trabajo …
return { renamed: 42 }; // → completed; este es el resultado
// throw new Error('Folder not found') // → failed; el mensaje es el error
}
| Export | Regla |
|---|---|
description |
Obligatorio. Lo que ve la IA en worker_list, hasta 500 caracteres. Indique aquí la forma de la entrada |
timeoutMs |
Opcional. 60 segundos por defecto, como máximo 23 horas |
inputSchema |
Opcional. Un pequeño subconjunto de JSON Schema (type, properties, required, enum, items), comprobado solo en su PC |
handler |
Obligatorio. async (input, ctx) => result |
ctx |
Qué es |
|---|---|
ctx.report(message) |
Mensaje de progreso, recortado a 256 caracteres. 1 llamada cada uno |
ctx.log(message) |
Escribe solo en el log del worker |
ctx.env |
Entorno del sistema + el .env del proyecto (.env tiene prioridad). Se quitan las variables que empiezan por THREEMINAPI_ |
ctx.signal |
AbortSignal que se dispara al cancelar o al agotarse el tiempo |
| Cómo termina el handler | La tarea pasa a |
|---|---|
return value |
completed. El valor debe ser JSON |
throw |
failed. El mensaje (con cause), con los tokens enmascarados y recortado a 4.000 caracteres. El stack se queda en el log local |
| Tiempo agotado | failed (timeout) |
| Cancelada | Se dispara ctx.signal; la ejecución se termina 2 segundos después. Su valor de retorno no se envía |
- Aplicar cambios: los cambios en el código de un handler y en
.envse aplican desde la siguiente tarea. Añadir o renombrar un archivo, o cambiar una descripción, requiere3minapi reload(o el siguientestart);worker newrecarga por sí solo - Quitar un archivo no elimina el worker de 3Min API: sus tareas fallan. Use
3minapi worker delete <name> - Los secretos (sus propias claves de API) van en el
.envdel proyecto, que.gitignoreya cubre. Guárdelo en UTF-8 (UTF-16 se rechaza) - La misma tarea puede llegar dos veces (at-least-once). Un worker con efectos secundarios debe tolerar una repetición
- Un resultado cuyo nivel superior tiene una clave
_3minapifalla conreserved_result_key - Su worker puede guardar sus propios datos en
data.db: ábralo connode:sqliteennew URL('../data.db', import.meta.url). Las tablas que empiezan por_3minapi_son de la CLI: solo lectura
Ejecutar desde su IA
Con start en marcha, pídaselo a su IA como siempre, sin necesidad de nombres de herramientas.
- "Renombra las fotos de D:\Photos\2026 por fecha"
- "Consulta el precio de BTC cada minuto, 10 veces"
- "Detén la consulta del precio"
La IA usa worker_list → task_create → task_get. Una tarea espera en 3Min API hasta que la CLI la recoge: una CLI en marcha en modo en vivo (por defecto) recibe un aviso y la recoge; en modo sondeo, en su siguiente comprobación. Hasta entonces task_get muestra delivery: "pending", y después "delivered".
Tareas repetidas
Solo para workers locales, task_create acepta repeat para ejecutar la misma entrada a un intervalo fijo: una tarea y un ID de tarea para todas las ejecuciones.
{
"worker": "price-feed",
"input": { "symbol": "BTC" },
"repeat": { "interval_seconds": 60, "max_runs": 10 }
}
| Campo / regla | Valor |
|---|---|
interval_seconds |
De 10 a 604.800 (7 días). Si una ejecución sigue en curso cuando toca la siguiente, esa se omite |
max_runs |
Opcional. Si lo omite, se repite hasta que se cancele: para detenerla, pide a la IA que la cancele |
| Estado | Se queda en working; repeat muestra runs, failed y last_run_at. completed tras la última ejecución, con un resumen |
| Fallos | Una ejecución fallida no la detiene. 5 ejecuciones fallidas seguidas → failed (repeat_failed) |
| Coste | Cada ejecución es 1 llamada, además de lo que la CLI gasta en recibir tareas. Cada minuto sin fin ≈ 43.200 llamadas al mes |
| Cambiarla | Cancélela y cree una nueva |
| Mientras la CLI está apagada | En pausa. Si no se informa ninguna ejecución en 24 horas más un intervalo → failed |
| Worker público | No permitido: repeatRequiresLocalWorker |
El resultado de cada ejecución se guarda en su PC como una fila propia (run_no 1, 2, …).
Leer resultados
Cada resultado se guarda en data.db en su PC. Los resultados de hasta unos 100 KB también se envían a 3Min API y llegan a la IA mediante task_get. Uno mayor no se envía: la tarea se completa con un sustituto en result._3minapi (stored_locally: true, ID de la tarea, tamaño, un resumen shape y el nombre del reader).
IA — mediante el lector de resultados del host, un worker local integrado llamado _results_ + 8 caracteres del ID del host. worker_list lo muestra como results_reader de ese host dentro de hosts, no entre los workers. Calcula en su PC y devuelve solo la respuesta. Las herramientas task_result_* de abajo le pasan cada paso y eligen el PC según el task_id o el worker indicado, así que la IA no necesita su nombre.
| Orden | Herramienta | Uso |
|---|---|---|
| 1 | task_result_describe (task_id o worker) |
Conozca primero la forma. Una ruta que falta en un resultado se lee como NULL, así que las formas mezcladas dan sumas erróneas |
| 2 | task_result_query (sql, worker) |
SQL de solo lectura sobre la vista results. Agrega y devuelve solo la respuesta |
| 3 | task_result_read (task_id, path, offset) |
Fragmentos en bruto de unos 90 KB, solo cuando se necesitan los datos en bruto |
- Cada tarea del lector cuesta al menos 4 llamadas y espera hasta que la CLI la recoge
- El lector se registra cuando
startse ejecuta con al menos un archivo de worker
Usted — 3minapi worker results list/show/describe/query o 3minapi dashboard. data.db nunca se limpia automáticamente; use worker results prune. Puede contener datos personales.
Dejar que una IA ejecute la CLI
Algunos clientes de IA pueden ejecutar comandos en su PC si se lo permite: agentes de programación como Claude Code o Codex, y algunas aplicaciones de escritorio. Otros, como ChatGPT en la web, no pueden: ejecute usted el comando y pegue lo que mostró.
| La IA puede | La IA no debe tocar |
|---|---|
Editar workers/*.mjs (descripción, handler) y 3minapi.json |
El token del host: nunca en un chat ni en una línea de comandos (3minapi login lo pide) |
Ejecutar worker new, worker run, reload, status, doctor, logs, worker results … |
Las carpetas propias de la CLI (credentials.json, control.db): consulta 3minapi paths |
Ejecutar init <folder> o init --yes después de preguntar dónde |
Las tablas que empiezan por _3minapi_ en data.db |
- Sin terminal, los comandos destructivos necesitan
--yes, así que--yeses la única confirmación. Confirme con el usuario antes deworker delete --yes: elimina el worker y su historial de tareas --jsonda una salida que una IA puede analizar. Los errores llegan como{ "error": { "kind", "message", "exitCode", "code"?, "resetAt"? } }.resetAtacompaña a una parada por cuota cuando se conoce la hora de reinicio
Hosts y tokens
| Situación | Qué hacer |
|---|---|
| Varios PC | Añada un host por PC. Un PC = un host = un proyecto. Los nombres de los workers deben ser distintos entre PC |
| Token perdido o filtrado | Rótelo en la página del host. El anterior deja de funcionar al instante, y una CLI que lo use se detiene |
| Pasar a otro PC | Rote el token → copie la carpeta del proyecto → 3minapi login con el token nuevo → 3minapi start. Los workers y el historial se conservan |
| Eliminar un host | Elimina sus workers locales y su historial de tareas. Úselo solo para empezar de cero; una CLI en marcha se detiene |
| Mover la carpeta | 3minapi stop → muévala → ejecute un comando dentro de ella, o 3minapi init <folder> --move |
La página del host muestra cómo recibe tareas la CLI (en vivo o por sondeo), cuándo se conectó o comprobó por última vez, el intervalo de comprobación (solo sondeo), la concurrencia, la versión y la plataforma: datos que informa la CLI, no un estado actual.
Límites y cuota
| Elemento | Valor |
|---|---|
| Workers locales | Ilimitados en todos los planes |
| Recepción (en vivo, por defecto) | Mantener la conexión no cuesta llamadas. 1 por conexión o reconexión más 1 recogida de puesta al día tras ella, y 1 por recogida cuando se avisa de una tarea o una cancelación. La conexión se corta por la red unas cuantas veces al día y se reconecta sola, así que aun sin trabajo usa algunas llamadas: 6 cortes al día ≈ 12 llamadas al día ≈ 360 al mes |
| Recepción (sondeo) | Cada recogida es 1 llamada, aunque no haya nada en espera. Por defecto cada 60 segundos ≈ 1.440 al día ≈ 43.200 al mes |
| Otras llamadas | 1 por confirmación de recepción, 1 por informe (ctx.report y el resultado final), 1 por ejecución repetida, 1 por reload/status |
| Ejecuciones simultáneas | concurrency, 4 por defecto (1–50). Como máximo concurrency tareas por recogida |
| Plazo | Si nadie la recoge en 24 horas desde su creación → failed (se comprueba cada hora, así que hasta unas 25 horas) |
| Historial de tareas | Al menos 60 días en planes de pago. En Free, los workers locales y sus ejecuciones se eliminan 7 días después de registrar el worker; reload o el siguiente start lo vuelve a registrar |
| Cuota agotada | La CLI se detiene sola (código de salida 5) y no se reinicia. Los informes nunca se bloquean |
| Resultado enviado a 3Min API | Unos 100 KB; los resultados mayores se quedan en su PC (se envía un sustituto) |
| Logs locales | Se conservan 30 días / 300 MB por defecto (logRetentionDays, logMaxBytes) |
Para gastar menos llamadas, mantenga el modo en vivo por defecto. Si su red necesita sondeo, suba pollIntervalMs en 3minapi.json (las tareas se recogen más tarde) y reinicie.
Mientras las concurrency ranuras están ocupadas, la CLI no recoge tareas nuevas: siguen en pending (las cancelaciones sí llegan). 3minapi start y 3minapi status muestran el rendimiento resultante.
Estado y solución de problemas
¿Está en marcha? Compruébelo con 3minapi status en ese PC. La Recepción de la CLI en la web, y la última comprobación o conexión que worker_list da a la IA, son datos del pasado, no un estado actual.
| Síntoma | Causa y solución |
|---|---|
La tarea sigue en working con delivery: "pending" (Esperando al PC en la web) |
La CLI no la ha recogido. Ejecute 3minapi start en ese PC |
3minapi start dice que no pudo abrir la conexión en vivo |
Un proxy o cortafuegos de la empresa la bloquea. 3minapi doctor lo comprueba; inicie con --mode poll (o receiveMode: "poll") para recoger a intervalos |
Not picked up within 24 hours — the 3Min API CLI on the user's PC did not fetch it. |
La CLI estuvo apagada 24 horas. Iníciela y vuelva a enviar la tarea |
No run was reported for 24 hours — the 3Min API CLI on the user's PC stopped running it. |
Una tarea repetida perdió su CLI. Iníciela y vuelva a crear la tarea |
Worker did not respond within 24 hours. |
Una tarea local que la CLI recogió pero cuyo resultado nunca llegó: el PC siguió apagado tras un fallo. No se vuelve a ejecutar |
Falló con host_stopped |
Detuvo la CLI (Ctrl+C o stop) mientras se ejecutaba. Una tarea repetida solo pierde esa ejecución |
Falló con host_restarted |
El PC o la CLI se cayó a mitad de la tarea. Puede que se haya ejecutado o no, y no se vuelve a ejecutar |
| La IA envía la entrada con una forma antigua | Cambió una descripción sin 3minapi reload |
Falta un worker en worker_list |
Archivo nuevo sin reload, un error de carga (3minapi worker list) o la eliminación a los 7 días en Free (reload) |
La CLI rechaza un nombre con worker_name_taken |
Otro worker (público, o en otro PC) tiene ese nombre. Renombre el archivo |
| La CLI terminó con el código 4 o 5 | 4: token no válido o sin plan; vuelva a hacer login. 5: cuota mensual agotada |
Códigos de salida
| Código | Significado |
|---|---|
| 0 | OK |
| 1 | Fallo |
| 2 | Error de uso (incluido un --yes que falta) |
| 3 | Error de entorno o de configuración |
| 4 | Detenida: token no válido, o la cuenta no tiene plan (Free cuenta como plan) |
| 5 | Detenida: cuota mensual agotada |
| 130 | Interrumpida (Ctrl+C) |
Tras 4 o 5 nada se reinicia por sí solo.
error.data.reason de una tarea local fallida
| Motivo | Significado |
|---|---|
handler_error |
El handler lanzó un error |
timeout |
Superó timeoutMs |
invalid_input |
No cumplía inputSchema; no se ejecutó |
invalid_worker |
El archivo existe pero no se puede usar: sin handler, un nombre duplicado o un error de importación |
worker_not_found |
No existe ese archivo en ese PC |
unsupported_syntax |
TypeScript que la CLI no puede ejecutar sin compilación (p. ej. enum) |
result_too_large |
Supera unos 100 KB y no se pudo guardar en el PC |
reserved_result_key |
El resultado tiene una clave _3minapi en el nivel superior |
host_stopped |
La CLI se detuvo a mitad de la ejecución |
host_restarted |
El PC o la CLI se cayó a mitad de la ejecución; se informa en el siguiente start |
repeat_failed |
Una tarea repetida falló 5 ejecuciones seguidas |
Resumen del protocolo
Cómo trabajan juntas la CLI y 3Min API, como referencia.
Entrega
- Pull: en modo en vivo la CLI mantiene una conexión y pide a 3Min API las tareas en espera cuando recibe un aviso (y una vez tras cada conexión); en modo sondeo las pide cada
pollIntervalMs. En ambos casos toma solo las que puede ejecutar en ese momento - Ack: confirma la recepción de inmediato (
deliverypasa a"delivered"). Sin confirmación en 60 segundos, la tarea se vuelve a enviar, hasta 6 veces, y luegofailed - At-least-once: la misma tarea puede llegar dos veces
- Cancelación: se avisa en modo en vivo, o se comunica en la siguiente recogida en modo sondeo →
ctx.signal. La tarea se queda encancelled - Informes: el progreso y el resultado final se envían con el token del host. Un informe que falla por la red se reintenta durante hasta 24 horas
Tamaños
| Elemento | Límite |
|---|---|
input |
100 KB |
| Resultado enviado | Unos 100 KB (100 KiB menos 1 KiB de envoltorio) |
ctx.report |
256 caracteres |
| Mensaje de error | 4.000 caracteres |
| Descripción del worker | 500 caracteres |
| Nombre del worker | 50 caracteres |
3minapi.json (prioridad: flag > variable de entorno > archivo del proyecto > valor por defecto)
| Clave | Por defecto | Rango | Variable de entorno |
|---|---|---|---|
workersDir |
workers |
Dentro del proyecto | — |
receiveMode |
live |
live o poll |
THREEMINAPI_RECEIVE_MODE |
pollIntervalMs |
60000 | 5000–3600000 (solo en modo sondeo) | THREEMINAPI_POLL_INTERVAL_MS |
concurrency |
4 | 1–50 | THREEMINAPI_CONCURRENCY |
localServerPort |
3180 | 1024–65535 | THREEMINAPI_LOCAL_SERVER_PORT |
logRetentionDays |
30 | 1–365 | THREEMINAPI_LOG_RETENTION_DAYS |
logMaxBytes |
300 MB | 10 MB–1 GB | THREEMINAPI_LOG_MAX_BYTES |
Cambiar receiveMode, pollIntervalMs o concurrency requiere reiniciar. Las claves desconocidas solo generan un aviso.
Carpetas — 3minapi paths las muestra.
| SO | Token y configuración | BD de control y logs |
|---|---|---|
| macOS | ~/Library/Application Support/3minapi |
~/Library/Application Support/3minapi, ~/Library/Logs/3minapi |
| Windows | %APPDATA%\3minapi |
%LOCALAPPDATA%\3minapi |
| Linux | $XDG_CONFIG_HOME/3minapi (~/.config) |
$XDG_STATE_HOME/3minapi (~/.local/state) |
El token vive en estas carpetas, no en el proyecto, así que copiar el proyecto no copia el token.
Privacidad
- El
resulty elerrorde un worker llegan a la conversación con la IA tal cual. Devuelva solo lo necesario data.dbguarda cada resultado en su PC, incluidos los datos personales que contenga, hasta que lo limpie