<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miller Correa</title>
    <description>The latest articles on DEV Community by Miller Correa (@macorreag).</description>
    <link>https://dev.to/macorreag</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F460698%2Fd9ff4683-d432-44c1-a7e2-7658995dee9b.jpeg</url>
      <title>DEV Community: Miller Correa</title>
      <link>https://dev.to/macorreag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/macorreag"/>
    <language>en</language>
    <item>
      <title>DeepSeek Harness: el harness abierto que hace lo que Claude Code no te deja tocar</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Wed, 02 Sep 2026 01:19:18 +0000</pubDate>
      <link>https://dev.to/macorreag/deepseek-harness-el-harness-abierto-que-hace-lo-que-claude-code-no-te-deja-tocar-2df4</link>
      <guid>https://dev.to/macorreag/deepseek-harness-el-harness-abierto-que-hace-lo-que-claude-code-no-te-deja-tocar-2df4</guid>
      <description>&lt;p&gt;Los agentes de código son todavía una tecnología relativamente nueva. Y aun así, casi todos venimos de la misma experiencia: abres Claude Code (o cualquier otro), le pides algo, y en el momento en que algo sale mal… estás mirando una caja negra.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Por qué falló?&lt;/li&gt;
&lt;li&gt;¿Fue el tool? ¿Fue el modelo? ¿Fue tu prompt?&lt;/li&gt;
&lt;li&gt;¿En qué &lt;em&gt;turno exacto&lt;/em&gt; se torció todo?&lt;/li&gt;
&lt;li&gt;¿Y por qué no puedo cambiarle ni el color a esta interfaz?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si alguna vez te hiciste esas preguntas, este post es para ti. Porque &lt;strong&gt;DeepSeek Harness&lt;/strong&gt; responde las cuatro — y la última de una forma que va a cambiar cómo piensas lo que un "harness de agentes" puede ser.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spoiler: no es "otro Claude Code". Es otra categoría. Y es &lt;strong&gt;open source&lt;/strong&gt; (MIT).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Qué es DeepSeek Harness
&lt;/h2&gt;

&lt;p&gt;DeepSeek Harness (&lt;code&gt;dsh&lt;/code&gt;) es un &lt;strong&gt;harness de agentes basado en plugins&lt;/strong&gt;. No es una app monolítica: es un runtime sobre &lt;strong&gt;Cordis&lt;/strong&gt;, un framework de plugins, donde &lt;em&gt;absolutamente todo&lt;/em&gt; es un plugin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;las &lt;strong&gt;tools&lt;/strong&gt; (bash, filesystem, search, web, ask-user, skills…)&lt;/li&gt;
&lt;li&gt;el &lt;strong&gt;loop del agente&lt;/strong&gt; y el sistema de &lt;strong&gt;goals&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;el &lt;strong&gt;sandbox&lt;/strong&gt; y la política de permisos&lt;/li&gt;
&lt;li&gt;la &lt;strong&gt;UI del navegador&lt;/strong&gt; (tema, layout, sidebar, renderer, marca)&lt;/li&gt;
&lt;li&gt;la &lt;strong&gt;orquestación&lt;/strong&gt; (workflows, subagentes, Ralph)&lt;/li&gt;
&lt;li&gt;hasta el &lt;strong&gt;medidor de tokens&lt;/strong&gt; y la &lt;strong&gt;compactación de contexto&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se arranca igual de fácil que cualquier CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dsh web                            &lt;span class="c"&gt;# interfaz web completa&lt;/span&gt;
dsh &lt;span class="nt"&gt;--profile&lt;/span&gt; headless &lt;span class="s2"&gt;"corre los tests"&lt;/span&gt;   &lt;span class="c"&gt;# one-shot, headless&lt;/span&gt;
dsh &lt;span class="nt"&gt;--profile&lt;/span&gt; &amp;lt;mi-perfil&amp;gt;          &lt;span class="c"&gt;# tu propio perfil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo importante no es &lt;em&gt;cómo se arranca&lt;/em&gt;, sino lo que esa arquitectura te permite hacer. Vamos a ello.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Observabilidad: sabes &lt;strong&gt;exactamente&lt;/strong&gt; dónde falló (tool, modelo o usuario)
&lt;/h2&gt;

&lt;p&gt;Esta es, para mí, la killer feature. Y la razón por la que lo llamo "disruptivo" sin exagerar.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness tiene una vista llamada &lt;strong&gt;Trajectory&lt;/strong&gt;: un &lt;em&gt;ledger&lt;/em&gt; de eventos por turno donde puedes seleccionar registros de &lt;strong&gt;User&lt;/strong&gt;, &lt;strong&gt;Assistant&lt;/strong&gt;, &lt;strong&gt;Tool&lt;/strong&gt; y &lt;strong&gt;Subtool&lt;/strong&gt; anidados. Por cada evento ves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;timing real&lt;/strong&gt;: cuánto fue &lt;em&gt;TTFT&lt;/em&gt; (time-to-first-token) y cuánto fue &lt;em&gt;decoding&lt;/em&gt; (con hover para el reloj exacto)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tokens consumidos&lt;/strong&gt; por evento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;input / output&lt;/strong&gt; completo de cada tool call&lt;/li&gt;
&lt;li&gt;las &lt;strong&gt;fronteras de turno&lt;/strong&gt; y de &lt;em&gt;step&lt;/em&gt; bien marcadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traducción práctica: cuando un run se descarrila, no adivinas. &lt;strong&gt;Sigues la traza&lt;/strong&gt; y ves si el problema fue un tool que devolvió basura, un turno del modelo que alucinó, o tu prompt que estaba mal formulado. La responsabilidad queda &lt;em&gt;atribuida&lt;/em&gt;, no diluida.&lt;/p&gt;

&lt;p&gt;Y esto no es solo cosmética: los errores son &lt;strong&gt;estructurados y legibles&lt;/strong&gt;. Cuando algo se bloquea, el harness no te suelta un stderr críptico. Te dice exactamente qué pasó:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[exit code: 1]
[sandbox: file access denied under workspace-write mode]
[status: running]  →  [status: complete]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese último patrón es clave para lo que viene. Porque una denegación no es un muro: es &lt;strong&gt;información accionable&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Hardened de verdad: sandbox duro, y aun así no te frena
&lt;/h2&gt;

&lt;p&gt;Aquí es donde mucha gente se equivoca con los agentes. Piensan que "seguro" significa "capado". DeepSeek Harness demuestra lo contrario.&lt;/p&gt;

&lt;p&gt;Puedes &lt;strong&gt;endurecerlo&lt;/strong&gt; tanto como quieras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox por modos&lt;/strong&gt;, en cada call: &lt;code&gt;read-only&lt;/code&gt;, &lt;code&gt;workspace-write&lt;/code&gt; y &lt;code&gt;danger-full-access&lt;/code&gt;. El agente arranca confinado al workspace y a los directorios temporales, y &lt;em&gt;nada&lt;/em&gt; más.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox de bash a nivel kernel&lt;/strong&gt; (Seatbelt / Landlock), no solo una validación en el proceso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Política de aprobación &lt;code&gt;ask&lt;/code&gt;&lt;/strong&gt;: los permisos sensibles piden confirmación humana, con &lt;em&gt;presets&lt;/em&gt; de permisos configurables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills limitantes&lt;/strong&gt;: instrucciones reutilizables que puedes cargar para acotar el comportamiento del agente (sus reglas, sus límites, su "personalidad" operativa).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo brutal es que, &lt;strong&gt;dentro de ese régimen endurecido, el agente sigue logrando las cosas&lt;/strong&gt;. ¿Por qué? Porque la denegación es &lt;em&gt;legible y recuperable&lt;/em&gt;: el agente ve el marcador &lt;code&gt;[sandbox: file access denied under workspace-write mode]&lt;/code&gt;, entiende exactamente qué pidió y qué se le negó, y pide &lt;em&gt;un único&lt;/em&gt; reintento con el modo más amplio justo y necesario — no abre la compuerta entera.&lt;/p&gt;

&lt;p&gt;Es la diferencia entre "caja negra que a veces se atasca" y "sistema confinado que te explica qué necesita y por qué". Para una empresa, eso es &lt;strong&gt;auditabilidad&lt;/strong&gt;. Y la auditabilidad es lo que te deja dormir tranquilo.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Intervenir en el "look" del Agent (sí, de verdad)
&lt;/h2&gt;

&lt;p&gt;Esto es lo que Claude Code literalmente &lt;strong&gt;no te deja tocar&lt;/strong&gt;. La UI de DeepSeek Harness también es un conjunto de plugins (&lt;code&gt;client-ui-*&lt;/code&gt;): tema, layout, sidebar, renderer de mensajes, marca, ajustes, todo.&lt;/p&gt;

&lt;p&gt;¿Qué significa en la práctica?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Re-branding total&lt;/strong&gt;: ¿quieres que el agente se llame como tu producto y lleve tus colores? Se puede. Es un plugin de UI, no un "dark mode".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tematización y layout&lt;/strong&gt; a tu gusto, no al del vendor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMR en vivo del client-plugin&lt;/strong&gt;: editas el plugin de UI y el navegador se recarga &lt;strong&gt;sin refresh&lt;/strong&gt;. Cambias el look del agente mientras lo usas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Piénsalo en términos de producto: con Claude Code estás &lt;em&gt;dentro&lt;/em&gt; de la experiencia que Anthropic decidió darte. Con DeepSeek Harness, &lt;strong&gt;la experiencia es tuya&lt;/strong&gt;. Para una startup que quiere vender un agente embebido o una herramienta interna, esto no es un detalle: es la diferencia entre "usar una app" y "construir sobre una plataforma".&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Orquestación multiagente de primera clase (no es un afterthought)
&lt;/h2&gt;

