claude-code-arcane 1.4.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +5 -4
  3. package/dist/cli.js +2 -0
  4. package/docs/SKILLS-CATALOG.md +30 -3
  5. package/docs/USER-GUIDE.md +2 -2
  6. package/docs/coding-standards.md +26 -0
  7. package/package.json +2 -1
  8. package/profiles/job-hunt.yaml +12 -2
  9. package/profiles/second-brain.yaml +37 -0
  10. package/rules/drafter-reviewer.md +39 -0
  11. package/rules/vault-conventions.md +144 -0
  12. package/skills/brain-dump/SKILL.md +53 -0
  13. package/skills/cold-outreach/SKILL.md +10 -10
  14. package/skills/cold-outreach/references/recruiter-playbook.md +5 -5
  15. package/skills/cover-letter/SKILL.md +8 -8
  16. package/skills/cv-ats-export/SKILL.md +19 -6
  17. package/skills/cv-ats-export/scripts/cv_export.py +49 -4
  18. package/skills/cv-ats-export/scripts/verify_pdf.py +90 -0
  19. package/skills/cv-tailor/SKILL.md +7 -7
  20. package/skills/cv-tailor/references/ats-keywords.md +9 -9
  21. package/skills/hub-note/SKILL.md +68 -0
  22. package/skills/interview-prep/SKILL.md +7 -7
  23. package/skills/interview-prep/references/star-framework.md +10 -10
  24. package/skills/job-aplicar/SKILL.md +88 -0
  25. package/skills/job-hunt/SKILL.md +20 -13
  26. package/skills/job-hunt/references/templates/Aplicacion.md +6 -2
  27. package/skills/job-hunt/references/templates/CV Custom.md +1 -1
  28. package/skills/job-hunt/references/templates/Contacto.md +1 -1
  29. package/skills/job-hunt/references/templates/Dashboard.md +19 -15
  30. package/skills/job-hunt/references/templates/Perfil.md +2 -2
  31. package/skills/job-outcome/SKILL.md +55 -0
  32. package/skills/job-scrape/SKILL.md +95 -0
  33. package/skills/job-scrape/references/dedup-playbook.md +25 -0
  34. package/skills/job-scrape/references/getonbrd-cli.md +62 -0
  35. package/skills/job-scrape/references/getonbrd-urls.md +37 -0
  36. package/skills/job-scrape/references/linkedin-cli.md +64 -0
  37. package/skills/job-scrape/references/linkedin-urls.md +42 -0
  38. package/skills/job-scrape/references/seen_jobs.schema.json +68 -0
  39. package/skills/job-scrape/scripts/getonbrd_search.py +501 -0
  40. package/skills/job-scrape/scripts/linkedin_search.py +428 -0
  41. package/skills/job-search/SKILL.md +22 -19
  42. package/skills/job-search/references/scoring-rubric.md +8 -8
  43. package/skills/job-upskill/SKILL.md +58 -0
  44. package/skills/linkedin-optimize/SKILL.md +5 -5
  45. package/skills/master-profile/SKILL.md +17 -17
  46. package/skills/network-map/SKILL.md +7 -7
  47. package/skills/obsidian-bases/SKILL.md +85 -0
  48. package/skills/obsidian-bases/references/bases-syntax.md +123 -0
  49. package/skills/obsidian-canvas/SKILL.md +91 -0
  50. package/skills/obsidian-markdown/SKILL.md +110 -0
  51. package/skills/pdf-generator/scripts/fill_inspect.py +2 -0
  52. package/skills/pdf-generator/scripts/render_body.py +2 -0
  53. package/skills/personal-brand/SKILL.md +10 -10
  54. package/skills/personal-brand/references/post-pillars.md +14 -14
  55. package/skills/portfolio-site/SKILL.md +11 -11
  56. package/skills/review-dump/SKILL.md +108 -0
  57. package/skills/review-monthly/SKILL.md +56 -0
  58. package/skills/review-weekly/SKILL.md +91 -0
  59. package/skills/second-brain/SKILL.md +211 -0
  60. package/skills/second-brain/hooks/hooks.json +16 -0
  61. package/skills/second-brain/hooks/validate-note.sh +85 -0
  62. package/skills/second-brain/references/cross-project.md +57 -0
  63. package/skills/second-brain/references/templates/Atomic.md +22 -0
  64. package/skills/second-brain/references/templates/Daily.md +25 -0
  65. package/skills/second-brain/references/templates/Dashboard.base +70 -0
  66. package/skills/second-brain/references/templates/Dump.md +11 -0
  67. package/skills/second-brain/references/templates/Hub.md +22 -0
  68. package/skills/second-brain/references/templates/Monthly.md +29 -0
  69. package/skills/second-brain/references/templates/Weekly.md +29 -0
  70. package/skills/second-brain/references/templates/codebases.md +37 -0
  71. package/skills/second-brain/references/templates/hot.md +37 -0
  72. package/skills/second-brain/references/templates/vault-CLAUDE.md +127 -0
  73. package/skills/vault-audit/SKILL.md +72 -0
  74. package/skills/vault-audit/scripts/vault_audit.py +539 -0
  75. package/skills/vault-clip/SKILL.md +73 -0
  76. package/skills/vault-recall/SKILL.md +82 -0
  77. package/skills/vault-recall/scripts/vault_index.py +626 -0
  78. package/skills/vault-tidy/SKILL.md +76 -0
  79. package/skills/xlsx-generator/scripts/formula_check.py +2 -0
  80. package/skills/xlsx-generator/scripts/libreoffice_recalc.py +2 -0
  81. package/skills/xlsx-generator/scripts/xlsx_add_column.py +2 -0
  82. package/skills/xlsx-generator/scripts/xlsx_insert_row.py +2 -0
  83. package/skills/xlsx-generator/scripts/xlsx_reader.py +2 -0
  84. package/skills/zettel/SKILL.md +66 -0
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: master-profile
3
- description: "Build and maintain the master professional profile — the single source of truth (experience, skills with levels, projects, education, references, bios) that every CV, LinkedIn profile and portfolio derives from. Triggers: perfil maestro, master resume, cronologia laboral, single source of truth CV, mi experiencia profesional."
3
+ description: "Build and maintain the master professional profile - the single source of truth (experience, skills with levels, projects, education, references, bios) that every CV, LinkedIn profile and portfolio derives from. Triggers: perfil maestro, master resume, cronologia laboral, single source of truth CV, mi experiencia profesional."
4
4
  argument-hint: "[build | update | derive <role>]"
