dsa-tracker
v0.6.0
Published
CLI de Tracker: tickets, horas y documentación desde la terminal, más análisis de orgs de Salesforce y control del alcance contratado. Con o sin Claude.
Maintainers
Readme
dsa-tracker
Tracker desde la terminal: tus tickets, el cronómetro, las horas y la documentación de los proyectos, sin abrir el navegador. Además analiza una org de Salesforce y avisa cuando algo queda fuera del alcance contratado. Instala un skill para que Claude Code entienda Tracker en cualquier carpeta de tu máquina.
App: https://tracker-dsa-sf.vercel.app
Instalación
npm i -g dsa-tracker
tracker loginlogin pide email y contraseña, guarda la sesión en ~/.tracker/session.json y deja el skill de
Claude Code en ~/.claude/skills/tracker/. Con eso Claude entiende "mostrame mis tickets" o
"pasá APP-12 a revisión" desde cualquier repo, no solo desde el de Tracker.
Requiere Node 20 o más. Las cuentas las crea un administrador: no hay registro autoservicio.
Comandos
Sesión
tracker login [--email <email>] [--password <pw>] Entrar. Instala el skill de Claude Code.
tracker logout Cerrar sesión.
tracker whoami Quién sos, tu rol y tus proyectos.
tracker setup Reinstalar el skill.
Tickets
tracker ls [-p APP] [--all] [--done] [--limit N] Tus tickets sin terminar.
tracker show APP-12 Detalle, subtareas y comentarios.
tracker search "texto" [-p APP] Buscar en título y descripción.
tracker projects Tus proyectos.
tracker new -p APP "Título" [-t bug] [--priority high] [-d "..."] [--me] [-c "Por hacer"]
tracker mv APP-12 "revision" Mover de columna.
tracker assign APP-12 [nombre|email] [--me] Asignar. Sin nombre, desasigna.
tracker edit APP-12 [--title "..."] [-d "..."] [-t bug] [--priority high]
[--epic "..."] [--estimate 4] [--date 2026-09-30]
tracker rm APP-12 [--yes] Borrar. Sin --yes solo muestra qué se lleva.
tracker sub APP-12 Ver las subtareas.
tracker sub APP-12 "Título" [--me] Crear una.
tracker activity APP-12 Historial de cambios del ticket.
Comentarios
tracker comment APP-12 "texto" Comentar.
tracker comment ls APP-12 Verlos, numerados.
tracker comment edit APP-12 2 "texto nuevo"
tracker comment rm APP-12 2
Adjuntos
tracker files ls APP-12 Los archivos del ticket.
tracker files add APP-12 ./captura.png Subir uno (hasta 25 MB).
tracker files get APP-12 "captura" [-o ruta] Bajarlo.
tracker files rm APP-12 "captura"
Épicas
tracker epic ls APP Las épicas del proyecto y su avance.
tracker epic show APP "migracion" Detalle y los tickets que cuelgan.
tracker epic add APP "Migración de datos" [-d "..."] [--status planned] [--color "#5b8def"] [--date 2026-09-30]
tracker epic edit APP "migracion" [--name "..."] [-d "..."] [--status done] [--date ""]
tracker epic assign APP-12 "migracion" Poner un ticket en una épica.
tracker epic assign APP-12 ninguna Sacarlo de la épica.
tracker epic rm APP "migracion" Borrarla (tiene que estar vacía).
Horas
tracker start APP-12 [--note "..."] Arrancar el cronómetro.
tracker stop Pararlo y cargar las horas.
tracker status Ver el cronómetro activo.
tracker log APP-12 1h30m [--date 2026-08-06] [--note "..."]
tracker log ls APP-12 Las cargas del ticket, numeradas.
tracker log edit APP-12 2 [2h] [--date ...] [--note "..."]
tracker log rm APP-12 2
tracker hours [--days 7] [-p APP] Tus horas de los últimos días.
tracker timesheet APP [--days 7] Las del equipo en el proyecto.
tracker report APP [--days 30] Cómo va el proyecto.
Proyectos
tracker project ls Tus proyectos.
tracker project new APP "Nombre" [-d "..."] [--client "Acme"]
tracker project edit APP [--name "..."] [-d "..."] [--client "..."]
tracker project archive APP | tracker project activate APP
tracker member ls APP Quiénes son miembros.
tracker member add APP nacho | tracker member rm APP nacho
tracker column ls APP Las columnas del tablero.
tracker column add APP "En QA" [--done] --done la marca como final.
tracker column edit APP "qa" [--name "..."] [--done] [--undone]
tracker column mv APP "qa" 3 Moverla (1 es la primera).
tracker column rm APP "qa" ["destino"] Sus tickets van a la otra columna.
Ideas y bugs
tracker idea ls [--all] [--kind bug] Lo que anotó el equipo.
tracker idea show "filtro"
tracker idea add "Título" [-d "..."] [--kind bug] Lo puede hacer cualquiera.
tracker idea edit "filtro" [--title "..."] [-d "..."]
tracker idea done|planned|declined|open "filtro" [--note "..."]
tracker idea promote "filtro" APP Pasarla a ticket.
tracker idea rm "filtro"
Administración
tracker user ls Las personas y su rol.
tracker user edit nacho [--role dev] [--on|--off] Cambiar rol o desactivar.
tracker role ls [dev] La matriz de permisos.
tracker role keys Qué significa cada permiso.
tracker role allow dev tickets.delete
tracker role deny dev tickets.delete
tracker usage Cuánto está consumiendo Tracker.
Documentación
tracker docs ls APP [-s "texto"] Documentos del proyecto.
tracker docs read APP "spec" El texto del documento por stdout.
tracker docs get APP "spec" [-o ruta] Bajar el original.
tracker docs add APP ./archivo.docx [-d "..."] Subir un archivo.
tracker docs edit APP "spec" "descripción nueva"
tracker docs rm APP "spec" Borrarlo.
Clientes y entornos de Salesforce
tracker client ls Los clientes que ves.
tracker client add "Acme" Crear uno (admin).
tracker client link APP "Acme" Asociar un proyecto a un cliente.
tracker env ls "Acme" | tracker env ls -p APP Entornos del cliente.
tracker env add "Acme" "Producción" --kind production [--url ...] [--org-id ...]
tracker env orgs Tus orgs autenticadas en "sf".
tracker env link "Acme" "UAT" [--alias acme-uat] Completa el Org ID desde "sf".
tracker env connect "Acme" "UAT" [--alias ...] Le da a Tracker tu autorización.
tracker env edit "Acme" "UAT" [--name ...] [--kind ...] [--url ...] [--note ...]
tracker env scan "Acme" "UAT" on|off Prende o apaga el scan nocturno.
tracker env revoke "Acme" "UAT" Le saca la autorización a Tracker.
tracker env rm "Acme" "UAT" [--yes] Borrarlo, con sus hallazgos.
Análisis de la org
tracker scan "Acme" [--env UAT] [--only config|automation|coverage|api] [--dry-run]
tracker scan -p APP Deduce el cliente del proyecto.
tracker scan ls "Acme" [--all] [--kind ...] La bandeja de hallazgos.
tracker scan show "Acme" "process builder" El detalle y la huella.
tracker scan dismiss "Acme" "..." [--note "..."] No vuelve a aparecer.
tracker scan review "Acme" "..." Visto, se deja para después.
tracker scan promote "Acme" "..." APP Pasa al backlog fuera de alcance.
Fuera de alcance
tracker oos ls APP [--all] Lo que no cubre el contrato.
tracker oos show APP "sap" La evidencia de un registro.
tracker oos add APP "Integración con SAP" [--ticket APP-12] [-d "..."] [-e "..."]
tracker oos confirm APP "sap" [--note "..."] Confirmar que está afuera.
tracker oos sales APP "sap" Pasar a comercial.
tracker oos sold APP "sap" Se vendió: vuelve al tablero.
tracker oos dismiss APP "sap" Falso positivo, sí estaba dentro.
tracker oos edit APP "sap" [-d "..."] [-e "..."]
tracker oos rm APP "sap"
Genérico
tracker query <tabla> [-w col=eq.valor] [--select a,b] [--limit N]
Global
--json Salida en JSON.
-h, --help
-v, --versionDetalles que ahorran una vuelta
mv acepta prefijos sin acentos. tracker mv APP-12 rev encuentra "En revisión". Si el
prefijo coincide con más de una columna, el comando falla y lista las opciones en lugar de elegir.
Un número pelado en log son horas. tracker log APP-12 2 carga dos horas. También acepta
1.5, 1,5, 1h 30m, 90m y 1:30.
Solo hay un cronómetro por persona. start sobre otro ticket para el anterior y carga sus
minutos; el comando lo avisa.
Las épicas se resuelven por parte del nombre, igual que las columnas: tracker epic show APP
migracion encuentra "Migración de datos". Si coincide con más de una, falla y lista en lugar de
elegir — adivinar mal acá manda tickets a la épica equivocada sin avisar. Y epic assign toma la
clave del ticket, no el proyecto: el proyecto sale del propio ticket, así que no se puede asignar a
una épica de otro proyecto por error.
epic rm se niega si la épica tiene tickets. Borrarla igual no los borra —el vínculo se pone
en null—, pero deja un proyecto donde de golpe todo quedó "sin épica" y nadie sabe por qué. Hay que
vaciarla primero, que es una decisión explícita.
docs read es el comando que más rinde con Claude. Devuelve el texto de un .docx, un .xlsx
o un .pdf por salida estándar, sin que tengas Office instalado: la app extrae el texto al subir
el archivo y el CLI lo lee de ahí. Si el PDF es un escaneo son imágenes de las páginas y no hay
texto que leer; ahí docs get te baja el original.
Los archivos que subís con docs add quedan sin texto extraído. La extracción corre en el
navegador, y duplicar ese parser acá sería garantizar que las dos copias se desincronicen. Se
descargan bien, pero no aparecen al buscar por contenido hasta que alguien los suba desde la web.
El comando te lo avisa.
Para vaciar un campo se pasa vacío, y en PowerShell hay que escribirlo pegado con =:
--note='' funciona, --note "" no — PowerShell se come el argumento vacío y el CLI ve la opción
sin valor. Vale para -d, --note, --date, --estimate y --client. En bash las dos formas
andan.
Lo que no se puede deshacer pide --yes. tracker rm APP-12 y tracker env rm sin esa
bandera no borran: muestran qué se llevaría por delante (subtareas, horas, hallazgos) y el comando
exacto para confirmar. Es a propósito, y sobre todo para que Claude no borre nada que nadie pidió.
Los comentarios y las cargas de horas se referencian por su número, el que imprimen
comment ls y log ls, no por uuid. Los dos listados ordenan igual, así que el número no se
mueve entre un comando y el otro.
query es la escotilla. Solo lectura, sobre cualquier tabla o vista, con la sintaxis de
filtros de PostgREST (col=eq.valor, col=ilike.*texto*, col=gte.10). Sirve para consultar
partes de la app que todavía no tienen comando propio, sin esperar una versión nueva del CLI.
Fuera de alcance: por qué start y mv a veces fallan
Si un ticket está marcado fuera del alcance contratado, start y mv no avisan: fallan, y
te muestran el motivo y la evidencia. Existe para que nadie se ponga a construir algo que el
cliente no pagó, que es más barato de evitar que de discutir después.
Para seguir de todas formas está --anyway, y es a propósito una decisión explícita de una
persona. Si el registro es un error, tracker oos dismiss devuelve el ticket al tablero y deja
constancia de que se revisó, que es mejor que borrarlo.
Nunca hay precios ni estimaciones en estos registros: título, descripción y evidencia. La cotización la maneja comercial fuera de Tracker.
El scan de la org
tracker scan "Acme" mira una org de Salesforce y deja lo que encuentra en una bandeja del
cliente. Cuatro detectores: cambios del audit trail (agrupados por día y sección, que es la señal
de scope creep), Process Builder y Workflow Rules activos, Apex por debajo del 75% de cobertura, y
clases en versiones de API viejas.
Solo lectura. Consultas SOQL, ningún deploy y ningún retrieve: se puede correr contra
producción sin miedo. Bajar la metadata completa tardaría minutos y consumiría llamadas de API del
cliente.
tracker scan corre con tu sesión de sf, así que solo podés escanear orgs a las que ya tenés
acceso. tracker env orgs lista lo que tenés autenticado y tracker env link copia el Org ID a
Tracker sin copiar nada más.
tracker env connect es lo que hace que el scan corra solo todas las noches. Le pasa a Tracker el
refresh token que tu sf ya consiguió —el mismo mecanismo con el que se mueve una autorización a otra
máquina— y el servidor lo guarda cifrado. Desde ahí escanea sin que nadie tenga nada prendido, y el
botón Escanear de la web también funciona.
sf org login web --instance-url https://test.salesforce.com --alias acme-uat
tracker env connect "Acme" "UAT" --alias acme-uatDos cosas que conviene saber de ese camino: en la org del cliente la autorización figura como
"Salesforce CLI" (no "Tracker"), y desconectar desde Tracker no revoca en Salesforce — borra
nuestra copia y deja tu sf local intacto. Revocarla de verdad es sf org logout o Setup → Connected
Apps OAuth Usage.
Un hallazgo no es un registro fuera de alcance. El hallazgo es una observación sobre la org y
vive a nivel cliente; el registro fuera de alcance está atado a un proyecto y a un contrato. Como un
cliente puede tener varios proyectos nuestros a la vez, cuál corresponde lo decide una persona:
tracker scan promote "Acme" "..." APP.
Volver a escanear no resucita lo descartado. Cada hallazgo lleva una huella estable; lo que ya está en la bandeja se actualiza y lo descartado sigue descartado. Es la razón por la que la bandeja sigue siendo usable en la segunda semana.
Requiere el sf CLI instalado y una org autenticada. Si falta, el comando lo dice.
Permisos y seguridad
El CLI ve y puede exactamente lo mismo que vos en la web. Se autentica con tu sesión y la anon
key pública; nunca con la service_role. La autorización vive en las políticas de RLS de la base,
así que no hay una segunda capa que pueda quedar desincronizada ni forma de que el CLI te habilite
algo que el navegador no.
La sesión queda en un archivo. ~/.tracker/session.json, con permisos 0600 en sistemas que
los respetan. Cualquier proceso que corra con tu usuario lo puede leer — igual que el
localStorage del navegador. tracker logout lo borra. Si perdés la máquina, cambiá la
contraseña desde la app: eso invalida los refresh tokens.
No hay comandos destructivos más allá de docs rm y oos rm. No se puede borrar un ticket, un
proyecto ni un cliente desde el CLI, a propósito.
El scan no escribe en Salesforce. Ni un deploy, ni un cambio de configuración, ni un test
ejecutado: solo SELECT. Lo que escribe lo escribe en Tracker.
Variables de entorno
| Variable | Para qué |
| -------- | -------- |
| TRACKER_EMAIL, TRACKER_PASSWORD | Login no interactivo (scripts, CI). |
| TRACKER_HOME | Mover la carpeta de configuración. |
| TRACKER_SUPABASE_URL, TRACKER_SUPABASE_ANON_KEY | Apuntar a otro proyecto de Supabase. |
| TRACKER_APP_URL | Cambiar la URL que se imprime en los links. |
| CLAUDE_CONFIG_DIR | Dónde se instala el skill. |
Desarrollo
El CLI vive en cli/ dentro del repo de Tracker.
cd cli
npm install
npm run build
npm install -g . # queda `tracker` apuntando a este códigoSin dependencias de runtime: fetch, util.parseArgs y node:fs vienen en Node. Eso mantiene la
instalación global en un solo paquete y sin superficie de supply chain.
Verificación
$env:TRACKER_EMAIL = '[email protected]'
$env:TRACKER_PASSWORD = '...'
powershell -File tests/cli-checks.ps1 -Project APP [-SfAlias escUAT]Corre contra la API real y no toca datos reales: crea su propio ticket y su propio cliente, los usa, y los borra al terminar. El borrado del ticket va por la API y no por el CLI porque el CLI no borra tickets a propósito; con un rol de dev ese paso no va a poder, y está bien — el test no debería tener más permisos que quien lo corre.
Escanea una org de Salesforce de verdad si hay una autenticada en sf. Elige un sandbox y nunca
producción por su cuenta; con -SfAlias le decís cuál. Es solo lectura. Sin sf cae a un hallazgo
insertado por la API y avisa cuál de los dos caminos tomó, así que la suite sirve igual en una
máquina sin Salesforce (112 checks con org, 103 sin).
Escanear de verdad importa: los dos bugs que tuvo el scan —el quoting de spawn y que Flow no
tiene DeveloperName— habrían pasado contra un doble.
Publicar una versión nueva
npm version patch # o minor
npm publish --access publicprepublishOnly reconstruye dist/ solo. Si el publish pide un código de 2FA, es lo esperado:
no hace falta ningún token guardado en ninguna parte.
