| name | noteflow-cli |
| description | Referencia completa del CLI de NoteFlow. Úsala cuando necesites interactuar con las notas del usuario desde la terminal — crear, leer, editar, organizar notas en grupos y carpetas, sincronizar con GitHub o NoteFlow Cloud, o integrar NoteFlow en scripts y flujos automatizados. |
| version | 1.10.0 |
NoteFlow CLI — Referencia completa
NoteFlow CLI es un script Node.js standalone (cli/noteflow.js) sin dependencias externas. Escribe/lee directamente en el directorio de notas de NoteFlow, compartiendo los mismos archivos que la app de escritorio.
Instalación
Linux/RPi headless
curl -fsSL https://raw.githubusercontent.com/yagoid/noteflow/main/cli/install-cli.sh | sudo bash
Linux desktop / Windows
Se instala automáticamente con el .deb o .exe de NoteFlow. No requiere pasos adicionales.
Requisito
Node.js ≥ 18. Sin dependencias npm.
Directorio de notas
| Plataforma | Ruta |
|---|
| Linux | ~/.local/share/noteflow-notes/ |
| Windows / macOS | ~/noteflow-notes/ |
Formato de nota (v2 — carpeta por nota)
Cada nota es un directorio <slug>-<id>/ con un note.md (solo frontmatter:
metadatos + índice de secciones) y un .md por sección (markdown puro):
proyecto-alpha-abc12345/
note.md ← ancla de metadatos
sec001.md ← cuerpo de la sección "Note"
sec002.md ← cuerpo de la sección "Tasks"
note.md:
---
id: "abc12345"
title: "31-03-2026"
tags: ["urgent", "backend"]
created: "2026-03-31T10:00:00.000Z"
updated: "2026-03-31T10:05:00.000Z"
formatVersion: 2
sections:
- id: "sec001"
name: "Note"
file: "sec001.md"
isRawMode: true
- id: "sec002"
name: "Tasks"
file: "sec002.md"
isRawMode: true
---
- El contenido de cada sección vive en su archivo
<sectionId>.md (sin frontmatter).
updated: de note.md es el timestamp canónico de sincronización de toda la nota.
isRawMode: true = modo markdown/raw. false = modo rich text (TipTap HTML).
- Notas con
encryption: en note.md están cifradas (la carpeta solo contiene
note.md) — el CLI las ignora.
- El marcador
.noteflow-format (contenido 2) en la raíz indica el formato v2.
- La variable de entorno
NOTEFLOW_NOTES_DIR permite apuntar a otro directorio
(scripting / testing).
Comandos
add — Añadir texto a una nota
noteflow add <texto> [opciones]
Añade texto a la nota diaria de hoy (título DD-MM-YYYY). Si no existe, la crea.
| Opción | Descripción |
|---|
--title <título> | Escribir en una nota con ese título en lugar de la del día |
--section <nombre> | Sección/pestaña destino. La crea si no existe. Default: Note |
--tag <tag> | Añade este tag a la nota (si no lo tiene ya) |
--group <nombre> | Asigna la nota a un grupo |
--folder <nombre> | Coloca la nota en una carpeta de ese grupo (requiere --group) |
--raw | Fuerza modo raw/markdown en la sección (default) |
--rich | La sección nueva se crea en modo rich text |
Comportamiento de append: el texto se añade al final del contenido existente de la sección, separado por \n.
noteflow add "Fix: CORS en /api/notes"
noteflow add "Revisar logs del servidor" --section "Tasks" --tag urgent
noteflow add "Reunión con cliente" --title "Proyecto Alpha" --section "Meetings"
noteflow add "nueva feature" --group backend
new — Crear nota vacía
noteflow new <título> [opciones]
| Opción | Descripción |
|---|
--section <nombre> | Nombre de la primera sección. Default: Note |
--group <nombre> | Asignar a un grupo |
--folder <nombre> | Colocar en una carpeta de ese grupo (requiere --group) |
--json | Devuelve { id, title, dirname } en JSON |
noteflow new "Proyecto Alpha"
noteflow new "Sprint 14" --group backend --section "Planning"
noteflow new "Mi nota" --json
list — Listar notas
noteflow list [opciones]
Muestra notas ordenadas por updated desc. Por defecto excluye archivadas.
| Opción | Descripción |
|---|
--tag <tag> | Filtrar por tag |
--group <nombre> | Filtrar por grupo |
--folder <nombre> | Filtrar por carpeta (desambigua con --group si el nombre se repite) |
--archived | Incluir notas archivadas |
--json | Array JSON con metadata completa de cada nota |
Cada elemento del JSON incluye: id, title, tags, group, folder, created, updated, archived, favorited, sections (array de nombres), dirname.
noteflow list
noteflow list --group backend
noteflow list --tag urgent --json
noteflow list --archived
get — Ver contenido de una nota
noteflow get <título> [opciones]
El título puede ser parcial — si hay varios matches, muestra la lista y pide más precisión.
| Opción | Descripción |
|---|
--section <nombre> | Mostrar solo esta sección |
--json | JSON completo con todas las secciones y su contenido |
El JSON incluye: id, title, tags, group, folder, created, updated, archived, favorited, sections[] (con id, name, content, isRawMode), dirname.
noteflow get "Proyecto Alpha"
noteflow get "Proyecto Alpha" --section Tasks
noteflow get "31-03" --json
read — Leer contenido RAW (para pipes / agentes)
noteflow read <título> [sección]
Imprime el contenido tal cual en stdout, sin indentar ni decorar — a
diferencia de get, es apto para pipe y para que un agente lo consuma directo.
Es la forma recomendada de leer una sección concreta.
| Forma | Resultado |
|---|
noteflow read "Proyecto Alpha" | Nota entera como markdown limpio (# título, ## sección + cuerpo) |
noteflow read "Proyecto Alpha" "Tasks" | Solo el cuerpo de esa sección (verbatim) |
noteflow read "Proyecto Alpha" --section Tasks | Igual, forma con flag (útil con títulos multi-palabra) |
noteflow read "Proyecto Alpha" --json | JSON con todas las secciones (o solo una si se indica) |
- El título puede ser parcial. Si hay varios matches, error pidiendo precisión.
- Nombres de sección duplicados: apunta a uno con un sufijo 1-based, p. ej.
"Tasks#2". Si hay ambigüedad sin sufijo, el error te dice exactamente qué escribir.
noteflow read "Proyecto Alpha" Tasks
noteflow read "Proyecto Alpha" "Tasks#2"
noteflow read "Proyecto Alpha" --json | jq '.sections[].name'
set — Sobrescribir (o crear) una sección
noteflow set <título> <sección> [fuente de contenido] [--rich]
Reemplaza el contenido de una sección (la crea si no existe). Es el complemento
de add, que solo añade al final. Es la forma recomendada de editar una sección.
| Fuente (gana la primera presente) | Descripción |
|---|
--text "<contenido>" | Texto inline |
--file <ruta> | Lee el contenido de un archivo |
--stdin | Lee de stdin (también se usa automáticamente al recibir un pipe) |
--rich | Si crea la sección, la crea en modo rich text (default: raw) |
- Si la sección no existe, se crea (mensaje
Created section "X").
- Nombres duplicados: usa el sufijo
#n ("Tasks#2"). Ante ambigüedad sin sufijo,
set falla en vez de adivinar.
noteflow set "Proyecto Alpha" Tasks --text "- [ ] deploy"
cat todo.md | noteflow set "Proyecto Alpha" Tasks --stdin
noteflow set "Proyecto Alpha" Notas --file ./notas.txt
⚠ Windows / PowerShell — contenido multilínea o complejo: para texto de
una sola línea --text va bien. Para varias líneas o caracteres
conflictivos, usa --file <ruta> (la vía más fiable): al pasar un --text
con saltos de línea, PowerShell puede truncarlo a la primera línea sin avisar.
--stdin (pipe/here-string) también funciona; el CLI ya limpia el BOM que
PowerShell añade. Regla práctica para agentes: contenido no trivial → --file.
Editar una parte concreta de una sección grande: el CLI edita a nivel de
sección (no hay find-replace). Con set el patrón es leer → modificar → sobrescribir:
noteflow read "Proyecto Alpha" Arquitectura > sec.md
noteflow set "Proyecto Alpha" Arquitectura --file sec.md
Si tienes herramientas de edición propias (un agente con edit/patch), evita el
round-trip: noteflow path + touch te dejan editar el .md de la sección
directamente en disco (ver abajo).
path — Ruta absoluta del .md de una sección (o del dir de la nota)
noteflow path <título> [sección]
Imprime rutas absolutas en stdout, verbatim y sin decorar (igual que read).
Sirve para editar el .md de una sección directamente con tus propias
herramientas en vez de hacer round-trips read → set --file. Después de editar,
ejecuta noteflow touch <título> (bumpea updated: y sincroniza).
| Forma | Resultado |
|---|
noteflow path "Proyecto Alpha" | Ruta absoluta del directorio de la nota |
noteflow path "Proyecto Alpha" Tasks | Ruta absoluta del .md de esa sección |
noteflow path "Proyecto Alpha" --section Tasks | Igual, forma con flag (útil con títulos multi-palabra) |
noteflow path "Proyecto Alpha" --json | { id, title, dir, noteFile, sections: [{ id, name, file, isRawMode }] } |
noteflow path "Proyecto Alpha" Tasks --json | { id, title, dir, section, file, isRawMode } |
- En
--json, file es siempre la ruta absoluta del .md.
- Resolución idéntica a
read: título parcial, sufijo #n para nombres de sección
duplicados, error pidiendo precisión si hay ambigüedad. Notas cifradas se ignoran.
noteflow path "Proyecto Alpha" Tasks
noteflow path "Proyecto Alpha" --json | jq -r '.sections[] | "\(.name) → \(.file)"'
touch — Bumpear updated: y sincronizar tras editar a mano
noteflow touch <título>
Relee la nota desde disco y la reescribe: bumpea el updated: de note.md (el
timestamp canónico de sync de la nota) y empuja note.md + todos los .md de
sección al backend de sync activo (Cloud si hay sesión, si no GitHub). Es el
paso obligatorio después de editar un .md con noteflow path: sin él, el
cambio queda solo en local y el sync no se entera.
- Sin sync configurado no falla: bumpea
updated: y no imprime línea de sync.
- Como cualquier comando que escribe, reescribe la carpeta de la nota: los
.md
que no sean note.md ni una sección listada en el índice se eliminan. No
dejes ficheros sueltos dentro de la carpeta de una nota.
- No crea ni renombra secciones: para eso usa
section add / section rename
(editar note.md a mano no es una vía soportada).
SEC=$(noteflow path "Proyecto Alpha" Tasks)
noteflow touch "Proyecto Alpha"
sections — Ver secciones de una nota
noteflow sections <título>
Lista las secciones con nombre, número de líneas y modo (raw/rich).
noteflow sections "Proyecto Alpha"
section — Gestionar secciones (por nombre)
noteflow section list <título>
noteflow section add <título> <nombre> [--rich]
noteflow section rename <título> <viejo> <nuevo>
noteflow section delete <título> <nombre> [--yes]
Gestiona las secciones de una nota por nombre, sin necesidad de ids.
| Subcomando | Descripción |
|---|
list | Alias de noteflow sections <título> |
add | Crea una sección vacía (raw por defecto; --rich para rich text) |
rename | Renombra una sección (la carpeta/archivo no cambia — va por id) |
delete | Borra una sección (confirm salvo --yes). Rechaza borrar la última |
- Los nombres de sección no son únicos: desambigua duplicados con un sufijo
1-based, p. ej.
"Tasks#2". Entrecomilla los nombres con espacios.
noteflow section add "Proyecto Alpha" "Meeting Notes"
noteflow section rename "Proyecto Alpha" Tasks To-do
noteflow section delete "Proyecto Alpha" Scratch --yes
noteflow section delete "Proyecto Alpha" "Tasks#2"
delete / rm — Eliminar nota
noteflow delete <título> [--yes]
Pide confirmación salvo con --yes. Si hay sync activo, también la elimina del repositorio GitHub.
noteflow delete "Borrador temporal" --yes
rename — Renombrar nota
noteflow rename <título-actual> <nuevo-título>
Actualiza el campo title de note.md. El nombre de la carpeta no cambia (contiene el id).
noteflow rename "Reunión" "Reunión con cliente - Q2"
move — Mover una nota a un grupo/carpeta
noteflow move <título> --group <grupo> [--folder <carpeta>]
noteflow move <título> --ungroup
Mueve una nota entre grupos y carpetas (equivalente al drag-and-drop de la app).
| Forma | Resultado |
|---|
--group <g> | Mueve la nota a la raíz del grupo (limpia la carpeta) |
--group <g> --folder <f> | Mueve la nota a esa carpeta (la carpeta debe existir en el grupo) |
--ungroup | Saca la nota del grupo y la carpeta (queda sin agrupar) |
noteflow move "Sprint 14" --group backend --folder Planning
noteflow move "Sprint 14" --group backend
noteflow move "Sprint 14" --ungroup
favorite — Marcar/desmarcar como favorita
noteflow favorite <título>
noteflow pin <título>
Toggle: si es favorita la desmarca, si no lo es la marca (campo favorited). La app
de escritorio muestra las favoritas en la parte superior de la lista. pin es un
alias histórico del mismo comando.
archive — Archivar/desarchivar nota
noteflow archive <título>
Toggle: alterna el estado archived. Las notas archivadas no aparecen en list salvo con --archived.
Grupos
Los grupos son categorías visuales (con color) que agrupan notas en la sidebar de la app.
groups — Listar grupos
noteflow groups [--json]
group create — Crear grupo
noteflow group create <nombre> [--color <color>]
Colores disponibles: accent (default), accent-2, red, cyan, purple, text, orange, pink.
noteflow group create backend --color cyan
noteflow group create "Proyectos cliente" --color orange
group delete — Eliminar grupo
noteflow group delete <nombre> [--yes]
Las notas del grupo quedan sin grupo (no se eliminan). También se borran las
carpetas de ese grupo (las carpetas solo existen dentro de un grupo).
Carpetas
Las carpetas son un único nivel de anidación dentro de un grupo
(grupo → carpeta → nota). Viven en folders.json como
{ id, name, groupId, order }. Una nota con folder siempre tiene también
group. Los nombres de carpeta pueden repetirse entre grupos distintos.
folders — Listar carpetas
noteflow folders [--group <grupo>] [--json]
Sin --group lista todas, agrupadas por grupo. Con --group solo las de ese grupo.
folder create — Crear carpeta
noteflow folder create <nombre> --group <grupo>
--group es obligatorio (una carpeta no existe fuera de un grupo).
noteflow folder create Planning --group backend
folder rename — Renombrar carpeta
noteflow folder rename <nombre> <nuevo-nombre> [--group <grupo>]
Usa --group para desambiguar si el nombre se repite en varios grupos.
folder delete — Eliminar carpeta
noteflow folder delete <nombre> [--group <grupo>] [--yes]
Las notas de la carpeta caen a la raíz del grupo (conservan el grupo, pierden
la carpeta). No se eliminan.
noteflow folder delete Planning --group backend --yes
Asignar notas a carpetas
noteflow new "Sprint 14" --group backend --folder Planning
noteflow add "texto" --title "Sprint 14" --group backend --folder Planning
noteflow move "Sprint 14" --group backend --folder Planning
noteflow list --group backend --folder Planning
Sync con GitHub
El CLI usa Device Flow OAuth — igual que la app de escritorio, pero guarda el token por separado (sin cifrado de OS). Si el usuario ya está logueado en la app de escritorio, el CLI necesita su propio login.
login — Conectar con GitHub
noteflow login [nombre-repo]
Default repo: noteflow-notes. Muestra un código y URL para autorizar en el navegador. En headless, el usuario abre la URL desde otro dispositivo.
noteflow login
noteflow login mis-notas-privadas
logout — Desconectar
noteflow logout
push — Subir todas las notas
noteflow push
pull / update — Bajar notas del repo
noteflow pull
noteflow update
Solo sobreescribe si el updated: remoto es más reciente que el local.
migrate — Migración única al formato v2
noteflow migrate
Convierte las notas planas v1 (<slug>-<id>.md en la raíz) al formato carpeta v2
(<slug>-<id>/note.md + un .md por sección), escribe el marcador
.noteflow-format y, si hay sync con token accesible, sube el nuevo layout y
elimina los archivos planos del remoto. Idempotente. La app de escritorio ejecuta
la misma migración local automáticamente al arrancar.
self-update — Actualizar el CLI
noteflow self-update
Descarga la versión más reciente de cli/noteflow.js desde GitHub y reemplaza el script actual. Útil en RPi headless donde no hay instalador. No requiere estar conectado a GitHub sync — usa la API pública del repo.
noteflow self-update
Si ya está en la última versión: Already up to date.
Sync con NoteFlow Cloud (cuenta, cifrado)
Alternativa al sync de GitHub ligada a la cuenta NoteFlow (requiere suscripción Cloud
para subir cambios). Todo viaja cifrado en el cliente (AES-256-GCM); el CLI habla
directamente con el backend, pensado para máquinas headless (RPi, servidores, cron).
Mientras hay sesión con Cloud habilitado, Cloud tiene prioridad sobre GitHub: los
comandos push, pull, status y el sync automático tras cada mutación usan Cloud
(el sync de GitHub queda en pausa aunque siga configurado).
cloud login — Iniciar sesión
noteflow cloud login [email]
Envía un código de 6 dígitos por email y lo pide por prompt. La sesión del CLI es
independiente de la de la app de escritorio (los tokens rotan en cada uso; compartirla
los desconectaría mutuamente). Al iniciar sesión, el sync Cloud del CLI queda habilitado.
cloud logout — Cerrar sesión
noteflow cloud logout
Conserva las notas locales y el cursor de sync (volver a entrar retoma incremental).
cloud setup — Crear las claves de cifrado (modo estándar)
noteflow cloud setup
Solo para el modo estándar (managed): genera la clave y la deposita en el servidor —
nada que recordar. El modo privado (e2ee) se configura desde la app de escritorio
(muestra el recovery code de un solo uso); el CLI entonces pide la passphrase o el
recovery code en cada ejecución, o lee NOTEFLOW_CLOUD_PASSPHRASE para servidores/cron.
La clave nunca se guarda en disco en esta máquina.
cloud push / cloud pull — Sync completo manual
noteflow cloud push
noteflow cloud pull
El primer push ejecuta automáticamente un pull inicial de reconciliación
(First Cloud reconcile…) para no pisar remoto más nuevo. En el pull manda el
updated: del ancla de cada nota: el remoto más nuevo gana la carpeta entera; los
borrados remotos solo se aplican si la copia local no cambió desde el último sync.
cloud status — Estado de la cuenta y el sync
noteflow cloud status [--json]
Muestra email, modo de claves (standard (managed) / private (e2ee) / none),
habilitado, último sync y cursor. JSON:
{ notesDir, noteCount, cloud: { email, enabled, keysMode, lastSync, pullCursor } | null, githubConfigured }.
status — Estado actual
noteflow status [--json]
Muestra: número de notas, directorio, grupos, estado de GitHub y última sync.
JSON: { notesDir, noteCount, github: { owner, repo, lastSync, tokenAccessible }, groups }.
Con NoteFlow Cloud activo, status enruta a cloud status y su JSON cambia a la
forma documentada arriba — los scripts que dependan del shape de GitHub deben
comprobar la clave cloud.
Flags globales
| Flag | Aplica a | Descripción |
|---|
--json | list, get, read, path, new, groups, folders, status, cloud status | Salida JSON machine-readable |
--yes | delete, group delete, folder delete, section delete | Salta confirmación interactiva |
--archived | list | Incluye notas archivadas |
--section <nombre> | read, path, get, add, set | Apunta a una sección por nombre |
--group <nombre> | add, new, move, list, folders, folder * | Apunta a/filtra por un grupo |
--folder <nombre> | add, new, move, list | Apunta a/filtra por una carpeta (requiere grupo) |
--ungroup | move | Saca la nota del grupo y la carpeta |
--text / --file / --stdin | set | Fuente del contenido a escribir |
--rich | add, set, section add | Sección nueva en modo rich text (default: raw) |
Integración con IA / scripts
Para integrar el CLI en scripts o agentes de IA, usa --json en los comandos de lectura:
noteflow list --json
noteflow get "Proyecto Alpha" --json
noteflow new "Auto-note" --json
noteflow status --json | jq '.github.tokenAccessible'
El CLI escribe en stdout y los errores en stderr, con exit code 0 en éxito y 1 en error.
Flujo típico para un agente
Todo se direcciona por nombre (título de nota + nombre de sección). No necesitas
tocar ids nunca.
noteflow list --json
noteflow read "título" "Sección"
noteflow set "título" "Sección" --text "contenido nuevo"
echo "contenido" | noteflow set "título" "Sección" --stdin
noteflow add "más contenido" --title "título" --section "Sección"
noteflow path "título" "Sección"
noteflow touch "título"
noteflow section rename "título" "Sección" "Nuevo nombre"
noteflow push
read vs get: get es para humanos (indenta y decora); read emite el
contenido verbatim — úsalo siempre que vayas a procesar el texto.
set vs add: set reemplaza la sección; add añade al final.
Ediciones parciales de secciones grandes → path + touch, no read + set.
El CLI no tiene find-replace, así que con read/set toda edición parcial obliga a
sacar la sección entera, modificarla y volver a escribirla completa. Si tu agente ya
tiene herramientas de edición de ficheros (edit/patch), es mejor pedirle a path la
ruta del .md de la sección, editarlo in situ y cerrar con touch:
SEC=$(noteflow path "título" "Sección")
noteflow touch "título"
touch es obligatorio: es quien bumpea updated: en note.md y hace el push
(editar el .md a pelo no sincroniza nada por sí solo).
- Usa
read/set cuando reescribas la sección entera, o cuando no tengas acceso al
sistema de ficheros (p. ej. la nota vive en otra máquina).
Notas importantes
- El CLI no puede descifrar tokens guardados por la app de escritorio con
safeStorage de Electron. Requiere su propio login (GitHub) y su propio cloud login (NoteFlow Cloud) — la sesión Cloud además no debe compartirse con la app: los refresh tokens rotan en cada uso y compartirla desconectaría a ambos.
- En modo e2ee la passphrase se pide en cada ejecución (o
NOTEFLOW_CLOUD_PASSPHRASE); ni la passphrase ni la clave de cifrado se guardan nunca en disco.
- Notas encriptadas (
encryption: en note.md) se ignoran en todos los comandos de lectura.
NOTEFLOW_NOTES_DIR (variable de entorno) redirige el directorio de notas — útil para scripts y tests.
- ⚠ App de escritorio abierta ⇒ riesgo de perder cambios de grupos/carpetas.
La app mantiene
groups.json/folders.json en memoria y los reescribe en sus
propios ciclos (guardado / auto-sync cada 5 min), pisando los grupos y carpetas
creados desde el CLI mientras la app corre (los cambios a nivel de nota —
contenido, secciones, favorito, archivo — sí sobreviven, viven en carpetas por-nota).
El CLI ahora avisa por stderr si detecta NoteFlow en ejecución al mutar
grupos/carpetas. Para cambios fiables de estructura: cierra la app primero (o
hazlos desde la propia app). Silencia el aviso con NOTEFLOW_NO_APP_CHECK=1.
noteflow help <comando> muestra ayuda detallada de un comando concreto
(help new, help favorite, help folder, etc.).