5
5
  category: "career"
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Glob, Grep, Write, Edit
8
8
  ---
9
9
 
10
- # Master Profile — Single Source of Truth
10
+ # Master Profile - Single Source of Truth
11
11
 
12
12
  Construís y mantenés el **perfil maestro**: el documento del que derivan todos los CVs, el LinkedIn y el portfolio. La regla de oro: **si algo cambia, se cambia acá primero** y de acá se sincroniza al resto.
13
13
 
@@ -21,32 +21,32 @@ Mantener N CVs sincronizados a mano es la causa #1 de errores (fechas que no coi
21
21
 
22
22
  Generá el archivo con estas secciones (todas las que apliquen):
23
23
 
24
- 1. **Personal info** — nombre, display name, headline actual, ubicación, email público vs personal, teléfono, LinkedIn, GitHub, portfolio. (El email *público* puede diferir del personal.)
25
- 2. **Bios** — tres largos: corto (hero/one-liner), medio (2–3 oraciones para "About"), largo (about page completo).
26
- 3. **Work experience** (más reciente primero) — por cada rol: empresa, período, ubicación/modalidad, producto, stack, manager/referencia, y **bullets de logros con número→contexto→resultado**.
27
- 4. **Education** — institución, período, foco.
28
- 5. **Certifications** — nombre, año, estado (completo/in progress).
29
- 6. **Skills consolidados con nivel** — agrupados (lenguajes, frameworks, infra, tooling) con nivel (Expert/Advanced/Proficient/…) y opcionalmente % para el portfolio.
30
- 7. **Projects** — tech, rol, highlights, link en vivo.
31
- 8. **Achievements / highlights** — premios, showcases, hitos.
32
- 9. **Languages** — idioma + nivel.
33
- 10. **References** — nombre, rol, relación, contacto.
24
+ 1. **Personal info** - nombre, display name, headline actual, ubicación, email público vs personal, teléfono, LinkedIn, GitHub, portfolio. (El email *público* puede diferir del personal.)
25
+ 2. **Bios** - tres largos: corto (hero/one-liner), medio (2-3 oraciones para "About"), largo (about page completo).
26
+ 3. **Work experience** (más reciente primero) - por cada rol: empresa, período, ubicación/modalidad, producto, stack, manager/referencia, y **bullets de logros con número→contexto→resultado**.
27
+ 4. **Education** - institución, período, foco.
28
+ 5. **Certifications** - nombre, año, estado (completo/in progress).
29
+ 6. **Skills consolidados con nivel** - agrupados (lenguajes, frameworks, infra, tooling) con nivel (Expert/Advanced/Proficient/…) y opcionalmente % para el portfolio.
30
+ 7. **Projects** - tech, rol, highlights, link en vivo.
31
+ 8. **Achievements / highlights** - premios, showcases, hitos.
32
+ 9. **Languages** - idioma + nivel.
33
+ 10. **References** - nombre, rol, relación, contacto.
34
34
 
35
35
  ## Modos
36
36
 
37
- ### `build` — Crear el maestro desde cero
37
+ ### `build` - Crear el maestro desde cero
38
38
  1. Si no existe el workspace, sugerir `/job-hunt setup` primero.
39
- 2. Recolectar info por sección — preferí **entrevistar al usuario por bloques** (no un cuestionario gigante). Empezá por experiencia y skills.
39
+ 2. Recolectar info por sección - preferí **entrevistar al usuario por bloques** (no un cuestionario gigante). Empezá por experiencia y skills.
40
40
  3. Para cada logro, empujar a la forma **cuantificable**: "¿qué número podés ponerle? ¿comparado con qué? ¿qué resultado tuvo?". Un bullet sin métrica es una oportunidad perdida.
41
41
  4. Escribir `01-Perfiles/Perfil Maestro.md`.
42
42
  5. Sugerir derivar el primer perfil por rol: `/master-profile derive <role>`.
43
43
 
44
- ### `update` — Mantener al día
44
+ ### `update` - Mantener al día
45
45
  1. Leer el maestro actual.
46
46
  2. Aplicar el cambio (nuevo rol, nuevo logro, ascenso, proyecto).
47
47
  3. **Avisar qué derivados quedan desactualizados** (CVs por rol, LinkedIn, portfolio) y ofrecer re-derivarlos.