&lt;p&gt;Otra cosa que aquí es &lt;em&gt;core&lt;/em&gt; y en otros sitios es un parche:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Goals&lt;/strong&gt;: un objetivo de larga duración &lt;em&gt;event-sourced&lt;/em&gt; que persiste en la sesión y permite que el agente &lt;strong&gt;continúe de forma autónoma&lt;/strong&gt; entre rondas (con un cap de rondas configurable). El estado se guarda como eventos en el log de sesión, así que es rejugable y auditable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow tool&lt;/strong&gt;: escribes un script JavaScript que &lt;strong&gt;fanea&lt;/strong&gt; el trabajo a decenas de subagentes, con fases y resultados estructurados. Orquestación real a escala.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ralph&lt;/strong&gt;: un loop de agentes &lt;em&gt;frescos&lt;/em&gt; (cada ronda abre un agente nuevo sin semilla de conversación, usando el workspace como memoria). Ideal para iteración que no quiere arrastrar sesgo de contexto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagentes&lt;/strong&gt; (&lt;code&gt;subagent&lt;/code&gt; y &lt;code&gt;subagent_fork&lt;/code&gt;): delegación con o sin herencia de contexto, en background, y con control (&lt;code&gt;send_message&lt;/code&gt;, &lt;code&gt;interrupt&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traducción: el &lt;em&gt;fan-out&lt;/em&gt;, la persistencia de objetivos y la iteración multiagente no son hacks. Son herramientas del propio harness.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Self-host: tus datos, tus reglas
&lt;/h2&gt;

&lt;p&gt;La agnosticidad de modelo no la voy a vender como novedad — Codex ya lo hacía —; aquí simplemente &lt;strong&gt;se mantiene&lt;/strong&gt;. Lo que sí vale la pena para una empresa es lo demás: lo corres &lt;strong&gt;self-host&lt;/strong&gt; (tus datos, tus llaves, tus logs) y controlas costes con &lt;strong&gt;medidor de tokens&lt;/strong&gt; y &lt;strong&gt;compactación&lt;/strong&gt; configurables.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Skills desatadas del proveedor: un plugin para gobernarlas a todas
&lt;/h2&gt;

&lt;p&gt;Hay una consecuencia del diseño por plugins que pocos notan, y para mí es de las más importantes: &lt;strong&gt;las skills hoy están secuestradas por cada proveedor&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Las &lt;strong&gt;Claude Skills&lt;/strong&gt; solo viven dentro de Claude Code.&lt;/li&gt;
&lt;li&gt;Las skills de &lt;strong&gt;Codex&lt;/strong&gt; solo viven dentro de Codex.&lt;/li&gt;
&lt;li&gt;¿Cambias de agente? Pierdes (o tienes que reescribir) toda tu librería de skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DeepSeek Harness tiene su propio sistema de skills (&lt;code&gt;dsh-skill&lt;/code&gt;), pero lo clave es que, como &lt;em&gt;todo&lt;/em&gt; es un plugin, &lt;strong&gt;puedes escribir un plugin que interprete los formatos de skills de otros proveedores&lt;/strong&gt; — Claude Skills, Codex, o los que vengan — y los exponga como skills nativas dentro del mismo harness.&lt;/p&gt;

&lt;p&gt;Traducción: tu inversión en skills deja de estar presa de un vendor. Un plugin, y tienes &lt;strong&gt;una sola&lt;/strong&gt; librería de skills, agnóstica de formato, corriendo sobre el modelo que tú elijas. Eso es algo &lt;em&gt;impensable&lt;/em&gt; en Claude Code o Codex: son productos cerrados, y ni siquiera tienen un punto de extensión donde enchufar un intérprete de skills ajeno.&lt;/p&gt;




&lt;h2&gt;
  
  
  La comparación (sin dramatismo)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;DeepSeek Harness&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arquitectura&lt;/td&gt;
&lt;td&gt;100% plugins (Cordis): tools, loop, UI, sandbox&lt;/td&gt;
&lt;td&gt;Monolito cerrado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modelo&lt;/td&gt;
&lt;td&gt;Agnóstico (se mantiene; Codex ya lo hacía)&lt;/td&gt;
&lt;td&gt;Atado a Claude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observabilidad&lt;/td&gt;
&lt;td&gt;Trajectory: User/Tool/Assistant/Subtool, timing TTFT vs decoding, tokens por evento&lt;/td&gt;
&lt;td&gt;Caja negra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI&lt;/td&gt;
&lt;td&gt;Plugins tematizables + re-branding + HMR en vivo&lt;/td&gt;
&lt;td&gt;Fija, no se toca&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sandbox&lt;/td&gt;
&lt;td&gt;Modos por call + bash a nivel kernel + approval &lt;code&gt;ask&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Limitado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orquestación&lt;/td&gt;
&lt;td&gt;Goals, Workflows, Ralph, subagentes&lt;/td&gt;
&lt;td&gt;Mínima&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensión&lt;/td&gt;
&lt;td&gt;Escribes tus propios plugins y perfiles&lt;/td&gt;
&lt;td&gt;No extensible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;Plugin compatible multi-formato (Claude, Codex, propios)&lt;/td&gt;
&lt;td&gt;Atadas a cada proveedor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;Self-host, auditable&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;La diferencia de fondo no es "tiene más features". Es una cuestión de &lt;strong&gt;filosofía&lt;/strong&gt;: Claude Code es un producto cerrado que &lt;em&gt;te deja usar&lt;/em&gt;. DeepSeek Harness es una plataforma abierta que &lt;em&gt;te deja construir&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Por qué es el mejor harness para compañías y startups
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auditable&lt;/strong&gt;: sabes qué tool falló, qué modelo se equivocó, qué pidió el usuario. La traza está ahí, atribuida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endurecible&lt;/strong&gt;: sandbox duro + approval, sin sacrificar productividad. Seguridad que no frena.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personalizable&lt;/strong&gt;: re-brandea la UI, escribe tus propios tools/skills/plugins. Tu producto, no el del vendor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composable&lt;/strong&gt;: orquestación multiagente como primitiva de primera clase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portable&lt;/strong&gt;: tus skills no quedan atadas a un proveedor; un plugin las unifica (Claude, Codex, propios).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlable&lt;/strong&gt;: self-host + medidor de tokens = dueño de tus costes y tus datos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para una startup, esto es la diferencia entre alquilar una herramienta y poseer una ventaja competitiva. Para una empresa, es la diferencia entre "adoptar una IA opaca" y "gobernar una IA auditada".&lt;/p&gt;




&lt;h2&gt;
  
  
  El punto
&lt;/h2&gt;

&lt;p&gt;DeepSeek Harness todavía está en release candidate (&lt;code&gt;0.1.x&lt;/code&gt;), y no te voy a vender que es perfecto. Pero su apuesta arquitectónica es la correcta: &lt;strong&gt;abierto, observable, endurecible y re-brandeable&lt;/strong&gt;. Es exactamente lo que un harness de agentes &lt;em&gt;debería&lt;/em&gt; ser en 2026, y lo que los productos cerrados no pueden —ni quieren— ofrecerte.&lt;/p&gt;

&lt;p&gt;Si estás construyendo algo con agentes, hazte una pregunta honesta: ¿quieres estar &lt;em&gt;dentro&lt;/em&gt; de la caja negra de otro, o quieres una caja que puedas abrir, auditar y hacer tuya?&lt;/p&gt;

&lt;p&gt;Yo ya elegí. 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;¿Has probado DeepSeek Harness? ¿O vienes de la frustración de no poder tocar tu agente actual? Cuéntamelo en los comentarios.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ia</category>
      <category>deepseek</category>
      <category>programacion</category>
      <category>devops</category>
    </item>
    <item>
      <title>¿Tu agente puede reescribir su propio plan? Ownership determinista con DeepSeek Harness</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Sun, 23 Aug 2026 03:43:46 +0000</pubDate>
      <link>https://dev.to/macorreag/tu-agente-puede-reescribir-su-propio-plan-ownership-determinista-con-deepseek-harness-3c7g</link>
      <guid>https://dev.to/macorreag/tu-agente-puede-reescribir-su-propio-plan-ownership-determinista-con-deepseek-harness-3c7g</guid>
      <description>&lt;p&gt;¿Alguna vez le pediste a un agente una tarea concreta y, a mitad de camino, cambió el plan en silencio — re-escribió sus propios objetivos, se salió del alcance, o te "confirmó" que había hecho algo que en realidad había descartado?&lt;/p&gt;

&lt;p&gt;En el &lt;a href="https://dev.to/macorreag/la-ia-esta-sobrescribiendo-tus-notas-tres-capas-de-ownership-para-proteger-tu-conocimiento-3e3l"&gt;post anterior sobre agnosticBrain&lt;/a&gt; hablamos del conocimiento: la IA sobrescribiendo notas que refinaste a mano. Aquí el problema es distinto pero espejo: &lt;strong&gt;el agente sobrescribiendo su propio plan de ejecución&lt;/strong&gt;. Y hoy por fin lo resolvemos de forma &lt;strong&gt;determinista&lt;/strong&gt;, no aspiracional, gracias a &lt;a href="https://github.com/deepseek-ai" rel="noopener noreferrer"&gt;DeepSeek Harness&lt;/a&gt; y a un plugin que construimos: &lt;a href="https://github.com/Macorreag/dsh-todo-hardened" rel="noopener noreferrer"&gt;&lt;code&gt;@macorreag/dsh-todo-hardened&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El contexto: la lista de tareas siempre fue del agente
&lt;/h2&gt;

&lt;p&gt;Todos los asistentes de código tienen algún mecanismo de tareas: &lt;code&gt;TodoWrite&lt;/code&gt; en Claude Code, las task lists de Codex y Cursor, los todos de OpenCode. Funcionan, pero comparten un defecto estructural: &lt;strong&gt;la lista es propiedad del agente&lt;/strong&gt;. El modelo la escribe, la edita y la completa como quiere, y la única barrera es un prompt que dice "mantén la lista actualizada".&lt;/p&gt;

&lt;p&gt;Eso no es una garantía, es una &lt;em&gt;sugerencia&lt;/em&gt;. Tres limitaciones que nos cansamos de sufrir:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Es disciplina de prompt, no enforcement.&lt;/strong&gt; Si el modelo deriva, re-encuadra el objetivo o se distrae, la lista lo acompaña. Nadie lo impide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No hay capa humana inviolable.&lt;/strong&gt; No existe un "esto lo decidió el humano y tú no lo tocas". Todo lo que el agente ve, el agente lo puede mutar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La "aprobación" no existe como mecanismo.&lt;/strong&gt; A lo sumo el agente te dice "¿te parece si hago X?" y luego él mismo reporta que lo hizo. La confirmación humana real, si existe, es externa y manual.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El resultado es un agente que se auto-gobierna su propio contrato. Y un contrato donde una de las partes puede reescribirlo unilateralmente &lt;strong&gt;no es un contrato&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El GAP: faltaba ownership para el &lt;em&gt;estado de ejecución&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;En agnosticBrain resolvimos esto para el conocimiento con una tercera capa: &lt;code&gt;curated/&lt;/code&gt;, inviolable para el LLM. El insight era simple y profundo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;El LLM propone. El humano decide. Nadie sobrescribe &lt;code&gt;curated/&lt;/code&gt; sin aprobación humana.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El GAP que quedaba abierto era llevar &lt;strong&gt;esa misma jerarquía al plan de trabajo del agente&lt;/strong&gt;. Porque un agente no solo lee y escribe notas: decide, prioriza, completa y descarta tareas. Y si su lista de tareas no tiene la misma protección que &lt;code&gt;curated/&lt;/code&gt;, entonces la parte más crítica de la ejecución — &lt;strong&gt;qué se decidió hacer&lt;/strong&gt; — sigue siendo maleable.&lt;/p&gt;

&lt;h2&gt;
  
  
  La solución: &lt;code&gt;dsh-todo-hardened&lt;/code&gt;, ownership para el todo-list
&lt;/h2&gt;

&lt;p&gt;Construimos un plugin para DeepSeek Harness que replica el patrón de agnosticBrain, pero sobre la lista de tareas del agente. Tres capas de ownership:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capa&lt;/th&gt;
&lt;th&gt;Dueño&lt;/th&gt;
&lt;th&gt;Quién muta&lt;/th&gt;
&lt;th&gt;Regla crítica&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;active/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agente&lt;/td&gt;
&lt;td&gt;Agente (CRUD + finalizar) y humano&lt;/td&gt;
&lt;td&gt;Trabajo en curso&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;locked/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Humano&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Solo humano&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inviolable para el agente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;archive/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sistema&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nadie&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Append-only: solo se entra&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;La clave es &lt;code&gt;locked/&lt;/code&gt;: cuando un humano &lt;strong&gt;cura&lt;/strong&gt; una tarea (la bloquea), el agente no puede modificarla. Punto. Y esto no es una regla escrita en un prompt — es una &lt;strong&gt;FSM de estados + validación de schema + ownership&lt;/strong&gt; que corre como &lt;em&gt;gate mecánico&lt;/em&gt; antes de &lt;em&gt;cada&lt;/em&gt; mutación.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Las reglas no son disciplina de prompt; se aplican mecánicamente en el plugin, igual que &lt;code&gt;curated/&lt;/code&gt; en agnosticBrain.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si el agente quiere cambiar una tarea bloqueada, no la toca: &lt;strong&gt;propone&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  El flujo: proponer, no imponer
&lt;/h2&gt;

&lt;p&gt;Cuando el agente necesita modificar algo que está en &lt;code&gt;locked/&lt;/code&gt;, la única vía es una propuesta:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;El agente crea una propuesta (&lt;code&gt;todo_propose&lt;/code&gt;) sobre la tarea bloqueada: &lt;code&gt;kind=update | complete | cancel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;La propuesta queda en estado &lt;code&gt;open&lt;/code&gt; — &lt;strong&gt;no aplica nada&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;El humano la aprueba (&lt;code&gt;todo_approve&lt;/code&gt;) o la rechaza (&lt;code&gt;todo_reject&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Solo la aprobación humana aplica el cambio sobre &lt;code&gt;locked/&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Y aquí está lo que "otros nos limitaban": la aprobación es &lt;strong&gt;real&lt;/strong&gt;. No es el agente preguntando y auto-respondiéndose. Las acciones humanas (&lt;code&gt;todo_lock&lt;/code&gt;, &lt;code&gt;todo_unlock&lt;/code&gt;, &lt;code&gt;todo_approve&lt;/code&gt;, &lt;code&gt;todo_reject&lt;/code&gt;) pasan por el &lt;em&gt;approval seam&lt;/em&gt; del harness (&lt;code&gt;ctx.approval.request&lt;/code&gt;), que muestra una &lt;strong&gt;UI de confirmación&lt;/strong&gt; y concede &lt;code&gt;allowed-once&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdlkycsy0gizmt4w048d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdlkycsy0gizmt4w048d1.png" alt=" " width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sin canal de aprobación disponible, la acción falla cerrada.&lt;/strong&gt; Un subagente no puede autorizarlas. Nadie aprueba por delegación.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Un rastro real, no un diagrama
&lt;/h2&gt;

&lt;p&gt;Esto no es un whiteboard. Es el log append-only del plugin corriendo en una sesión real (cada operación registra su &lt;code&gt;actor&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent  | add        t-… → active
human  | lock       t-… → locked
agent  | propose    p-… target=t-… kind=update
human  | approve    p-… → aplica el cambio
agent  | propose    p-… target=t-… kind=complete
human  | reject     p-… → no se aplica
agent  | propose    p-… target=t-… kind=update
human  | approve    p-… → aplica
human  | unlock     t-… → active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El agente intentó completar la tarea; el humano lo rechazó; el agente reformuló la propuesta; el humano la aprobó. Todo quedó registrado, con actor y timestamp, en un &lt;code&gt;log.md&lt;/code&gt; que es append-only. &lt;strong&gt;El agente puede intentar cualquier cosa, pero no puede modificar &lt;code&gt;locked/&lt;/code&gt; sin que quede un rastro y sin que un humano abra la puerta.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué esto era imposible antes de DeepSeek Harness
&lt;/h2&gt;

&lt;p&gt;El patrón no es nuevo: la idea de "humano decide, agente propone" ya la teníamos en agnosticBrain. Lo nuevo es que DSH &lt;strong&gt;expone los primitivos necesarios para hacerlo mecánico&lt;/strong&gt;, en vez de dejarlo a la buena fe del modelo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sistema de plugins (Cordis)&lt;/strong&gt; donde un paquete puede registrar &lt;em&gt;tools&lt;/em&gt; &lt;strong&gt;y&lt;/strong&gt; instalar un &lt;em&gt;hook&lt;/em&gt; &lt;code&gt;tools.guard&lt;/code&gt; que rechaza &lt;code&gt;write&lt;/code&gt;/&lt;code&gt;edit&lt;/code&gt;/&lt;code&gt;bash&lt;/code&gt; directos sobre &lt;code&gt;todo/&lt;/code&gt;. La única vía de escritura son las tools &lt;code&gt;todo_*&lt;/code&gt; (que están gated) o el panel humano.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Un approval seam de verdad&lt;/strong&gt; (&lt;code&gt;ctx.approval.request&lt;/code&gt;) con UI, &lt;code&gt;allowed-once&lt;/code&gt; y &lt;em&gt;fail-closed&lt;/em&gt;. No es "el modelo dice que aprobó": es el harness el que pide y registra la confirmación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Política de sandbox por sesión&lt;/strong&gt;, de modo que cada sesión escribe en su propio &lt;code&gt;&amp;lt;workspace&amp;gt;/todo/&lt;/code&gt; — resuelto por ejecución, no con un cwd global frágil.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En otros harnesses, para lograr esto tendrías que &lt;em&gt;reimplementar&lt;/em&gt; el seam de aprobación y el guard a mano, y aún así no tendrías dónde anclarlos de forma durable. Aquí es un plugin npm que se declara en una composición y &lt;strong&gt;sobrevive a reinicios&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  La conexión con agnosticBrain
&lt;/h2&gt;

&lt;p&gt;Lo lindo es que no inventamos una filosofía nueva: es la misma, aplicada a otro dominio.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dominio&lt;/th&gt;
&lt;th&gt;agnosticBrain&lt;/th&gt;
&lt;th&gt;dsh-todo-hardened&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qué protege&lt;/td&gt;
&lt;td&gt;Conocimiento refinado a mano&lt;/td&gt;
&lt;td&gt;El plan/estado de ejecución&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capa inviolable&lt;/td&gt;
&lt;td&gt;&lt;code&gt;curated/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;locked/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mecanismo&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/propose&lt;/code&gt; → aprobación&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;todo_propose&lt;/code&gt; → aprobación&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Garantía&lt;/td&gt;
&lt;td&gt;El LLM nunca sobrescribe&lt;/td&gt;
&lt;td&gt;El agente nunca muta sin humano&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Antes protegíamos lo que &lt;em&gt;sabes&lt;/em&gt;. Ahora protegemos lo que &lt;em&gt;decidiste que se haga&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;Los agentes son poderosos, pero un agente que es dueño absoluto de su propia lista de tareas es un agente que puede re-negociar el contrato contigo a espaldas tuyas. Con DeepSeek Harness y &lt;code&gt;dsh-todo-hardened&lt;/code&gt;, por fin convertimos el "debería respetar el plan" en "&lt;strong&gt;no puede&lt;/strong&gt; modificarlo sin que tú lo apruebes".&lt;/p&gt;

&lt;p&gt;El agente propone. El humano decide. Y ahora, de verdad, es imposible lo contrario.&lt;/p&gt;

&lt;p&gt;Si quieres verlo: el plugin está en &lt;a href="https://github.com/Macorreag/dsh-todo-hardened" rel="noopener noreferrer"&gt;github.com/Macorreag/dsh-todo-hardened&lt;/a&gt; (npm &lt;code&gt;@macorreag/dsh-todo-hardened&lt;/code&gt;, MIT), y la filosofía que hereda, en &lt;a href="https://github.com/Macorreag/agnosticBrain" rel="noopener noreferrer"&gt;github.com/Macorreag/agnosticBrain&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿alguna vez un agente te reescribió el plan a mitad de una tarea, lo detectaste?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ia</category>
      <category>deepseek</category>
      <category>agentes</category>
      <category>productividad</category>
    </item>
    <item>
      <title>¿La IA está sobrescribiendo tus notas? Tres capas de ownership para proteger tu conocimiento</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Sat, 22 Aug 2026 00:46:19 +0000</pubDate>
      <link>https://dev.to/macorreag/la-ia-esta-sobrescribiendo-tus-notas-tres-capas-de-ownership-para-proteger-tu-conocimiento-3e3l</link>
      <guid>https://dev.to/macorreag/la-ia-esta-sobrescribiendo-tus-notas-tres-capas-de-ownership-para-proteger-tu-conocimiento-3e3l</guid>
      <description>&lt;p&gt;¿Alguna vez refinaste una nota durante horas — redactando, puliendo, dándole estructura — y un &lt;code&gt;ingest&lt;/code&gt; posterior la sobrescribió silenciosamente, como si tus horas nunca hubieran existido?&lt;/p&gt;

&lt;p&gt;Si usas LLMs para mantener una base de conocimiento, probablemente ya sentiste ese dolor: la IA genera contenido excelente, pero cuando tú lo mejoras a mano, no siempre respeta tus ediciones. Este artículo te muestra cómo resolvimos ese problema en &lt;a href="https://github.com/Macorreag/agnosticBrain" rel="noopener noreferrer"&gt;agnosticBrain&lt;/a&gt;, un vault de conocimiento basado en el patrón &lt;strong&gt;LLM Wiki&lt;/strong&gt; de Andrej Karpathy, al que agregamos &lt;strong&gt;tres capas de ownership&lt;/strong&gt; en lugar de las dos originales.&lt;/p&gt;

&lt;h2&gt;
  
  
  El contexto: LLM Wiki, la propuesta de Karpathy
&lt;/h2&gt;

&lt;p&gt;En abril de 2026, Andrej Karpathy publicó su &lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f" rel="noopener noreferrer"&gt;gist sobre LLM Wiki&lt;/a&gt;, una idea elegante para bases de conocimiento personales:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The wiki is a persistent, compounding artifact. The cross-references are already there. The contradictions have already been flagged. The synthesis already reflects everything you've read.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La idea: en lugar de RAG clásico (recuperar fragmentos crudos en cada consulta), el LLM &lt;strong&gt;compila y mantiene una wiki persistente&lt;/strong&gt; — un conjunto de notas markdown interconectadas que vive entre tú y tus fuentes. Obsidian es el IDE, el LLM es el programador, y la wiki es el código.&lt;/p&gt;

&lt;p&gt;La arquitectura tiene &lt;strong&gt;dos capas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;raw/&lt;/code&gt;&lt;/strong&gt; — Tus fuentes crudas. Inmutables. El LLM solo lee.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;wiki/&lt;/code&gt;&lt;/strong&gt; — Conocimiento compilado. El LLM lo escribe y mantiene todo. Tú lo lees.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suena perfecto, ¿no? El LLM hace todo el trabajo pesado. Pero hay un punto ciego.&lt;/p&gt;

&lt;h2&gt;
  
  
  El GAP: el conocimiento refinado a mano no estaba protegido
&lt;/h2&gt;

&lt;p&gt;El patrón de Karpathy asume que &lt;strong&gt;tú nunca escribes en la wiki&lt;/strong&gt; — el LLM la mantiene por completo. En la práctica, eso no se sostiene. Eventualmente quieres intervenir: corregir una síntesis, afinar una conclusión, documentar algo que aprendiste por experiencia y que ninguna fuente captura.&lt;/p&gt;

&lt;p&gt;¿Y qué pasa entonces?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Los sistemas de conocimiento con IA tienen un punto ciego: no distinguen entre conocimiento generado automáticamente y conocimiento refinado por el humano. El LLM, durante un &lt;code&gt;ingest&lt;/code&gt; o &lt;code&gt;lint&lt;/code&gt;, puede sobrescribir silenciosamente ediciones manuales que costaron horas construir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si editas &lt;code&gt;wiki/&lt;/code&gt; a mano, estás editando un archivo que el LLM considera suyo. El próximo &lt;code&gt;ingest&lt;/code&gt; puede sobrescribirlo, exactamente como tu compilador regeneraría un archivo generado.&lt;/p&gt;

&lt;p&gt;Ese es el único GAP que reconocemos en la propuesta de Karpathy, y es justo el que resolvimos en agnosticBrain.&lt;/p&gt;

&lt;h2&gt;
  
  
  La solución: tres capas de ownership
&lt;/h2&gt;

&lt;p&gt;En lugar de dos capas, agnosticBrain define &lt;strong&gt;cuatro directorios con dueños explícitos y reglas no-negociables&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directorio&lt;/th&gt;
&lt;th&gt;Quién escribe&lt;/th&gt;
&lt;th&gt;Quién lee&lt;/th&gt;
&lt;th&gt;Regla crítica&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;raw/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Humano&lt;/td&gt;
&lt;td&gt;Todos&lt;/td&gt;
&lt;td&gt;LLM nunca modifica&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wiki/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;Todos&lt;/td&gt;
&lt;td&gt;El humano no edita a mano&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;curated/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Humano&lt;/td&gt;
&lt;td&gt;Todos&lt;/td&gt;
&lt;td&gt;LLM &lt;strong&gt;NUNCA&lt;/strong&gt; modifica&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;archivo/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sistema&lt;/td&gt;
&lt;td&gt;Todos&lt;/td&gt;
&lt;td&gt;Solo se entra, orden del humano&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;La clave es la tercera capa: &lt;strong&gt;&lt;code&gt;curated/&lt;/code&gt;&lt;/strong&gt; — notas refinadas manualmente, sagradas, de solo lectura para cualquier agente. La regla es contundente:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;REGLA 1 — El contenido de &lt;code&gt;curated/&lt;/code&gt; es inviolable.&lt;/strong&gt; NUNCA editar, sobrescribir ni alterar el contenido de una nota que reside en &lt;code&gt;curated/&lt;/code&gt;. Esta prohibición de contenido no tiene excepción: no se negocia en ingest, lint, ni ninguna otra operación de conocimiento.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si lo editaste a mano y no quieres perderlo → va en &lt;code&gt;curated/&lt;/code&gt;, no en &lt;code&gt;wiki/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo congelar una nota: &lt;code&gt;/curate&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Para proteger una nota que refinaste, el flujo es simple. La mueves de &lt;code&gt;wiki/&lt;/code&gt; a &lt;code&gt;curated/&lt;/code&gt; con la operación &lt;code&gt;/curate&lt;/code&gt;, y a partir de ese momento el LLM no la puede modificar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verificar&lt;/strong&gt; que la nota está en &lt;code&gt;wiki/&lt;/code&gt; y confirmar que quieres congelar su estado actual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;En tus propias palabras&lt;/strong&gt; — única fricción intencional del pipeline: el humano escribe la idea central de la nota. El LLM &lt;strong&gt;nunca redacta ni sugiere&lt;/strong&gt; esta línea. Es una firma de propiedad humana.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reescribir el frontmatter&lt;/strong&gt; al schema de &lt;code&gt;curated/&lt;/code&gt;: &lt;code&gt;status: human-canonical&lt;/code&gt;, &lt;code&gt;llm_action: read-only&lt;/code&gt;, &lt;code&gt;human_curated: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mover&lt;/strong&gt; la nota a &lt;code&gt;curated/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actualizar&lt;/strong&gt; &lt;code&gt;wiki/index.md&lt;/code&gt; (la entrada pasa a marcarse como &lt;code&gt;[CURATED]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registrar&lt;/strong&gt; en &lt;code&gt;wiki/log.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirmar al humano&lt;/strong&gt;: "✅ La nota [[curated/…]] está ahora protegida. El LLM no la modificará en futuros ingest ni lint."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cuando el LLM encuentra información nueva: &lt;code&gt;/propose&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Aquí está la parte interesante. ¿Qué pasa si el LLM procesa una nueva fuente que &lt;strong&gt;debería actualizar&lt;/strong&gt; una nota curada? ¿Ignora el conocimiento? ¿Lo aplica en secreto?&lt;/p&gt;

&lt;p&gt;Ninguna de las dos. La &lt;strong&gt;REGLA 6&lt;/strong&gt; lo resuelve:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;REGLA 6 — Proponer, no imponer, sobre &lt;code&gt;curated/&lt;/code&gt;.&lt;/strong&gt; Si información nueva actualiza o contradice &lt;code&gt;curated/&amp;lt;nota&amp;gt;&lt;/code&gt;: → Crear &lt;code&gt;wiki/_proposed/YYYY-MM-DD-&amp;lt;nombre-nota&amp;gt;.md&lt;/code&gt; con el diff propuesto. → Nunca tocar la nota curada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El flujo, definido en &lt;code&gt;SKILLS/propose.md&lt;/code&gt;, es el siguiente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identificar&lt;/strong&gt; la nota curada afectada y leerla completa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Construir el diff propuesto&lt;/strong&gt; — solo la sección afectada, no el archivo completo. Formato: sección actual (cita verbatim) → propuesta de cambio (solo el delta) → justificación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crear la propuesta&lt;/strong&gt; en &lt;code&gt;wiki/_proposed/YYYY-MM-DD-&amp;lt;nota&amp;gt;.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actualizar&lt;/strong&gt; el index (sección "Propuestas pendientes").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registrar&lt;/strong&gt; en &lt;code&gt;wiki/log.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notificar al humano&lt;/strong&gt;: "⚠️ Información nueva relevante para curated/. Creé una propuesta. Cuando quieras, te muestro el diff o lo aplico si lo apruebas."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El nombre del directorio lo dice todo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;El LLM propone. El humano decide. Nadie sobreescribe curated/ sin aprobación humana.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esto es lo que llamamos el mecanismo que &lt;strong&gt;cierra el loop de aprendizaje sin sacrificar la protección&lt;/strong&gt; del conocimiento curado. El LLM puede seguir aprendiendo de nuevas fuentes, pero nunca actúa unilateralmente sobre lo que tú construiste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo se cierra el loop: la aprobación humana
&lt;/h2&gt;

&lt;p&gt;Cuando quieres aceptar una propuesta, solo dices algo como:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Aplica la propuesta de &lt;code&gt;_proposed/YYYY-MM-DD-&amp;lt;nota&amp;gt;.md&lt;/code&gt;"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Y el LLM:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lee la propuesta completa.&lt;/li&gt;
&lt;li&gt;Lee la nota curada completa.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aplica SOLO el delta propuesto — nada más.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Actualiza &lt;code&gt;last_human_edit&lt;/code&gt; (aunque fue el LLM quien lo aplicó, es una edición aprobada por el humano).&lt;/li&gt;
&lt;li&gt;Marca la propuesta como aplicada y actualiza el index.&lt;/li&gt;
&lt;li&gt;Registra &lt;code&gt;proposal-applied&lt;/code&gt; en el log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Incluso en la aprobación, la protección no es un candado: es &lt;strong&gt;un límite de permisos&lt;/strong&gt; donde solo una decisión humana explícita puede abrir la escritura.&lt;/p&gt;

&lt;h2&gt;
  
  
  El resto del sistema
&lt;/h2&gt;

&lt;p&gt;agnosticBrain no es solo ownership. Tiene &lt;strong&gt;nueve operaciones&lt;/strong&gt; definidas en el kernel (&lt;code&gt;AGENTS.md&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operación&lt;/th&gt;
&lt;th&gt;Invocación&lt;/th&gt;
&lt;th&gt;Qué hace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/ingest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ingest [fuente]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compila una fuente en átomos enlazados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/query&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/query [pregunta]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Consulta navegando por MOCs y enlaces tipados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Health-check + salud del grafo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/archive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/archive [nota]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mueve nota a &lt;code&gt;archivo/&lt;/code&gt; — solo por orden explícita&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/curate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/curate [nota]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Congela nota de &lt;code&gt;wiki/&lt;/code&gt; a &lt;code&gt;curated/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/propose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto durante ingest&lt;/td&gt;
&lt;td&gt;Crea propuesta de cambio para nota curada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dashboard: conteos, log, propuestas pendientes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/gaps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/gaps&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Absorbe brechas respondidas (feedback loop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/compose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/compose [--hasta-limpio]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Composición autónoma continua del grafo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Y un principio de diseño que nos gusta especialmente (REGLA 8): &lt;strong&gt;una nota = un átomo; el cerebro es una red, no un archivador&lt;/strong&gt;. Cada &lt;code&gt;/ingest&lt;/code&gt; mejora el grafo — más nodos, mejores enlaces, menos centralización — en vez de engordar pocas notas gigantes. El cerebro compone, no acumula.&lt;/p&gt;

&lt;p&gt;Todo en texto plano: markdown puro, sin dependencias de apps. Solo necesitas Obsidian (con Templater) y el kernel en &lt;code&gt;AGENTS.md&lt;/code&gt; — un archivo que leen sin transformación los agentes (Claude Code, Codex, Cursor).&lt;/p&gt;

&lt;h2&gt;
  
  
  En resumen
&lt;/h2&gt;

&lt;p&gt;Karpathy nos dio un patrón brillante para que el LLM compile tu conocimiento en una wiki persistente. Pero le faltaba responder una pregunta: &lt;strong&gt;¿qué pasa cuando tú también escribes?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nuestra respuesta fue una tercera capa de ownership + un mecanismo de propuesta que respeta la jerarquía natural: el LLM propone, el humano decide. Con eso el conocimiento refinado a mano se vuelve inviolable, y el aprendizaje no se detiene — simplemente pasa por aprobación humana.&lt;/p&gt;

&lt;p&gt;Si quieres ver la implementación completa — con los 9 skills, los scripts de verificación y las reglas del kernel — está todo en &lt;a href="https://github.com/Macorreag/agnosticBrain" rel="noopener noreferrer"&gt;github.com/Macorreag/agnosticBrain&lt;/a&gt;. Y la propuesta original que extendemos, en el &lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f" rel="noopener noreferrer"&gt;gist de LLM Wiki de Karpathy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Esperamos que este patrón te sea de gran utilidad en tu flujo de conocimiento. &lt;strong&gt;¿tu LLM ha sobrescrito alguna vez una nota que cuidaste a mano?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ia</category>
      <category>obsidian</category>
      <category>productividad</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Conecta Notion y AI en n8n: ¡Adiós API, hola MCP OAuth2!</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Thu, 20 Nov 2025 05:06:40 +0000</pubDate>
      <link>https://dev.to/macorreag/conecta-notion-y-ai-en-n8n-adios-api-hola-mcp-oauth2-53h2</link>
      <guid>https://dev.to/macorreag/conecta-notion-y-ai-en-n8n-adios-api-hola-mcp-oauth2-53h2</guid>
      <description>&lt;p&gt;¿Alguna vez has soñado con decirle a tu automatización: &lt;em&gt;"Oye, revisa mi base de datos de Notion y resume las tareas pendientes de esta semana"&lt;/em&gt; y que simplemente... &lt;strong&gt;lo haga&lt;/strong&gt;? 🤯&lt;/p&gt;

&lt;p&gt;Sin configurar docenas de nodos HTTP. Sin pelearte con la documentación de la API de Notion para ver cómo filtrar por fechas. Solo tú, tu agente de IA y tus datos.&lt;/p&gt;

&lt;p&gt;Bueno, tengo noticias increíbles. El mundo del &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; ha llegado a n8n con una actualización que estábamos esperando: &lt;strong&gt;Soporte nativo para OAuth2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hoy vamos a ver cómo conectar el servidor oficial de Notion MCP directamente en n8n. ¡Prepárate para darle superpoderes a tus workflows! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;¿Qué es esto y por qué debería importarme?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Para los que no están al tanto, &lt;strong&gt;MCP&lt;/strong&gt; es como un estándar universal (imagina un puerto USB-C) para conectar modelos de IA con fuentes de datos. Antes, si querías que ChatGPT o Claude interactuaran con Notion dentro de n8n, tenías que crear herramientas personalizadas complejas.&lt;/p&gt;

&lt;p&gt;El problema anterior:&lt;br&gt;&lt;br&gt;
Conectar servidores MCP remotos seguros requería configuraciones extrañas o proxies porque la autenticación era un dolor de cabeza.&lt;br&gt;&lt;br&gt;
La solución actual:&lt;br&gt;&lt;br&gt;
&lt;a href="https://community.n8n.io/t/setting-official-notion-mcp-in-n8n/100333/23?page=2" rel="noopener noreferrer"&gt;n8n ha lanzado el soporte para MCP Client OAuth2 API&lt;/a&gt;. Esto significa que puedes usar el servidor oficial de Notion (&lt;a href="https://mcp.notion.com/mcp" rel="noopener noreferrer"&gt;https://mcp.notion.com/mcp&lt;/a&gt;) y autenticarte con el botón de "Conectar cuenta" de toda la vida.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;¿Por qué esto es mejor que usar el nodo tradicional de Notion?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lenguaje Natural:&lt;/strong&gt; No necesitas configurar parámetros rígidos. La IA "lee" la estructura de tu Notion y decide qué hacer.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Velocidad de desarrollo:&lt;/strong&gt; Te ahorras horas definiendo funciones. Conectas el MCP y la IA ya sabe cómo crear páginas, leer bases de datos o buscar contenido.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad:&lt;/strong&gt; Usamos OAuth2 estándar. Nada de tokens pegados en texto plano donde no deben estar.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Tutorial: Conectando Notion vía MCP en n8n&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;¡Manos a la obra! Vamos a configurar esto en menos de lo que tardas en tomarte un café. ☕&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Requisitos previos&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Una instancia de &lt;strong&gt;n8n&lt;/strong&gt; actualizada (asegúrate de tener las últimas versiones que soportan MCP Auth).
&lt;/li&gt;
&lt;li&gt;Una cuenta de &lt;strong&gt;Notion&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Paso 1: El Nodo Mágico&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Necesitamos usar el nodo &lt;strong&gt;MCP Client Tool&lt;/strong&gt;. Este nodo es el puente que le dice a tu Agente de IA (como el nodo &lt;em&gt;AI Agent&lt;/em&gt;) qué herramientas tiene disponibles.&lt;/p&gt;

&lt;p&gt;Busca en tu n8n: MCP Client Tool (asegúrate de que sea la versión de LangChain).&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Paso 2: Configuración de Credenciales (El Truco Pro)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Tip de Experto:&lt;/strong&gt; A veces, la opción para crear la credencial no aparece correctamente si intentas hacerlo directamente desde el nodo. Para evitar dolores de cabeza, vamos a crearla primero desde el gestor de credenciales.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En el menú lateral izquierdo de n8n, ve a &lt;strong&gt;Credentials&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Haz clic en &lt;strong&gt;Add Credential&lt;/strong&gt; y busca &lt;strong&gt;MCP OAuth2 API&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Rellena los datos necesarios:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server URL&lt;/strong&gt;: &lt;a href="https://mcp.notion.com/mcp" rel="noopener noreferrer"&gt;https://mcp.notion.com/mcp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Configura el OAuth2 estándar (Client ID, Client Secret, Auth URL, Token URL) según la documentación de tu integración de Notion, o usa la configuración dinámica si está disponible.
&lt;/li&gt;
&lt;li&gt;Asegúrate de copiar el &lt;strong&gt;OAuth Redirect URL&lt;/strong&gt; de n8n (&lt;a href="https://oauth.n8n.cloud/oauth2/callback" rel="noopener noreferrer"&gt;https://oauth.n8n.cloud/oauth2/callback&lt;/a&gt;) y ponerlo en tu integración de Notion si estás usando una app personalizada.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyauidwhad4ww4cr8s5di.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyauidwhad4ww4cr8s5di.png" alt=" " width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Así se ve cuando la conexión es exitosa, ¡luz verde!)&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Guarda la credencial.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ahora sí, vuelve a tu nodo &lt;strong&gt;MCP Client Tool&lt;/strong&gt;, selecciona mcpOAuth2Api en Authentication y elige la credencial que acabas de crear de la lista.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Paso 3: El Código (Copy &amp;amp; Paste)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para hacértelo aún más fácil, aquí tienes el JSON del nodo listo para importar. He limpiado los datos sensibles para que sea seguro usarlo.&lt;/p&gt;

&lt;p&gt;Simplemente copia esto, pégalo en tu lienzo de n8n y ajusta las credenciales seleccionando la que creaste en el paso anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nodes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"endpointUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.notion.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcpOAuth2Api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_NODE_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Notion MCP Client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@n8n/n8n-nodes-langchain.mcpClientTool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"typeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"credentials"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mcpOAuth2Api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_CREDENTIAL_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MCP Notion Account"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"connections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Notion MCP Client"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ai_tool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pinData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Paso 4: ¡A probar!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Conecta este nodo a un &lt;strong&gt;AI Agent&lt;/strong&gt; (como el que usa OpenAI o Anthropic). En el chat del agente, simplemente escribe:&lt;/p&gt;

&lt;p&gt;"Por favor, crea una nota en mi página de 'Ideas' que diga 'Investigar más sobre MCP en n8n' y ponle fecha de hoy."&lt;/p&gt;

&lt;p&gt;¡La IA usará la herramienta MCP, &lt;strong&gt;se autenticará vía OAuth2&lt;/strong&gt;, entenderá tu estructura de Notion y ejecutará la acción sin que tú hayas configurado un nodo de "Create Page"! ✨&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusión: El futuro es conversacional&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Esta actualización de n8n nos acerca un paso más a un futuro donde no programamos &lt;em&gt;cómo&lt;/em&gt; suceden las cosas paso a paso, sino que definimos &lt;em&gt;qué&lt;/em&gt; herramientas tiene la IA y dejamos que ella haga el trabajo pesado.&lt;/p&gt;

&lt;p&gt;La integración nativa de &lt;strong&gt;Notion MCP&lt;/strong&gt; elimina la fricción técnica. Ya no hay excusas para no tener un asistente personal que realmente gestione tu vida digital.&lt;/p&gt;

&lt;p&gt;¿Y tú? ¿Qué vas a automatizar primero con Notion y MCP? ¡Déjame tus ideas en los comentarios! 👇&lt;/p&gt;

&lt;p&gt;Happy automating! 🤖💙, obviamente una IA me ayudo a escribir esto!&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>ai</category>
      <category>mcp</category>
      <category>notion</category>
    </item>
    <item>
      <title>Compartiendo modificaciones de código Sin Internet: La Utilidad del Git Patch</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Mon, 09 Jun 2025 03:59:43 +0000</pubDate>
      <link>https://dev.to/macorreag/compartiendo-modificaciones-de-codigo-sin-internet-la-utilidad-del-git-patch-4ma8</link>
      <guid>https://dev.to/macorreag/compartiendo-modificaciones-de-codigo-sin-internet-la-utilidad-del-git-patch-4ma8</guid>
      <description>&lt;p&gt;¿Alguna vez te has encontrado en la situación de querer compartir cambios específicos en archivos de código con un colega, pero sin la posibilidad de subir esos cambios a un repositorio o sin acceso a internet?. Ya sea para probar una funcionalidad con un mock, realizar validaciones temporales o simplemente para tener esos ajustes a mano para un uso futuro, la opción tradicional de git stash a veces no es suficiente, especialmente si quieres compartirlos.&lt;br&gt;
Si necesitas compartir esos cambios con tu equipo sin depender de un repositorio remoto o una conexión a internet, este artículo te mostrará cómo git patch se convierte en tu aliado. Exploraremos cómo crear y aplicar parches de manera efectiva, una solución robusta para la transferencia de código en escenarios específicos.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Qué es un 'Patch' en Git y Por Qué Deberías Usarlo?
&lt;/h2&gt;

&lt;p&gt;Es un documento de texto plano que contiene las indicaciones precisas de los cambios que deben realizarse sobre líneas específicas de archivos. Esta característica es fundamental en Git, ya que el sistema se encarga de rastrear cada cambio y construir un "historial" que permite obtener una versión actualizada de cada archivo.&lt;br&gt;
Su utilidad principal radica en la capacidad de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Transferir cambios sin conexión: Ideal para entornos con conectividad limitada o nula.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compartir ajustes específicos: Permite aislar cambios para pruebas o revisiones sin afectar ramas principales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controlar lo que se comparte: A diferencia de un commit o un push, puedes seleccionar exactamente qué modificaciones incluir en el parche.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Git Patch: Cómo Compartir Cambios de Código sin Necesidad de Internet ni Repositorios Remotos
&lt;/h1&gt;

&lt;p&gt;¿Te has encontrado en la situación de necesitar &lt;strong&gt;compartir rápidamente modificaciones en tus archivos de código&lt;/strong&gt; con un compañero, pero sin la posibilidad de usar un repositorio remoto o una conexión a internet? O quizás, ¿buscas una manera de guardar cambios específicos para pruebas temporales, como usar un &lt;em&gt;mock&lt;/em&gt; o quitar validaciones, sin que queden registrados en una rama o subirlos al repositorio? Los &lt;strong&gt;parches de Git&lt;/strong&gt; ofrecen una solución elegante y eficiente para estos escenarios, permitiéndote tener esos cambios "a mano para usar después".&lt;/p&gt;

&lt;p&gt;Un parche de Git es un &lt;strong&gt;documento de texto plano&lt;/strong&gt; que contiene las instrucciones precisas para efectuar cambios sobre líneas específicas de archivos. Esta es la esencia de Git, ya que el sistema se encarga de rastrear cada cambio y construir un "historial" que nos permite obtener una versión actualizada de cada archivo.&lt;/p&gt;

&lt;p&gt;A continuación, te mostramos cómo crear, transferir y aplicar estos parches de manera sencilla y efectiva.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Creación de un Parche (Patch)
&lt;/h2&gt;

&lt;p&gt;Para empezar, navega al &lt;strong&gt;directorio de trabajo de tu repositorio&lt;/strong&gt; en tu terminal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Para cambios no &lt;em&gt;comiteados&lt;/em&gt; ni &lt;em&gt;añadidos&lt;/em&gt; al *commit&lt;/strong&gt;*:&lt;br&gt;
Utiliza el comando &lt;code&gt;git diff&lt;/code&gt; para generar un archivo que contenga solo las diferencias no guardadas. Este es ideal para cambios que aún no has decidido guardar en el historial del proyecto.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; cambios.patch
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Este comando creará un archivo llamado &lt;code&gt;cambios.patch&lt;/code&gt; con todas las modificaciones pendientes.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Para el &lt;em&gt;commit&lt;/em&gt; más reciente&lt;/strong&gt;:&lt;br&gt;
Si tus cambios ya han sido &lt;em&gt;comiteados&lt;/em&gt; y deseas compartir las diferencias de tu último &lt;em&gt;commit&lt;/em&gt;, usa &lt;code&gt;git format-patch&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git format-patch &lt;span class="nt"&gt;-1&lt;/span&gt; HEAD
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Este comando generará un archivo &lt;code&gt;.patch&lt;/code&gt; que encapsula todas las diferencias de ese &lt;em&gt;commit&lt;/em&gt;.&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Copia y Transferencia del Archivo de Parche
&lt;/h2&gt;

&lt;p&gt;Una vez que tengas el archivo &lt;code&gt;.patch&lt;/code&gt; creado, puedes transferirlo a tu compañero utilizando &lt;strong&gt;cualquier método físico&lt;/strong&gt;. Algunas opciones incluyen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Copiarlo a una memoria USB.&lt;/li&gt;
&lt;li&gt;  Enviarlo por correo electrónico si dispones de una conexión temporal.&lt;/li&gt;
&lt;li&gt;  Utilizar cualquier otro método de transferencia física para llevarlo a tu compañero.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. ¿Como se usa el parche?
&lt;/h2&gt;

&lt;p&gt;Tu compañero debe seguir estos pasos para aplicar los cambios contenidos en el parche:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Copiar el archivo &lt;code&gt;.patch&lt;/code&gt;&lt;/strong&gt; en su directorio de trabajo del repositorio.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Usar el comando &lt;code&gt;git apply&lt;/code&gt;&lt;/strong&gt; para aplicar los cambios:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git apply cambios.patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¡Y listo! Los cambios se aplicarán &lt;strong&gt;directamente en los archivos locales&lt;/strong&gt; de tu compañero, sin necesidad de interacciones con un repositorio remoto o una conexión a internet. Esta es una forma &lt;strong&gt;eficiente y práctica&lt;/strong&gt; de colaborar en el desarrollo de software cuando las condiciones lo requieren.&lt;/p&gt;

&lt;p&gt;Esperamos que esta guía te sea de gran utilidad en tu flujo de trabajo como desarrollador. En la comunidad de &lt;code&gt;dev.to&lt;/code&gt;, valoramos el &lt;strong&gt;intercambio de conocimientos y experiencias&lt;/strong&gt; entre desarrolladores.&lt;/p&gt;

</description>
      <category>git</category>
      <category>patch</category>
      <category>developers</category>
      <category>devtips</category>
    </item>
    <item>
      <title>How to use gettext in phoenix?</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Fri, 16 Aug 2024 17:15:00 +0000</pubDate>
      <link>https://dev.to/macorreag/how-to-use-gettext-in-phoenix-aga</link>
      <guid>https://dev.to/macorreag/how-to-use-gettext-in-phoenix-aga</guid>
      <description>&lt;p&gt;Así se usa Gettext:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;gettext&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Welcome&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt; &lt;span class="err"&gt;%{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="err"&gt;}!",&lt;/span&gt; &lt;span class="na"&gt;name:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;Phoenix&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.notion.so/Errores-en-Gettext-ce3272b6f665495d9ea4942f030283bd?pvs=21" rel="noopener noreferrer"&gt;Errores en Gettext&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extraer las traducciones&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix gettext.extract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mezclar las traducciones extraídas con las que ya tengo  (para todos los lenguajes)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix gettext.merge priv/gettext
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pluralización
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://phrase.com/blog/posts/i18n-for-phoenix-applications-with-gettext/" rel="noopener noreferrer"&gt;https://phrase.com/blog/posts/i18n-for-phoenix-applications-with-gettext/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este comando de pluralización genera errores cuando se le pasa un numero menor que 1 ya que no existen plurales para 0 ó numeros negativos y sintacticamente no tiene sentido&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## Llamado de un texto en singular con número 1&lt;/span&gt;
&amp;lt;%&lt;span class="o"&gt;=&lt;/span&gt; ngettext&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Total salary"&lt;/span&gt;, &lt;span class="s2"&gt;"Total salaries"&lt;/span&gt;, 1&lt;span class="o"&gt;)&lt;/span&gt; %&amp;gt; &lt;span class="c"&gt;#-&amp;gt; Total Salaries&lt;/span&gt;
&lt;span class="c"&gt;## Llamado de un texto plural con número 2 ó mas en este caso ese numero se interpola&lt;/span&gt;

&amp;lt;%&lt;span class="o"&gt;=&lt;/span&gt; ngettext&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Total salary"&lt;/span&gt;, &lt;span class="s2"&gt;"Total salaries"&lt;/span&gt;, 2&lt;span class="o"&gt;)&lt;/span&gt; %&amp;gt; &lt;span class="c"&gt;#-&amp;gt; Total Salaries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Archivos .po en plural
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;msgid &lt;span class="s2"&gt;"Total salary"&lt;/span&gt;
msgid_plural &lt;span class="s2"&gt;"Total %{count} salaries"&lt;/span&gt;
msgstr[0] &lt;span class="s2"&gt;"Total Salary"&lt;/span&gt;
msgstr[1] &lt;span class="s2"&gt;"Total Salaries"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ventajas de manejar Gettext sin nomenclatura
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;La traducción al inglés ya está hecha en el código.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;El manejo de mayusculas y minusculas no depende de usar prefijos(ejm: Text ó Label), si no de la palabra correspondiente, si se usa una palabra en mayuscula la primera esta va a salir así como se escriba&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Con Nomenclatura
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;msgid &lt;span class="s2"&gt;"LabelDeductions"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Deducciones"&lt;/span&gt;

msgid &lt;span class="s2"&gt;"textDeductions"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"deducciones"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;ol&gt;
&lt;li&gt;Sin nomenclatura
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;msgid &lt;span class="s2"&gt;"Deductions"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Deducciones"&lt;/span&gt;

msgid &lt;span class="s2"&gt;"deductions"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"deducciones"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;em&gt;Nota:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;%&lt;span class="o"&gt;=&lt;/span&gt; gettext&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"house"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; %&amp;gt;
&amp;lt;%&lt;span class="o"&gt;=&lt;/span&gt; gettext&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"House"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Si se tiene lo anterior en el código y se realiza una traducción como&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;msgid &lt;span class="s2"&gt;"house"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"casa"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Al extraer y mezclar traducciones, Gettext infiere automáticamente la otra traducción sin tener en cuenta las mayúsculas y regresa(con la palabra fuzzy).&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#, elixir-format, fuzzy&lt;/span&gt;
msgid &lt;span class="s2"&gt;"House"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"casa"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Lo anterior permite que el desarrollador no tenga que estar pendiente de las mayusculas que están en el documento.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Se optimiza el tiempo de codificado, las traducciones se pueden hacer de manera atemporal.&lt;/p&gt;

&lt;p&gt;El hecho de ser atemporales y sin contexto se refiere a que “una persona sin tener el contexto ó la información de donde se muestran estos mensajes en la aplicación puede traducirlos ó crear una mejor traduccion.”&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;msgid &lt;span class="s2"&gt;"LabelDaysGrantedVacation"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Días otorgados de vacaciones"&lt;/span&gt;

&lt;span class="c"&gt;## Reemplaza con&lt;/span&gt;

msgid &lt;span class="s2"&gt;"Vacation days granted"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Días otorgados de vacaciones"&lt;/span&gt;

&lt;span class="c"&gt;## La traducción en ingles se torna opcional, ya que el usuarió visualizara&lt;/span&gt;
&lt;span class="c"&gt;## "Vacation days granted" y no "LabelDaysGrantedVacation" al igual que el &lt;/span&gt;
&lt;span class="c"&gt;## programador que vera un texto mas entendible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```bash
msgid "TextInfoAbbRUTAbbDIAN"
msgstr "Para ingresar la información personal de su nuevo trabajador, puede ingresar el archivo (PDF) del Registro Único Tributario (RUT) descargado de la DIAN (maximo de treinta días de antiguedad). Recuerde que lo puedes descargar del sistema Muisca de la DIAN "

msgid "To enter the personal information of your new worker, you can enter the file (PDF) of the Single Tax Registry (RUT) downloaded from the DIAN (maximum thirty days old). Remember that you can download it from the DIAN Muisca system "
msgstr "Para ingresar la información personal de su nuevo trabajador, puede ingresar el archivo (PDF) del Registro Único Tributario (RUT) descargado de la DIAN (maximo de treinta días de antiguedad). Recuerde que lo puedes descargar del sistema Muisca de la DIAN "
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Las variables empiezan a tomar sentido&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Con nomenclatura&lt;/span&gt;
msgid &lt;span class="s2"&gt;"LabelApplyDecree%{Decree}%{YearDecree}"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Aplica para decreto %{Decree} del año %{YearDecree}"&lt;/span&gt;

&lt;span class="c"&gt;#Sin nomenclatura&lt;/span&gt;
msgid &lt;span class="s2"&gt;"Applies to decree %{NumberDecree} of %{YearDecree}"&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"Aplica para decreto %{Decree} del año %{YearDecree}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Las traducciones se pueden compartir entre proyectos, &lt;/p&gt;

&lt;p&gt;El comando mix gettext.merge priv/gettext  no borra las traducciones que ya se tienen en el archivo, por el contrario las mezcla é intenta predecir las posibles traducciones, si no tiene una coincidencia perfecta, marca la traducción como "dirtty", una vez que se modifica por parte de un programador manualmente, la establece como limpia automaticamente para la proxima extracción.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://hexdocs.pm/gettext/Mix.Tasks.Gettext.Merge.html" rel="noopener noreferrer"&gt;Gettext utiliza la distancia de Jaro para determinar si dos palabras o frases son similares&lt;/a&gt; y de esta manera infiere la traducción que marca como &lt;em&gt;fuzzy&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Plurales, porque complicarse?
&lt;/h3&gt;

&lt;p&gt;Sí, es más complejo usar plurales en forma adecuada en Gettext que utilizar condicionales en elixir y usar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;numero_casas&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="s2"&gt;"Las Casas"&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="s2"&gt;"La Casa"&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que usar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;ngettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"La Casa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Las Casas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numero_casas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si bien tiene una curva de aprendizaje su uso, el código es más legible y estas traducciones nos serviran en otros proyectos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F63732f8b-97a4-4485-9480-33f2430864a1%2FUntitled.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F63732f8b-97a4-4485-9480-33f2430864a1%2FUntitled.png" alt="Untitled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De esta manera, si algo no funciona siempre va a tener una lectura real y clara&lt;/p&gt;

&lt;h2&gt;
  
  
  Ventaja traducción con los plurales
&lt;/h2&gt;

&lt;p&gt;Los id singulares son diferenciados de los Id plurales&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;#Los Id no chocan con los Id plurales&lt;/span&gt;
msgid &lt;span class="s2"&gt;"TextDeductions"&lt;/span&gt; &lt;span class="c"&gt;#mismo ID en singular&lt;/span&gt;
msgstr &lt;span class="s2"&gt;"deducciones"&lt;/span&gt;

msgid &lt;span class="s2"&gt;"TextDeduction"&lt;/span&gt;
msgid_plural &lt;span class="s2"&gt;"TextDeductions"&lt;/span&gt; &lt;span class="c"&gt;#mismo ID en plural&lt;/span&gt;
msgstr[0] &lt;span class="s2"&gt;"deduccion"&lt;/span&gt;
msgstr[1] &lt;span class="s2"&gt;"deducciones"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Desventajas
&lt;/h2&gt;

&lt;p&gt;Los plurares NO incluyen el termino que se debe utilizar cuando se tienen 0 items solo cuando se tiene uno ó muchos por ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;Sin&lt;/span&gt; &lt;span class="nx"&gt;filtros&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;hay&lt;/span&gt; &lt;span class="nx"&gt;forma&lt;/span&gt; &lt;span class="nx"&gt;de&lt;/span&gt; &lt;span class="nx"&gt;aplicarlo&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;Filtro&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nx"&gt;Filtros&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nx"&gt;Filtros&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los plurales se tornan más largos, &lt;/p&gt;

&lt;p&gt;ngettext("Deduction", "Deductions", 2)&lt;/p&gt;

&lt;p&gt;Los archivos mezclados primero se deben esx&lt;/p&gt;

&lt;p&gt;mix gettext.merge priv/gettext/en/LC_MESSAGES/default2.po priv/gettext/en/LC_MESSAGES/default.po&lt;/p&gt;

&lt;h3&gt;
  
  
  Mezclar 2 archivos .po
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mix gettext.merge  priv/gettext/en/LC_MESSAGES/default2.po priv/gettext/en/LC_MESSAGES/default.po
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Para test
&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("The house is very pretty") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("The house") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("is very pretty") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("is very %{house}") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("house") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;&amp;lt;%= gettext("House") %&amp;gt;&lt;/h2&gt;

&lt;h2&gt;
  
  
  Mayusculas y minusculas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Gettext es CaseSensitive&lt;/strong&gt; debido a que en algunos lenguajes una palabra en mayuscula es diferente a una palabra en minúscula, por lo tanto tiene esta diferencia y la solucion es tratar ambos casos como corresponde además facilita el trabajo del progrmador, esto es una ventaja y una desventaja en realidad que se soluciona con gettext extract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gettext con variables en el string
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="n"&gt;text_action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;@action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"LabelEdit%{Object}"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"LabelCreate%{Object}"&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"uk-text-capitalize uk-font-size-15"&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;WebPortalBillingWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text_action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;Object:&lt;/span&gt; &lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"TextClient"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usar Gettext dentro de controladores ó liveview
&lt;/h2&gt;

&lt;p&gt;Es importante pasar &lt;code&gt;*NombreApp**Web**.Gettext&lt;/code&gt;  en el primer parámetro para que funcione el gettext, tenga en cuent que el módulo es &lt;code&gt;NombreApp**Web&lt;/code&gt;** con &lt;strong&gt;Web&lt;/strong&gt; al final.*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NombreAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"LabelRestrictionForDSAdquisitionsNational%{Object}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;Object:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;id_type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usando con un contexto específico “errors” es decir, el archivo errors.po&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dgettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NombreAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#Si el mensaje esta en una variable puede definir un valor por defecto con || &lt;/span&gt;
&lt;span class="c1"&gt;#ya que si pasa nil a la función esta fallara&lt;/span&gt;

&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dgettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;NombreAppWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"Default Message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Como hacer una traduccion con un valor que cambia?
&lt;/h2&gt;

&lt;p&gt;Esto no funciona, nativamente pero se puede intentar sacar las variables aparte con una función para hacer el matching.&lt;/p&gt;

&lt;p&gt;Suponga que del back llegan los siguientes errores&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;"Son 300 pesos" 
"Son 650 pesos" 
"Son 700 pesos" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Es posible generar un gettext que traduzca este texto mediante un unico id?
&lt;/h3&gt;

&lt;p&gt;Puede intentar usar named_captures para sacar aparte la lista de numeros que vienen en un texto &lt;/p&gt;

&lt;p&gt;&lt;a href="https://hexdocs.pm/elixir/1.12/Regex.html#named_captures/3" rel="noopener noreferrer"&gt;Regex - Elixir v1.12.3&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;#Algo como esto
msgid "Son %{Number} pesos"
msgstr "Is %{Number} pesos"
#generara algo como esto
"Is 300 pesos"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;
&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;WebPortalBillingWeb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gettext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Is 700 pesos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>translations</category>
      <category>phoenix</category>
      <category>gettext</category>
      <category>elixir</category>
    </item>
    <item>
      <title>Ignora archivos solo para ti en Git</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Thu, 20 Jun 2024 13:05:32 +0000</pubDate>
      <link>https://dev.to/macorreag/ignora-archivos-solo-para-ti-en-git-14oi</link>
      <guid>https://dev.to/macorreag/ignora-archivos-solo-para-ti-en-git-14oi</guid>
      <description>&lt;h2&gt;
  
  
  ¡Ignora archivos solo para ti en Git: domina .git/info/exclude como un pro!
&lt;/h2&gt;

&lt;p&gt;Ey Devs!, ¿alguna vez han querido excluir archivos de Git solo para su repositorio local sin afectar a sus colaboradores? ¡Entonces .git/info/exclude es su nuevo mejor amigo! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es .git/info/exclude?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A diferencia del archivo .gitignore, que se comparte con los colaboradores y se aplica a todos los clones del repositorio, .git/info/exclude es un archivo &lt;strong&gt;personal&lt;/strong&gt; que reside en &lt;code&gt;.git/info/&lt;/code&gt; y solo se aplica a &lt;strong&gt;tu clon local&lt;/strong&gt;. Esto lo convierte en el lugar ideal para omitir archivos que solo son relevantes para tu configuración de desarrollo o que no deseas compartir con el mundo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cuándo usar .git/info/exclude?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagina estos escenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuraciones de inicio de sesión personalizadas:&lt;/strong&gt; Si tu proyecto utiliza archivos de inicio de sesión confidenciales, como &lt;code&gt;.env&lt;/code&gt; o &lt;code&gt;.credentials&lt;/code&gt;, añádelos a &lt;code&gt;.git/info/exclude&lt;/code&gt; para evitar que se confirmen accidentalmente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Herramientas de desarrollo específicas:&lt;/strong&gt; ¿Utilizas herramientas que generan archivos temporales en el directorio de trabajo del repositorio? Añádelos a &lt;code&gt;.git/info/exclude&lt;/code&gt; para mantener tu espacio de trabajo limpio y sin archivos innecesarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archivos de prueba o borradores:&lt;/strong&gt; Si tienes archivos de prueba o borradores que no deseas que se incluyan en el historial de Git, &lt;code&gt;.git/info/exclude&lt;/code&gt; es tu solución.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo usar .git/info/exclude?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Abre .git/info/exclude:&lt;/strong&gt; Ubicate en la raiz de tu proyecto rastreado por git y ejecuta este comando para usar tu editor de texto favorito para abrir este archivo ubicado en la raíz de tu repositorio Git.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code .git/info/exclude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agrega patrones de exclusión:&lt;/strong&gt; Cada línea en &lt;code&gt;.git/info/exclude&lt;/code&gt; representa un patrón de archivo que deseas omitir. Git utiliza la sintaxis de exclusión de Git estándar, como comodines y expresiones regulares.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Guarda:&lt;/strong&gt; Guarda los cambios en &lt;code&gt;.git/info/exclude&lt;/code&gt;. ¡Listo! Los archivos que coincidan con tus patrones de exclusión ahora serán ignorados por Git en tu clon local.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para omitir el archivo &lt;code&gt;test.txt&lt;/code&gt; de tu repositorio local, agrega la siguiente línea a &lt;code&gt;.git/info/exclude&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Recursos adicionales:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentación oficial de Git sobre .git/info/exclude:&lt;/strong&gt; &lt;a href="https://git-scm.com/docs/gitignore/" rel="noopener noreferrer"&gt;https://git-scm.com/docs/gitignore/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artículo sobre "Ignorar archivos en Git sin agregarlos a .gitignore":&lt;/strong&gt; &lt;a href="https://stackoverflow.com/questions/653454/how-do-you-make-git-ignore-files-without-using-gitignore" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/653454/how-do-you-make-git-ignore-files-without-using-gitignore&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;¡Consejo profesional:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utiliza comentarios en &lt;code&gt;.git/info/exclude&lt;/code&gt; para describir los archivos o patrones que estás excluyendo para mejorar la legibilidad y el mantenimiento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¡Con .git/info/exclude en tu arsenal, puedes mantener tu repositorio local limpio y organizado, sin sacrificar la flexibilidad de excluir archivos específicos para tu configuración de desarrollo!&lt;/p&gt;

</description>
      <category>git</category>
      <category>gitignore</category>
      <category>developer</category>
      <category>tricks</category>
    </item>
    <item>
      <title>Google Apps Script - Configuración en Codespaces</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Fri, 01 Mar 2024 13:19:43 +0000</pubDate>
      <link>https://dev.to/macorreag/google-apps-script-configuracion-en-codespaces-1kil</link>
      <guid>https://dev.to/macorreag/google-apps-script-configuracion-en-codespaces-1kil</guid>
      <description>&lt;h1&gt;
  
  
  Como usar Google Apps Script en Codespaces
&lt;/h1&gt;

&lt;p&gt;Te presento esta plantilla de Github-Codespaces para que modifiques tus proyectos de Google Apps Script mediante Clasp&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Macorreag/clasp-template/tree/main"&gt;https://github.com/Macorreag/clasp-template/tree/main&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuracion de Clasp en Codespaces
&lt;/h2&gt;

&lt;p&gt;Primero debe logearse en una maquina Linux con el siguiente comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clasp login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto genera un archivo &lt;code&gt;.clasprc.json&lt;/code&gt; en la carpeta ./home/name_user/ en sistemas Linux&lt;/p&gt;

&lt;p&gt;Default credentials saved to: ~/.clasprc.json (/home/[USER]/.clasprc.json).&lt;/p&gt;

&lt;p&gt;Luego debe copiar las credenciales en la ventana de codespaces.&lt;/p&gt;

&lt;p&gt;Despues Copie las credenciales al espacio de trabajo hacia la carpeta de usuario del entorno de Codespaces&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp codespaces-blank/.clasprc.json ../../home/codespace/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una ves realizado esto Clasp utilizará este archivo con el token que contiene para acceder a los archivos de Google Apps Script&lt;/p&gt;

&lt;h2&gt;
  
  
  Usar multiples archivos de configuración para las credenciales
&lt;/h2&gt;

&lt;p&gt;Github Codespaces permite usar un repositorio de &lt;code&gt;.dotfiles&lt;/code&gt; en el cual puedes establecer las credenciales en los archivos .clasprc.json en la ruta &lt;code&gt;~/&lt;/code&gt; es decir en el directorio raiz. Estos archivos definen las credenciales y cuentas utilizadas para el acceso a los script. Para manejar multiples cuentas puedes crear multiples archivos asi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clasprc-work.json&lt;/li&gt;
&lt;li&gt;clasprc-personal.json&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y finalmente para definir cual usar puedes usar un &lt;em&gt;soft link&lt;/em&gt; de Linux forzado para sobreescribir, que apunte a cada uno de los archivos según desees usar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -f -s {source-filename} {symbolic-filename}
ln -f -s ~/.clasprc-personal.json ~/.clasprc.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puede chequear que el cambio funciona correctamente con:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ clasp  login --status
&amp;gt; You are logged in as personal@gmail.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone el Script que necesita mediante&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clasp clone "15ImUC************************6qiC" --rootDir .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  habilitar Google Apps Script
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgajx6x97ctrbbf3jfsh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgajx6x97ctrbbf3jfsh.png" alt="Image description" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if errror:&lt;br&gt;
User has not enabled the Apps Script API. Enable it by visiting &lt;a href="https://script.google.com/home/usersettings"&gt;https://script.google.com/home/usersettings&lt;/a&gt; then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.&lt;/p&gt;

&lt;p&gt;NO OLVIDE APAGAR SU MAQUINA DE CODESPACEES&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiao061ve0btpgudxw8kv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiao061ve0btpgudxw8kv.png" alt="Image description" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In VS Code: open the Visual Studio Code Command Palette - for example, by pressing Ctrl+Shift+Enter(Windows/Linux) or Shift+Command+P (Mac) - type Codespaces: stop then press Enter.&lt;br&gt;
In the JetBrains client, click the stop button at the top of the GitHub Codespaces tool window. For more information, see the "JetBrains IDEs" tab of "Stopping and starting a codespace."&lt;br&gt;
In a terminal window: use the GitHub CLI command gh codespace stop. For more information, see "Using GitHub Codespaces with GitHub CLI." If you exit your codespace without running the stop command (for example, by closing the browser tab), or if you leave the codespace running without interaction, the codespace and its running processes will continue for the duration of the inactivity timeout period.&lt;/p&gt;

&lt;p&gt;El enlace para acceder a tus proyectos es:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://script.google.com/u/1/home/start"&gt;https://script.google.com/u/1/home/start&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La cuenta esta definida por el numero, ahi podras ver los proyectos que tienes actualmente en Google Apps Script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuracion para correr el comando RUN
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/google/clasp/blob/master/docs/run.md"&gt;https://github.com/google/clasp/blob/master/docs/run.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El contenedor monta en la carpeta superior un proyecto de Node, e internamente coloca los archivos de Google Apps Script&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=o5coAL7oE0o&amp;amp;ab_channel=VisualStudioCode"&gt;Luego cambia la carpeta donde inicia el contenedor mediante la propieddad de Devcontainers.&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>💵 ¿Cómo comprar un buen computador?</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Tue, 15 Aug 2023 16:23:14 +0000</pubDate>
      <link>https://dev.to/macorreag/como-comprar-un-buen-computador-401</link>
      <guid>https://dev.to/macorreag/como-comprar-un-buen-computador-401</guid>
      <description>&lt;p&gt;Como estudiante de ingeniería de sistemas, a menudo me preguntan ¿cual computador debo comprar? ó ¿ Cual computador de estos es mejor ? y la respuesta no solamente depende de las características del computador en si, sino que también depende de aspectos muy subjetivos como quien lo va a usar etc..&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Quién lo va a usar?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  ¿Niños?&lt;/li&gt;
&lt;li&gt;[ ]  ¿Jóvenes?&lt;/li&gt;
&lt;li&gt;[ ]  ¿Personas mayores?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Para que lo va a usar?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  Trabajo (Office, Word y Internet ).&lt;/li&gt;
&lt;li&gt;[ ]  Herramientas de diseño de Adobe como photoshop.&lt;/li&gt;
&lt;li&gt;[ ]  Juegos de alto rendimiento.&lt;/li&gt;
&lt;li&gt;[ ]  Solo navegar en internet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿ Sistema Operativo?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  Windows 10 (Excel, Word ...)&lt;/li&gt;
&lt;li&gt;[ ]  Windows 7 (Excel, Word ...)&lt;/li&gt;
&lt;li&gt;[ ]  Distribuciones Linux como Ubuntu&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Que programas usan ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Almacenamiento SSD ó Disco Magnético?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SSD

&lt;ul&gt;
&lt;li&gt;Mayor velocidad si se tiene buen procesador.&lt;/li&gt;
&lt;li&gt;Menor capacidad de almacenamiento.&lt;/li&gt;
&lt;li&gt;Es mejor para computadores portátiles [ ya que se puede mover cuando este prendido y que no se dañe el mismo ]&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Disco Magnético

&lt;ul&gt;
&lt;li&gt;Menor Velocidad según procesador.&lt;/li&gt;
&lt;li&gt;Muchísima capacidad de almacenamiento.&lt;/li&gt;
&lt;li&gt;Muy susceptible a daños cuando se cae ó el computador se mueve mucho.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Tiene que ser un computador portátil?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ¿ Va a usar Wifi o estará conectado mediante cable Ethernet?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  ¿Que prefiere?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  Bonito y liviano pero lento.&lt;/li&gt;
&lt;li&gt;[ ]  Liviano y un poco lento además se puede calentar.&lt;/li&gt;
&lt;li&gt;[ ]  Rápido, no muy bonito y pesado&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿que tamaño necesita el computador?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ]  Para llevar en la maleta todos los días (pequeño)&lt;/li&gt;
&lt;li&gt;[ ]  Para llevar de vez en cuando en la maleta (mediano)&lt;/li&gt;
&lt;li&gt;[ ]  No necesito moverlo casi nunca (puede ser de mesa)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Presupuesto?
&lt;/h2&gt;

&lt;p&gt;Cuánto dinero está dispuesto a gastar en él&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo se debería describir un computador portátil?
&lt;/h2&gt;

&lt;p&gt;Describir un computador es mucho más fácil a mi manera de ver si se llenan los siguientes espacios.&lt;/p&gt;

&lt;p&gt;Este computador es marca ________ referencia _______ tiene un procesador ______ de __ generación marca intel con una velocidad de reloj de ___ Ghz. Tiene una capacidad de memoria ram de ___ GigaBytes DDR__ expandible a __ ya que &lt;em&gt;(si-no)&lt;/em&gt; tiene un espacio disponible para aumentar.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿ Y tú cómo haces para responderle a tus amigos cuando te preguntan cosas de este tipo ? Escribelo aqui 👇👇👇👇
&lt;/h2&gt;

</description>
    </item>
    <item>
      <title>Google Apps Script support JSDoc and Markdown</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Wed, 19 Jul 2023 18:46:44 +0000</pubDate>
      <link>https://dev.to/macorreag/google-apps-script-support-jsdoc-and-markdown-3kb</link>
      <guid>https://dev.to/macorreag/google-apps-script-support-jsdoc-and-markdown-3kb</guid>
      <description>&lt;p&gt;Yes Google Apps Script support Markdown in docs only in your IDE&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhum629ip9srg71r9obhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhum629ip9srg71r9obhn.png" alt="Image description" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NOt is supported in the Library Docs Shared&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal1kpypsv0h6oxcxfkrl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal1kpypsv0h6oxcxfkrl.png" alt="Image description" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>google</category>
      <category>googleappsscript</category>
      <category>googledocs</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Estructura de carpetas visual Google Drive</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Fri, 09 Jun 2023 13:21:07 +0000</pubDate>
      <link>https://dev.to/macorreag/estructura-de-carpetas-visual-google-drive-la0</link>
      <guid>https://dev.to/macorreag/estructura-de-carpetas-visual-google-drive-la0</guid>
      <description>&lt;h2&gt;
  
  
  Objetivo
&lt;/h2&gt;

&lt;p&gt;Una de las mejores maneras para entender algun tipo de estructura organizativa, corresponde a los graficos. A dia de hoy Google Drive no cuenta con las herramientas para visualizar graficamente una estructura de carpetas. En sistemas unix existe el comando &lt;code&gt;tree&lt;/code&gt;el cual nos permite mostrar de manera gráfica y de forma estructurada la jerarquía de los directorios de nuestro sistema operativo.&lt;/p&gt;

&lt;p&gt;Y como logramos tener esta estructura visual en Google Drive?&lt;/p&gt;

&lt;h2&gt;
  
  
  Avances encontrados
&lt;/h2&gt;

&lt;p&gt;Actualmente se tienen algunas iniciativas las cuales utilizan Google Apps Script para generar un Tree View.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tecnologia.facilisimo.com/crear-un-tree-view-de-google-drive-para-ver-archivos-facilmente_1262031.html" rel="noopener noreferrer"&gt;https://tecnologia.facilisimo.com/crear-un-tree-view-de-google-drive-para-ver-archivos-facilmente_1262031.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/56400923/trying-to-create-tree-view-of-google-drive-folders" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/56400923/trying-to-create-tree-view-of-google-drive-folders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.labnol.org/internet/google-drive-tree/21198/" rel="noopener noreferrer"&gt;https://www.labnol.org/internet/google-drive-tree/21198/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Posible mejora
&lt;/h2&gt;

&lt;p&gt;Se sugiere utilizar la tecnolog[ia de &lt;a href="https://mermaid.js.org/" rel="noopener noreferrer"&gt;Mermaid&lt;/a&gt; para generar graficos en MarkDown a traves de la estructura generada por el Script de Google y obtener una representaci[on visual de la estructura de carpetas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Hard edge] --&amp;gt;|Link text| B(Round edge)
    B --&amp;gt; C{Decision}
    C --&amp;gt;|One| D[Result one]
    C --&amp;gt;|Two| E[Result two]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Notion se veria algo asi &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen9llzq0o0fw4gteyq6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen9llzq0o0fw4gteyq6o.png" alt="Image description" width="635" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Otra opción más avanzada
&lt;/h2&gt;

&lt;p&gt;Se puede utilizar la API de &lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;https://app.diagrams.net/&lt;/a&gt; para crear un grafico que incluya los enlaces a cada uno de las carpetas y podamos navegar de manera m[as rapida.&lt;/p&gt;

&lt;p&gt;Si bien diagrams no tiene API si puede usar una herramienta para manipular los diagramas de &lt;a href="http://diagrams.net" rel="noopener noreferrer"&gt;diagrams.net&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/70543817/is-there-draw-io-api-to-manipulate-diagrams" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/70543817/is-there-draw-io-api-to-manipulate-diagrams&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solución definitiva
&lt;/h2&gt;

&lt;p&gt;Rclone nos proporciona el comando Tree&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rclone tree remote:path
/
├── file1
├── file2
├── file3
└── subdir
    ├── file4
    └── file5

1 directories, 5 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>googleappsscript</category>
      <category>proposals</category>
      <category>folders</category>
      <category>treeview</category>
    </item>
    <item>
      <title>Tricks Chrome</title>
      <dc:creator>Miller Correa</dc:creator>
      <pubDate>Wed, 10 Feb 2021 21:51:20 +0000</pubDate>
      <link>https://dev.to/macorreag/shortcut-to-move-chrome-tabs-34gb</link>
      <guid>https://dev.to/macorreag/shortcut-to-move-chrome-tabs-34gb</guid>
      <description>&lt;p&gt;In chrome you can move the current tab to the right with the key combination:&lt;/p&gt;

&lt;p&gt;Ctrl + shift + Page Down&lt;/p&gt;

&lt;p&gt;And to move to the left you can use:&lt;/p&gt;

&lt;p&gt;Ctrl + shift + Page Up&lt;/p&gt;

&lt;p&gt;This can improve your productivity by having the tabs you use organized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit web page like a word
&lt;/h2&gt;

&lt;p&gt;Put in developers tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.designMode = 'on'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for off this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.designMode = 'off'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shorcuts for Extensions
&lt;/h2&gt;

&lt;p&gt;You can customize the shorcuts to make faster use of the extensions you have installed in your browser. Just go to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.tochrome://extensions/shortcuts"&gt;chrome://extensions/shortcuts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Devtools Avanzado
&lt;/h2&gt;

&lt;p&gt;Puede usar la paleta de comandos de las DevTools para acceder mas rapido a las herramientas, primero abra las Devtools y luego presione la combinacion:&lt;/p&gt;

&lt;p&gt;Ctrl + shift + P&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>shorcut</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