48
48
 
49
- ### `derive <role>` — Vista por rol
49
+ ### `derive <role>` - Vista por rol
50
50
  1. Leer el maestro.
51
51
  2. Crear/actualizar `01-Perfiles/<Role>.md` con el template `Perfil` (ver `Templates/Perfil.md`): filtrar y reordenar la experiencia/skills/proyectos hacia ese rol, definir keywords objetivo, score mínimo y mercado.
52
52
  3. Este perfil por rol es el `perfil_base` que después usa `/cv-tailor`.
@@ -61,7 +61,7 @@ Generá el archivo con estas secciones (todas las que apliquen):
61
61
  ## Reglas
62
62
 
63
63
  - Una sola fuente de verdad: no dejar que un CV por rol "evolucione" por fuera del maestro.
64
- - No inventar logros ni métricas — si el usuario no tiene el número, marcarlo como pendiente, no fabricarlo.
64
+ - No inventar logros ni métricas - si el usuario no tiene el número, marcarlo como pendiente, no fabricarlo.
65
65
  - Separar email público de personal; no exponer datos sensibles en archivos que vayan a un remoto.
66
66
 
67
67
  ## Handoff
@@ -7,7 +7,7 @@ user-invocable: true
7
7
  allowed-tools: Read, Glob, Grep, Bash, Write, Edit
8
8
  ---
9
9
 
10
- # Network Map — Inteligencia de contactos para warm intros
10
+ # Network Map - Inteligencia de contactos para warm intros
11
11
 
12
12
  Convertís el **export de conexiones de LinkedIn** en inteligencia accionable: dado un target company, quién de tu red 1er-grado trabaja (o trabajó) ahí, quién puede darte un warm intro, y un mensaje custom por contacto. Reemplaza a LinkedIn Premium para esto: solo necesitás tu propio export + Claude.
13
13
 
@@ -20,9 +20,9 @@ En LinkedIn → **Settings → Data Privacy → Get a copy of your data → Down
20
20
  ## Qué produce
21
21
 
22
22
  Dado un target company:
23
- 1. **1er-grado en la empresa** — contactos tuyos que trabajan ahí ahora (match por `Company`).
24
- 2. **Paths de warm intro** — contactos 1er-grado que probablemente conozcan gente del target (ej. ex-empleados de la empresa, gente del mismo rubro/rol) y podrían presentarte. *Nota honesta:* el export solo tiene tus 1er-grado; el verdadero 2do-grado (las conexiones de ellos) no está en el archivo. Lo que hacemos es **inferir** buenos candidatos a intro desde tus 1er-grado (empleo actual/pasado en el target, overlap de empresa/rol), no leer la red de cada uno.
25
- 3. **Mensaje por contacto** — template custom según historia compartida (misma empresa pasada, mismo rubro, conexión vieja vs reciente).
23
+ 1. **1er-grado en la empresa** - contactos tuyos que trabajan ahí ahora (match por `Company`).
24
+ 2. **Paths de warm intro** - contactos 1er-grado que probablemente conozcan gente del target (ej. ex-empleados de la empresa, gente del mismo rubro/rol) y podrían presentarte. *Nota honesta:* el export solo tiene tus 1er-grado; el verdadero 2do-grado (las conexiones de ellos) no está en el archivo. Lo que hacemos es **inferir** buenos candidatos a intro desde tus 1er-grado (empleo actual/pasado en el target, overlap de empresa/rol), no leer la red de cada uno.
25
+ 3. **Mensaje por contacto** - template custom según historia compartida (misma empresa pasada, mismo rubro, conexión vieja vs reciente).
26
26
 
27
27
  ## El motor
28
28
 
@@ -40,10 +40,10 @@ Devuelve nombre, posición, empresa, URL del perfil y fecha de conexión. Vos (C
40
40
 
41
41
  ## Modos
42
42
 
43
- ### `import <path>` — Registrar el export
43
+ ### `import <path>` - Registrar el export
44
44
  Copiar/referenciar `Connections.csv` en `05-Contactos/`, verificar que parsea (corré el script con `--top-companies`), y reportar tamaño de la red + top empresas.
45
45
 
46
- ### `[company]` — Mapear una empresa
46
+ ### `[company]` - Mapear una empresa
47
47
  1. Correr el script filtrando por la empresa.
48
48
  2. Clasificar: 1er-grado actuales en la empresa vs candidatos a warm-intro (ex-empleados / mismo rubro).
49
49
  3. Priorizar por relevancia (seniority/rol vs tu objetivo) y calidez (conexión reciente, historia compartida).
@@ -53,7 +53,7 @@ Copiar/referenciar `Connections.csv` en `05-Contactos/`, verificar que parsea (c
53
53
  ## Reglas
54
54
 
55
55
  - Data de terceros: tratamiento local, nunca a un remoto sin confirmación; respetá privacidad.
56
- - No inventar relaciones ni 2do-grado que el export no soporta — sé explícito sobre qué es dato y qué es inferencia.
56
+ - No inventar relaciones ni 2do-grado que el export no soporta - sé explícito sobre qué es dato y qué es inferencia.
57
57
  - Calidad sobre cantidad: 5 contactos bien elegidos > 50 mensajes genéricos.
58
58
 
59
59
  ## Handoff
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: obsidian-bases
3
+ description: "Crea y edita archivos .base de Obsidian: vistas table/cards/list/map, filtros, formulas y summaries sobre las propiedades de las notas. Incluye migracion desde queries de Dataview. Triggers: obsidian bases, archivo .base, base de datos en obsidian, vista de notas, dashboard obsidian, migrar dataview."
4
+ argument-hint: "[create <descripcion> | explain <archivo.base> | migrate <query dataview>]"
5
+ category: "pkm"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Write, Edit
8
+ ---
9
+
10
+ # Obsidian Bases - Vistas nativas
11
+
12
+ Bases es el core plugin de Obsidian (1.9+) que convierte las propiedades de las notas en tablas y cards vivas. No se instala nada. Adaptado de `kepano/obsidian-skills` al formato de este repo.
13
+
14
+ Modo: `$ARGUMENTS`
15
+
16
+ La referencia completa de sintaxis está en `references/bases-syntax.md`. Leela antes de escribir un `.base`: la mitad de los errores son de quoting de YAML, no de lógica.
17
+
18
+ ## Fase 1 - Verificar que Bases esté disponible
19
+
20
+ Leer `.obsidian/core-plugins.json` del vault. Si `bases` no está habilitado, decirlo y ofrecer las dos salidas: habilitarlo (es core, no requiere instalar) o resolver la vista con una tabla markdown estática. **Nunca escribir un `.base` en un vault que no lo tiene habilitado:** queda como un archivo que Obsidian muestra en crudo.
21
+
22
+ ## Fase 2 - Modos
23
+
24
+ ### `create` - Vista nueva
25
+ 1. Entender qué pregunta responde la vista. Una vista sin pregunta concreta termina siendo una tabla de todo el vault que nadie mira.
26
+ 2. **Verificar que las propiedades existan**: `Grep` en el frontmatter del vault por los campos que vas a filtrar. Filtrar por una propiedad que ninguna nota declara produce una vista vacía y parece un bug de Bases.
27
+ 3. Escribir el `.base` en `Bases/`, con approval antes de crear el archivo.
28
+ 4. Avisar que hay que abrirlo en Obsidian para confirmar que renderiza: la sintaxis se valida ahí, no acá.
29
+
30
+ ### `explain` - Leer un `.base` existente
31
+ Traducir el archivo a lenguaje llano: qué notas entran, qué columnas muestra, qué calcula cada fórmula. Read-only.
32
+
33
+ ### `migrate` - Desde Dataview
34
+ Traducir la query, y **decir explícitamente qué no se puede traducir**. Bases no cubre campos inline (`campo:: valor` en medio de la nota) ni texto computado ni `dataviewjs`. Si la query depende de eso, la respuesta honesta es que se quede en Dataview: una migración a medias deja al usuario con una vista que miente.
35
+
36
+ ## Estructura de un `.base`
37
+
38
+ ```yaml
39
+ filters:
40
+ and:
41
+ - file.inFolder("03_Resources")
42
+ - 'type == "atomic"'
43
+
44
+ formulas:
45
+ edad_dias: '(now() - file.mtime).days'
46
+
47
+ properties:
48
+ formula.edad_dias:
49
+ displayName: "Dias sin tocar"
50
+
51
+ views:
52
+ - type: table
53
+ name: "Notas atomicas"
54
+ filters:
55
+ not:
56
+ - file.hasTag("archivada")
57
+ order:
58
+ - file.name
59
+ - created
60
+ - formula.edad_dias
61
+ summaries:
62
+ formula.edad_dias: Average
63
+ ```
64
+
65
+ Los cinco bloques top-level son `filters`, `formulas`, `properties`, `summaries` y `views`. Los filtros globales aplican a todas las vistas; cada vista puede agregar los suyos.
66
+
67
+ ## Los tres errores que se repiten
68
+
69
+ 1. **Quoting de YAML.** Cualquier expresión con `:`, `{`, `}`, `[`, `]` va entre comillas. Si la expresión ya tiene comillas dobles adentro, el string va en comillas simples: `'if(done, "Si", "No")'`.
70
+ 2. **Duraciones.** Restar dos fechas da una `Duration`, no un número: hay que acceder al campo antes de operar (`.days`, `.hours`). `round(now() - file.mtime)` falla; `(now() - file.mtime).days` funciona.
71
+ 3. **Nulls.** Una propiedad ausente rompe la fórmula. Envolver en `if(propiedad, ...)` cuando el campo puede faltar, que en un vault real es casi siempre.
72
+
73
+ Una fórmula referenciada en `order` que no está declarada en `formulas` falla en silencio: la columna simplemente no aparece.
74
+
75
+ ## Reglas
76
+
77
+ - `file.backlinks` es caro: no lo pongas en una vista que se abre seguido.
78
+ - No crear una vista que dependa de una propiedad que el vault todavía no usa: primero se agrega al contrato de frontmatter del `CLAUDE.md`.
79
+ - Un `.base` por pregunta. Un archivo con ocho vistas es un dashboard que nadie lee.
80
+ - Pedí approval antes de escribir o sobrescribir un `.base`.
81
+ - Sin guiones largos.
82
+
83
+ ## Handoff
84
+
85
+ Base READY cuando el archivo existe y el usuario confirmó que renderiza en Obsidian. Si la vista necesitaba campos que las notas no tienen, el siguiente paso es actualizar el contrato de frontmatter con `/second-brain` y completar las notas con `/vault-tidy frontmatter`.
@@ -0,0 +1,123 @@
1
+ # Bases Syntax Reference
2
+
3
+ Referencia de la sintaxis de los archivos `.base` de Obsidian (core plugin, 1.9+). Fuente: `https://obsidian.md/help/bases/syntax`.
4
+
5
+ ## Bloques top-level
6
+
7
+ | Bloque | Qué hace |
8
+ |---|---|
9
+ | `filters` | Condiciones globales, aplican a todas las vistas. Opcional. |
10
+ | `formulas` | Propiedades calculadas, disponibles en todas las vistas. |
11
+ | `properties` | Configuración de display de una propiedad (`displayName`). |
12
+ | `summaries` | Fórmulas de agregación propias. |
13
+ | `views` | Lista de vistas: cómo se renderizan los datos. |
14
+
15
+ Sin `filters`, la base incluye **todos** los archivos del vault.
16
+
17
+ ## Filtros
18
+
19
+ Un objeto de filtro contiene `and`, `or` o `not`, y cada uno una lista de objetos de filtro o de statements (strings). Se anidan.
20
+
21
+ ```yaml
22
+ filters:
23
+ or:
24
+ - file.hasTag("tag")
25
+ - and:
26
+ - file.hasTag("book")
27
+ - file.hasLink("Textbook")
28
+ - not:
29
+ - file.hasTag("book")
30
+ - file.inFolder("Required Reading")
31
+ ```
32
+
33
+ Operadores:
34
+
35
+ - Aritméticos: `+`, `-`, `*`, `/`, `%`, `()`
36
+ - Comparación: `==`, `!=`, `>`, `<`, `>=`, `<=`
37
+ - Booleanos: `!`, `&&`, `||`
38
+ - Fechas: sumar o restar duraciones con `+` y `-`. Unidades: `y/year/years`, `M/month/months`, `w/week/weeks`, `d/day/days`, `h/hour/hours`, `m/minute/minutes`, `s/second/seconds`
39
+
40
+ ## Propiedades
41
+
42
+ Tres orígenes:
43
+
44
+ | Forma | Origen |
45
+ |---|---|
46
+ | `note.propiedad` o `propiedad` | frontmatter de la nota |
47
+ | `file.*` | metadata del archivo |
48
+ | `formula.nombre` | fórmula declarada en `formulas` |
49
+
50
+ Propiedades de archivo: `file.name`, `file.path`, `file.folder`, `file.ext`, `file.size`, `file.ctime`, `file.mtime`, `file.tags`, `file.links`, `file.embeds`, `file.backlinks`.
51
+
52
+ `file.backlinks` es costoso de calcular: evitarlo en vistas de uso frecuente.
53
+
54
+ Tipos de dato: strings (entre comillas), números, booleanos (`true`/`false`), fechas, duraciones, objetos, listas, y files/links.
55
+
56
+ ## Fórmulas
57
+
58
+ ```yaml
59
+ formulas:
60
+ formatted_price: 'if(price, price.toFixed(2) + " dollars")'
61
+ ppu: "(price / age).toFixed(2)"
62
+ ```
63
+
64
+ Funciones habituales: `if()`, `date()`, `now()`, `duration()`, además de los métodos de cada tipo (`toFixed`, `round`, `mean`).
65
+
66
+ Tres trampas:
67
+
68
+ 1. **Duraciones:** una resta de fechas devuelve `Duration`. Hay que acceder al campo numérico antes de operar: `(now() - file.mtime).days`, no `round(now() - file.mtime)`.
69
+ 2. **Nulls:** una propiedad ausente rompe la fórmula. Envolver en `if(propiedad, ...)`.
70
+ 3. **Referencias:** una `formula.x` usada en `order` pero no declarada en `formulas` falla en silencio, la columna no aparece.
71
+
72
+ ## Vistas
73
+
74
+ ```yaml
75
+ views:
76
+ - type: table
77
+ name: "My table"
78
+ limit: 10
79
+ groupBy:
80
+ property: note.age
81
+ direction: DESC
82
+ filters:
83
+ and:
84
+ - 'status != "done"'
85
+ - or:
86
+ - "formula.ppu > 5"
87
+ - "price > 2.1"
88
+ order:
89
+ - file.name
90
+ - note.age
91
+ - formula.ppu
92
+ summaries:
93
+ formula.ppu: Average
94
+ ```
95
+
96
+ Claves de una vista: `type`, `name`, `limit`, `groupBy`, `filters`, `order`, `summaries`.
97
+
98
+ Tipos: `table` (columnas), `cards` (galería), `list` (lista simple), `map` (geográfico).
99
+
100
+ ## Summaries por default
101
+
102
+ - Numéricos: Average, Min, Max, Sum, Range, Median, Stddev
103
+ - Fechas: Earliest, Latest
104
+ - Booleanos: Checked, Unchecked
105
+ - Cualquier tipo: Empty, Filled, Unique
106
+
107
+ Propios:
108
+
109
+ ```yaml
110
+ summaries:
111
+ customAverage: 'values.mean().round(3)'
112
+ ```
113
+
114
+ ## Quoting de YAML
115
+
116
+ Cualquier expresión que contenga `:`, `{`, `}`, `[`, `]` va entre comillas. Si la expresión tiene comillas dobles adentro, el string va entre comillas simples:
117
+
118
+ ```yaml
119
+ formulas:
120
+ label: 'if(done, "Yes", "No")'
121
+ ```
122
+
123
+ Es la causa número uno de un `.base` que no carga.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: obsidian-canvas
3
+ description: "Crea y edita archivos .canvas (JSON Canvas): nodos de nota, texto, archivo y link, grupos y edges con direccion y color. Triggers: obsidian canvas, json canvas, mapa visual, diagrama de notas, archivo .canvas, pizarra obsidian."
4
+ argument-hint: "[create <descripcion> | explain <archivo.canvas> | edit <archivo.canvas>]"
5
+ category: "pkm"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Write, Edit
8
+ ---
9
+
10
+ # Obsidian Canvas - JSON Canvas
11
+
12
+ Un `.canvas` es JSON plano con dos arrays: `nodes` y `edges`. El formato es JSON Canvas, un spec abierto, así que el archivo se puede generar y leer sin Obsidian. Adaptado de `kepano/obsidian-skills` al formato de este repo.
13
+
14
+ Modo: `$ARGUMENTS`
15
+
16
+ ## Modos
17
+
18
+ - **`create`**: generar un canvas nuevo desde una descripción o desde un conjunto de notas del vault.
19
+ - **`explain`**: leer un canvas y describir su estructura en texto. Read-only.
20
+ - **`edit`**: agregar o reacomodar nodos de un canvas existente. Pedí approval antes de escribir, y avisá que un canvas abierto en Obsidian sobrescribe el archivo al guardar: hay que cerrarlo antes.
21
+
22
+ ## Estructura
23
+
24
+ ```json
25
+ {
26
+ "nodes": [
27
+ {
28
+ "id": "n1",
29
+ "type": "file",
30
+ "file": "03_Resources/Indices parciales.md",
31
+ "x": 0, "y": 0, "width": 400, "height": 300
32
+ },
33
+ {
34
+ "id": "n2",
35
+ "type": "text",
36
+ "text": "Hipotesis: el costo esta en las lecturas",
37
+ "x": 480, "y": 0, "width": 300, "height": 120,
38
+ "color": "4"
39
+ },
40
+ {
41
+ "id": "g1",
42
+ "type": "group",
43
+ "label": "Investigacion",
44
+ "x": -40, "y": -60, "width": 900, "height": 440
45
+ }
46
+ ],
47
+ "edges": [
48
+ {
49
+ "id": "e1",
50
+ "fromNode": "n1", "fromSide": "right",
51
+ "toNode": "n2", "toSide": "left",
52
+ "label": "sugiere"
53
+ }
54
+ ]
55
+ }
56
+ ```
57
+
58
+ **Nodos.** Campos obligatorios: `id`, `type`, `x`, `y`, `width`, `height`. Tipos:
59
+
60
+ | `type` | Campo propio |
61
+ |---|---|
62
+ | `text` | `text` (markdown) |
63
+ | `file` | `file` (ruta en el vault), `subpath` opcional para un heading o bloque |
64
+ | `link` | `url` |
65
+ | `group` | `label`, `background`, `backgroundStyle` opcionales |
66
+
67
+ **Edges.** Obligatorio `id`, `fromNode`, `toNode`. Opcionales: `fromSide` y `toSide` (`top`, `right`, `bottom`, `left`), `fromEnd`/`toEnd` (`none`, `arrow`), `label`, `color`.
68
+
69
+ **Color.** Un preset `"1"` a `"6"` (rojo, naranja, amarillo, verde, cyan, violeta) o un hex `"#ff0000"`.
70
+
71
+ **Coordenadas.** El eje Y crece hacia abajo. Un grupo no contiene nodos por referencia: los contiene **geométricamente**, por solaparse con su rectángulo. Si movés un nodo fuera del rectángulo, sale del grupo.
72
+
73
+ ## Reglas para generar uno usable
74
+
75
+ - **Los `id` tienen que ser únicos.** Si se repiten, Obsidian se queda con uno solo y el resto desaparece sin error.
76
+ - **Layout en grilla, no apilado en el origen.** Separar los nodos al menos 60px: un canvas con todo en `x: 0, y: 0` se abre como una pila ilegible y reacomodarlo a mano cuesta más que generarlo de nuevo.
77
+ - **Verificar que cada `file` exista** antes de escribir el canvas: un nodo que apunta a una nota inexistente renderiza vacío.
78
+ - Un canvas es para pensar visualmente, no para almacenar conocimiento. Lo que se aprende en un canvas se escribe después como nota atómica.
79
+
80
+ Canvas READY cuando el JSON es válido, los ids son únicos, las rutas existen y el usuario confirmó que abre bien en Obsidian.
81
+
82
+ ## Reglas
83
+
84
+ - No inventar campos que el spec no define: Obsidian los ignora y ensucia el archivo.
85
+ - No reescribir un canvas entero para agregar un nodo: `Edit` sobre el array.
86
+ - Pedí approval antes de escribir o sobrescribir un `.canvas`, y verificá que no esté abierto en Obsidian.
87
+ - Sin guiones largos en labels ni en nodos de texto.
88
+
89
+ ## Handoff
90
+
91
+ Si lo que hacía falta era una vista tabular y no un mapa visual, el skill correcto es `/obsidian-bases`. Cuando el canvas dejó una conclusión, el siguiente paso es `/zettel` para escribirla como nota atómica: el canvas es el andamio, la nota es lo que queda.
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: obsidian-markdown
3
+ description: "Sintaxis de Obsidian Flavored Markdown: wikilinks, embeds, callouts, block IDs, propiedades, tags, highlights, math y mermaid. Valida o corrige una nota. Triggers: sintaxis obsidian, wikilink, callout, embed, block id, obsidian markdown, esto renderiza bien en obsidian, frontmatter obsidian."
4
+ argument-hint: "[reference | check <archivo> | fix <archivo>]"
5
+ category: "pkm"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Write, Edit
8
+ ---
9
+
10
+ # Obsidian Markdown - Sintaxis nativa
11
+
12
+ Obsidian extiende CommonMark y GFM. Este skill cubre **solo las extensiones propias de Obsidian**: el markdown estándar (títulos, negrita, listas, tablas, código) se da por sabido. Adaptado de `kepano/obsidian-skills` al formato de este repo.
13
+
14
+ Modo y archivo: `$ARGUMENTS`
15
+
16
+ ## Modos
17
+
18
+ - **`reference`** (default): responder la duda de sintaxis con la tabla de abajo, sin tocar archivos.
19
+ - **`check <archivo>`**: leer la nota y reportar qué no va a renderizar. Read-only.
20
+ - **`fix <archivo>`**: corregir lo que `check` encontró. Pedí approval antes de escribir, mostrando el diff propuesto.
21
+
22
+ ## Links y embeds
23
+
24
+ ```markdown
25
+ [[Nota]] link interno
26
+ [[Nota|Texto visible]] alias
27
+ [[Nota#Titulo]] link a un heading
28
+ [[Nota#^block-id]] link a un bloque
29
+ [[#Titulo en esta nota]] link interno a la misma nota
30
+
31
+ ![[Nota]] embed de la nota completa
32
+ ![[Nota#Titulo]] embed de una seccion
33
+ ![[imagen.png|300]] embed con ancho
34
+ ![[doc.pdf#page=3]] embed de una pagina de PDF
35
+ ```
36
+
37
+ Un block ID se define agregando `^mi-id` al final del párrafo. En listas y citas va en una línea aparte después del bloque.
38
+
39
+ **`[[wikilinks]]` para lo interno, `[texto](url)` solo para URLs externas.** No es estilo: Obsidian actualiza los wikilinks cuando renombrás una nota dentro de la app, y no toca los markdown links.
40
+
41
+ ## Callouts
42
+
43
+ ```markdown
44
+ > [!note]
45
+ > Callout basico.
46
+
47
+ > [!warning] Titulo propio
48
+ > Con titulo custom.
49
+
50
+ > [!faq]- Colapsado por default
51
+ > El `-` lo colapsa, el `+` lo abre.
52
+ ```
53
+
54
+ Tipos: `note`, `tip`, `info`, `warning`, `danger`, `bug`, `example`, `quote`, `success`, `failure`, `question`, `abstract`, `todo`. Un tipo inventado renderiza como `note` sin avisar, y ese es el error de callout más común.
55
+
56
+ ## Propiedades (frontmatter)
57
+
58
+ ```yaml
59
+ ---
60
+ title: Mi nota
61
+ date: 2026-07-27
62
+ tags:
63
+ - proyecto
64
+ - activo
65
+ aliases:
66
+ - Nombre alternativo
67
+ cssclasses:
68
+ - custom
69
+ ---
70
+ ```
71
+
72
+ `tags`, `aliases` y `cssclasses` son las tres propiedades que Obsidian entiende de forma nativa. El resto son campos propios y los consume Bases o Dataview.
73
+
74
+ ## Resto de la sintaxis propia
75
+
76
+ ```markdown
77
+ #tag #anidado/tag tags inline (no pueden empezar con numero)
78
+ ==resaltado== highlight
79
+ %%comentario%% invisible en lectura
80
+ $e^{i\pi}+1=0$ y $$...$$ math LaTeX inline y en bloque
81
+ texto[^1] / ^[nota inline] footnotes
82
+ ```
83
+
84
+ Los bloques ` ```mermaid ` renderizan diagramas nativamente.
85
+
86
+ ## Qué revisa `check`
87
+
88
+ | Check | Qué busca | Verdict |
89
+ |---|---|---|
90
+ | Tipo de callout | `> [!tipo]` con un tipo que no existe | FAIL: renderiza como `note` |
91
+ | Links externos como wikilink | `[[https://...]]` | FAIL: no resuelve |
92
+ | Links internos como markdown | `[texto](Nota.md)` dentro del vault | CONCERNS: se rompe al renombrar |
93
+ | Frontmatter | Abre con `---` en la primera línea y cierra | FAIL si no cierra: Obsidian lo muestra como texto |
94
+ | `tags` con `#` en frontmatter | `tags: [#foo]` | CONCERNS: el `#` no va en frontmatter |
95
+ | Block IDs | Duplicados en la misma nota | FAIL: el link resuelve al primero |
96
+ | Embeds de imagen | Ancho no numérico (`![[img.png|grande]]`) | CONCERNS: se ignora |
97
+ | Espacios en `[[ Nota ]]` | Espacios internos al principio o final del target | CONCERNS: puede no resolver |
98
+
99
+ Nota COMPLIANT cuando ninguna de estas falla.
100
+
101
+ ## Reglas
102
+
103
+ - No reformatear la nota entera cuando el pedido es arreglar un detalle: `Edit` sobre citas textuales, no `Write` del archivo completo.
104
+ - No convertir markdown links externos a wikilinks: los externos van como markdown link.
105
+ - No inventar tipos de callout ni propiedades que Obsidian no reconoce.
106
+ - Sin guiones largos en lo que agregues.
107
+
108
+ ## Handoff
109
+
110
+ Si la duda era de vistas agregadas y no de sintaxis de nota, el skill correcto es `/obsidian-bases`; si era de un canvas, `/obsidian-canvas`. Cuando la nota queda COMPLIANT, seguí con el flujo que la produjo (`/zettel`, `/review-dump` o `/vault-clip`).
@@ -12,6 +12,8 @@ allowed values (for checkboxes / dropdowns), and page number.
12
12
  Exit codes: 0 success, 1 bad args / file not found, 2 dep missing, 3 read error
13
13
  """
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import argparse
16
18
  import json
17
19
  import sys
@@ -27,6 +27,8 @@ Block types:
27
27
  Exit codes: 0 success, 1 bad args/missing file, 2 missing dep, 3 render error
28
28
  """
29
29
 
30
+ from __future__ import annotations
31
+
30
32
  import argparse
31
33
  import io
32
34
  import json
@@ -7,7 +7,7 @@ user-invocable: true
7
7
  allowed-tools: Read, Glob, Grep, Write, Edit
8
8
  ---
9
9
 
10
- # Personal Brand — Autoridad en LinkedIn para la búsqueda
10
+ # Personal Brand - Autoridad en LinkedIn para la búsqueda
11
11
 
12
12
  Construís una marca personal en LinkedIn orientada a conseguir trabajo: un backlog **secuenciado** de ideas de post (ritmo 1/día) que construye autoridad y credibilidad *antes* de salir a hacer outreach, de modo que cuando escribas a un recruiter ya tengan contexto de quién sos.
13
13
 
@@ -15,25 +15,25 @@ Trabajás contra el **perfil maestro** (`01-Perfiles/`) y el rol/empresas objeti
15
15
 
16
16
  ## Los 4 pilares
17
17
 
18
- 1. **Builder credibility** — qué construiste/entregaste, con resultados. Demuestra que hacés, no solo que sabés.
19
- 2. **Lessons from current role** — aprendizajes concretos del trabajo actual/reciente (técnicos y de proceso).
20
- 3. **POVs on your domain** — opiniones/tendencias de tu dominio. Te posiciona como alguien que piensa, no solo ejecuta.
21
- 4. **Behind-the-scenes of the job search** — el viaje de la búsqueda (en su justa medida): genera cercanía y a veces atrae oportunidades directas.
18
+ 1. **Builder credibility** - qué construiste/entregaste, con resultados. Demuestra que hacés, no solo que sabés.
19
+ 2. **Lessons from current role** - aprendizajes concretos del trabajo actual/reciente (técnicos y de proceso).
20
+ 3. **POVs on your domain** - opiniones/tendencias de tu dominio. Te posiciona como alguien que piensa, no solo ejecuta.
21
+ 4. **Behind-the-scenes of the job search** - el viaje de la búsqueda (en su justa medida): genera cercanía y a veces atrae oportunidades directas.
22
22
 
23
23
  Ver `references/post-pillars.md` para ángulos, hooks y formatos por pilar.
24
24
 
25
25
  ## Modos
26
26
 
27
- ### `plan` — Backlog de 90 ideas secuenciadas
27
+ ### `plan` - Backlog de 90 ideas secuenciadas
28
28
  1. Confirmar rol objetivo, empresas y los temas donde el usuario tiene autoridad real (del perfil maestro).
29
29
  2. Generar **90 ideas** repartidas en los 4 pilares. Cada idea = **hook + ángulo + formato** (texto, carrusel, lista, story, hot-take).
30
- 3. **Secuenciar**: los primeros ~30 días priorizan pilares 1–3 (construir autoridad); recién después meter más del pilar 4 y empujar el outreach. La autoridad va antes que el pedido.
30
+ 3. **Secuenciar**: los primeros ~30 días priorizan pilares 1-3 (construir autoridad); recién después meter más del pilar 4 y empujar el outreach. La autoridad va antes que el pedido.
31
31
  4. Entregar como tabla/calendario (día → idea → pilar → formato).
32
32
 
33
- ### `ideas <N>` — Lote de N ideas
33
+ ### `ideas <N>` - Lote de N ideas
34
34
  Generar N ideas frescas para un pilar o tema puntual, mismo formato hook+ángulo+formato.
35
35
 
36
- ### `draft <idea>` — Escribir un post
36
+ ### `draft <idea>` - Escribir un post
37
37
  Convertir una idea en un post listo para publicar: hook fuerte en la primera línea, cuerpo escaneable, CTA o pregunta de cierre. Tono humano, sin clichés de LinkedIn ("I'm humbled to announce…").
38
38
 
39
39
  ## Principios
@@ -43,7 +43,7 @@ Convertir una idea en un post listo para publicar: hook fuerte en la primera lí
43
43
  - **Una idea por post.** Foco.
44
44
  - **Consistencia > perfección.** El plan asume ritmo sostenible; mejor 1/día simple que 1/semana elaborado.
45
45
  - **Autoridad antes que pedido.** No arranques pidiendo trabajo; primero aportá valor.
46
- - **Verdad.** Nada de logros inflados — la audiencia y los recruiters lo notan.
46
+ - **Verdad.** Nada de logros inflados - la audiencia y los recruiters lo notan.
47
47
 
48
48
  ## Idioma
49
49