<?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: oubakiou</title>
    <description>The latest articles on DEV Community by oubakiou (@kiou_ouba_afbd120335456f3).</description>
    <link>https://dev.to/kiou_ouba_afbd120335456f3</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%2F3988109%2F9e652989-c669-418a-871e-cad98d1ac491.jpeg</url>
      <title>DEV Community: oubakiou</title>
      <link>https://dev.to/kiou_ouba_afbd120335456f3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kiou_ouba_afbd120335456f3"/>
    <language>en</language>
    <item>
      <title>Rendering Charts Beyond Mermaid's Reach with Vega-Lite and Embedding Them in Markdown (via LLM Skills)</title>
      <dc:creator>oubakiou</dc:creator>
      <pubDate>Tue, 30 Jun 2026 04:34:02 +0000</pubDate>
      <link>https://dev.to/kiou_ouba_afbd120335456f3/rendering-charts-beyond-mermaids-reach-with-vega-lite-and-embedding-them-in-markdown-via-llm-1kkl</link>
      <guid>https://dev.to/kiou_ouba_afbd120335456f3/rendering-charts-beyond-mermaids-reach-with-vega-lite-and-embedding-them-in-markdown-via-llm-1kkl</guid>
      <description>&lt;p&gt;AI agents like Claude Code and Codex can write code, polish documentation, and automate complex tasks. But ask them to "make a scatter plot of this data" or "show the trend as a heatmap," and they hit a wall. Mermaid tops out at basic bar charts and pie charts — statistical visualization is outside its scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/oubakiou/skills#dataviz-svg--vega-lite-%E3%81%AB%E3%82%88%E3%82%8B-svg-%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%E7%94%9F%E6%88%90" rel="noopener noreferrer"&gt;&lt;strong&gt;dataviz-svg&lt;/strong&gt;&lt;/a&gt; is a skill built to fill that gap. It generates SVG charts from &lt;a href="https://github.com/vega/vega-lite" rel="noopener noreferrer"&gt;Vega-Lite&lt;/a&gt; declarative JSON specs and embeds them directly into Markdown documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Mermaid Falls Short
&lt;/h2&gt;

&lt;p&gt;Mermaid is a great tool, but it excels in a different domain.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mermaid's strengths&lt;/th&gt;
&lt;th&gt;dataviz-svg's strengths&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flowcharts, sequence diagrams, ER diagrams&lt;/td&gt;
&lt;td&gt;Scatter plots, heatmaps, histograms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State diagrams, Gantt charts&lt;/td&gt;
&lt;td&gt;Box plots, area charts, bubble charts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple bar charts with a few data points&lt;/td&gt;
&lt;td&gt;Charts with 20+ data points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structural diagrams in general&lt;/td&gt;
&lt;td&gt;Multi-axis encoding (x, y, color, size)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short: Mermaid is for &lt;strong&gt;structural diagrams&lt;/strong&gt;, dataviz-svg is for &lt;strong&gt;data-driven statistical visualization&lt;/strong&gt;. When an agent can use both, the expressiveness of its documentation output improves dramatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Chart Types
&lt;/h2&gt;

&lt;p&gt;An example actually generated from the skill&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%2Feeg535zn5uc1d3x5cxgo.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%2Feeg535zn5uc1d3x5cxgo.png" alt=" " width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;dataviz-svg inherits the full expressiveness of Vega-Lite, so the range of supported charts is broad. Check out the &lt;a href="https://vega.github.io/vega-lite/examples/" rel="noopener noreferrer"&gt;official Vega-Lite gallery&lt;/a&gt; to see what's possible at a glance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bar charts&lt;/strong&gt; — vertical, horizontal, grouped, stacked (including 100% stacked)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line charts&lt;/strong&gt; — single series, multi-series (with &lt;code&gt;strokeDash&lt;/code&gt; for print-friendly output)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scatter plots&lt;/strong&gt; — basic scatter, bubble charts (size + color + log scale)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Area charts&lt;/strong&gt; — stacked area, streamgraph&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heatmaps&lt;/strong&gt; — 2D grid with overlaid text layers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Histograms&lt;/strong&gt; — distribution via binning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Box plots&lt;/strong&gt; — quartile display&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pie / Donut charts&lt;/strong&gt; — donut variant via &lt;code&gt;innerRadius&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layered charts&lt;/strong&gt; — line + point + text label overlays&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facet / Concatenation&lt;/strong&gt; — small multiples, horizontal/vertical multi-chart layouts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;The core of dataviz-svg is simple. Vega-Lite and Vega are bundled into a single ESM file (~1.6 MB) with Vite, so it runs on Node.js alone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vega-Lite JSON spec
    ↓ compile()
Vega spec
    ↓ Vega runtime
SVG string
    ↓ writeFileSync
output.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No native dependencies like &lt;code&gt;canvas&lt;/code&gt; or &lt;code&gt;puppeteer&lt;/code&gt;. No additional &lt;code&gt;npm install&lt;/code&gt; needed. The bundle ships with the skill, so it works right after installation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution Flow from the Agent's Perspective
&lt;/h3&gt;

&lt;p&gt;When an agent uses this skill, it follows 5 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understand data and visualization requirements&lt;/strong&gt; — identify the input data (inline values / CSV / JSON), chart type, and axis/color mappings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a Vega-Lite JSON spec&lt;/strong&gt; — write the spec as a JSON file, referencing the bundled pattern collection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render the SVG&lt;/strong&gt; — run &lt;code&gt;render-svg.sh&lt;/code&gt; to generate the SVG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embed in Markdown&lt;/strong&gt; — reference with &lt;code&gt;![Chart Title](./assets/chart.svg)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review and adjust&lt;/strong&gt; — inspect the SVG, tweak label angles or color scales, and re-render&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the user's perspective, you just say "turn this data into a heatmap" and the agent handles everything — spec creation, rendering, and document embedding — end to end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Visualizing Sales Data
&lt;/h2&gt;

&lt;p&gt;For example, to create a bar chart of quarterly sales data, the agent generates a Vega-Lite spec like this:&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;"$schema"&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://vega.github.io/schema/vega-lite/v5.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"white"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"values"&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;"quarter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&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;"quarter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;185&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;"quarter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;210&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;"quarter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Q4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sales"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;165&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;"mark"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"encoding"&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;"x"&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;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quarter"&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;"ordinal"&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;"y"&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;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sales"&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;"quantitative"&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;"color"&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;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quarter"&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;"nominal"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass this to &lt;code&gt;render-svg.sh&lt;/code&gt; and an SVG is generated — no browser required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Trade-offs
&lt;/h2&gt;

&lt;p&gt;Practicality comes first. Here are the deliberate trade-offs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SVG only&lt;/strong&gt;: No PNG/PDF support. Eliminating native dependencies (&lt;code&gt;canvas&lt;/code&gt; / &lt;code&gt;sharp&lt;/code&gt;) means zero setup friction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static output only&lt;/strong&gt;: Vega-Lite's interactive features (hover, zoom, selection) don't carry over to SVG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No font embedding&lt;/strong&gt;: Relies on system fonts. &lt;code&gt;sans-serif&lt;/code&gt; is the safest choice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No canvas package&lt;/strong&gt;: Text bounding box calculations are approximate, which may cause slight misalignment with long CJK (e.g., Japanese) labels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are intentional. The top priority is "works immediately in any environment, with no extra installation."&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&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;# For Claude Code&lt;/span&gt;
gh skill &lt;span class="nb"&gt;install &lt;/span&gt;oubakiou/skills dataviz-svg &lt;span class="nt"&gt;--agent&lt;/span&gt; claude-code &lt;span class="nt"&gt;--scope&lt;/span&gt; project

&lt;span class="c"&gt;# For Codex&lt;/span&gt;
gh skill &lt;span class="nb"&gt;install &lt;/span&gt;oubakiou/skills dataviz-svg &lt;span class="nt"&gt;--agent&lt;/span&gt; codex &lt;span class="nt"&gt;--scope&lt;/span&gt; project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only prerequisite is Node.js 18 or later. Vega and Vega-Lite are bundled, so no separate installation is needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;dataviz-svg is laser-focused on one thing: giving AI agents the ability to create data visualizations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates statistical charts that Mermaid can't handle, powered by Vega-Lite&lt;/li&gt;
&lt;li&gt;No browser, no extra dependencies — just Node.js&lt;/li&gt;
&lt;li&gt;The agent handles the entire pipeline: spec creation, rendering, and document embedding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Turn this data into a chart." — With that single request, the agent picks the right chart type, generates it, and embeds it in your document. Naturally integrating data visualization into the AI agent workflow — that's what dataviz-svg is for.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>datascience</category>
      <category>llm</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Your LLM reads the whole file. It doesn't have to.</title>
      <dc:creator>oubakiou</dc:creator>
      <pubDate>Fri, 19 Jun 2026 12:05:00 +0000</pubDate>
      <link>https://dev.to/kiou_ouba_afbd120335456f3/your-llm-reads-the-whole-file-it-doesnt-have-to-hem</link>
      <guid>https://dev.to/kiou_ouba_afbd120335456f3/your-llm-reads-the-whole-file-it-doesnt-have-to-hem</guid>
      <description>&lt;p&gt;Coding agents read specs, design docs, and long READMEs every day. Most of the time, they only need a few sections. Yet they load the entire file into context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hidden cost of "just read the file"
&lt;/h2&gt;

&lt;p&gt;Here's a scenario that plays out constantly. You ask your agent to check the error handling section of a 5,000-line API spec. The agent opens the file, reads all 5,000 lines into its context window, finds the 80 lines it needs, and answers your question.&lt;/p&gt;

&lt;p&gt;The result is correct. But the agent also consumed a large number of tokens on the 4,920 lines it didn't need. Repeat this for every file read in a session, and the waste compounds fast.&lt;/p&gt;

&lt;p&gt;The cost isn't just tokens. A context window stuffed with irrelevant content makes the agent's answers worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  What humans do differently
&lt;/h2&gt;

&lt;p&gt;When a human picks up a 300-page technical book, they don't read cover to cover to find the chapter on authentication. They flip to the table of contents, scan the chapter titles, and jump to page 47. LLMs can do the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markdown is already structured
&lt;/h2&gt;

&lt;p&gt;Markdown documents have a built-in structure: headings. A &lt;code&gt;# Title&lt;/code&gt; followed by &lt;code&gt;## Section A&lt;/code&gt; followed by &lt;code&gt;### Subsection A.1&lt;/code&gt; creates a hierarchy that mirrors a book's table of contents.&lt;/p&gt;

&lt;p&gt;Split a Markdown file at heading boundaries, and you get a natural "table of contents + sections" structure. Each heading starts a new section, the heading text becomes the index entry, and the section number becomes the address.&lt;/p&gt;

&lt;p&gt;This is the idea behind &lt;a href="https://github.com/oubakiou/md2idx" rel="noopener noreferrer"&gt;md2idx&lt;/a&gt;, a CLI tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use md2idx
&lt;/h2&gt;

&lt;p&gt;md2idx converts a Markdown file into JSON with two fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;index&lt;/code&gt;&lt;/strong&gt;: a numbered table of contents where each line is &lt;code&gt;&amp;lt;# markers for depth&amp;gt; &amp;lt;serial&amp;gt;. &amp;lt;heading text&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;sections&lt;/code&gt;&lt;/strong&gt;: a flat array of raw Markdown strings, one per heading
&lt;/li&gt;
&lt;/ul&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;npx md2idx spec.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.index'&lt;/span&gt;
&lt;span class="c"&gt;# 0. API Specification&lt;/span&gt;
&lt;span class="c"&gt;## 1. Authentication&lt;/span&gt;
&lt;span class="c"&gt;## 2. Endpoints&lt;/span&gt;
&lt;span class="c"&gt;### 3. GET /users&lt;/span&gt;
&lt;span class="c"&gt;### 4. POST /users&lt;/span&gt;
&lt;span class="c"&gt;## 5. Error Handling&lt;/span&gt;
&lt;span class="c"&gt;## 6. Rate Limiting&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The serial numbers match the array indices. To read the Error Handling section:&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;npx md2idx spec.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sections[5]'&lt;/span&gt;
&lt;span class="c"&gt;## Error Handling&lt;/span&gt;

When a request fails, the API returns a JSON error object with...
&lt;span class="o"&gt;(&lt;/span&gt;just the content of that one section&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To read a heading and all its children together:&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;npx md2idx spec.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sections[2:5][]'&lt;/span&gt;
&lt;span class="c"&gt;# Endpoints, GET /users, and POST /users — all 3 sections&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a 5,000-line spec where the agent needs 2 sections, context usage goes from ~5,000 lines to ~100 lines (20-line index + 80 lines of content). Depending on the document and which sections are needed, the reduction is typically 80–98%.&lt;/p&gt;

&lt;p&gt;The output is designed to work with &lt;code&gt;jq&lt;/code&gt;. One-line JSON by default (pipe-friendly), &lt;code&gt;--pretty&lt;/code&gt; for formatted output. Reads from a file argument or stdin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just grep for headings?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;grep -nE '#{1,6} ' spec.md&lt;/code&gt; gives you a list of headings. For simple cases, that works. But md2idx covers problems that grep can't solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Section body retrieval&lt;/strong&gt;: grep only returns heading lines. To get the body, you need to calculate the line range and use Read with offset/limit. With md2idx, &lt;code&gt;jq '.sections[N]'&lt;/code&gt; is all it takes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setext headings&lt;/strong&gt; (&lt;code&gt;===&lt;/code&gt; / &lt;code&gt;---&lt;/code&gt;): invisible to grep's &lt;code&gt;#&lt;/code&gt; pattern&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;#&lt;/code&gt; inside code fences&lt;/strong&gt;: grep returns false positives. md2idx skips fenced blocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline markup&lt;/strong&gt;: grep includes &lt;code&gt;[link](url)&lt;/code&gt; etc. as-is. md2idx strips markup in the index while preserving it in section content&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automate with a Claude Code skill
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mkdn.review/?url=https%3A%2F%2Fgithub.com%2Foubakiou%2Fmd2idx%2Fblob%2Fmain%2Fskills%2Fmd2idx-read%2FSKILL.md#p:introduction" rel="noopener noreferrer"&gt;Skill details (SKILL.md)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;md2idx-read&lt;/code&gt; skill, the agent autonomously handles everything from fetching the index to selecting sections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent checks the file size and, if large, calls md2idx to fetch the index&lt;/li&gt;
&lt;li&gt;It reads the index and identifies which sections are relevant to the current task&lt;/li&gt;
&lt;li&gt;It retrieves only those sections via &lt;code&gt;jq&lt;/code&gt; slicing&lt;/li&gt;
&lt;li&gt;If more sections are needed, it goes back to step 3 (the index is already in context)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install the skill&lt;/span&gt;
gh skill &lt;span class="nb"&gt;install &lt;/span&gt;oubakiou/md2idx md2idx-read &lt;span class="nt"&gt;--agent&lt;/span&gt; claude-code &lt;span class="nt"&gt;--scope&lt;/span&gt; project

&lt;span class="c"&gt;# or with npx&lt;/span&gt;
npx skills add oubakiou/md2idx &lt;span class="nt"&gt;--skill&lt;/span&gt; md2idx-read &lt;span class="nt"&gt;--agent&lt;/span&gt; claude-code &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, the agent uses the skill proactively whenever it encounters a large Markdown file. No manual invocation needed — it reads the index first, picks sections, and skips the rest.&lt;/p&gt;

&lt;p&gt;A fallback is included. If md2idx isn't available (network-restricted environments, permission issues), it falls back to &lt;code&gt;grep&lt;/code&gt; for headings and Read tool with offset/limit. Less accurate, but functional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it now
&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;# read the index of any Markdown file&lt;/span&gt;
npx md2idx README.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.index'&lt;/span&gt;

&lt;span class="c"&gt;# grab a specific section by number&lt;/span&gt;
npx md2idx README.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sections[2]'&lt;/span&gt;

&lt;span class="c"&gt;# search within a section&lt;/span&gt;
npx md2idx data.md | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sections[4]'&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;Tokyo

&lt;span class="c"&gt;# global install&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; md2idx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;md2idx has zero external dependencies — a self-contained line scanner, not a Markdown AST parser. It handles ATX headings (&lt;code&gt;#&lt;/code&gt; style), setext headings (&lt;code&gt;===&lt;/code&gt; / &lt;code&gt;---&lt;/code&gt; underlines), code fence skipping, and inline markup stripping.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;md2idx&lt;/strong&gt; is MIT-licensed and fully open source. If your LLM agents are reading entire large Markdown files, give it a try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/oubakiou/md2idx" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub repo →&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/md2idx" rel="noopener noreferrer"&gt;&lt;strong&gt;npm →&lt;/strong&gt;&lt;/a&gt; &lt;code&gt;npx md2idx your-file.md | jq -r '.index'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/oubakiou/md2idx/blob/main/skills/md2idx-read/SKILL.md" rel="noopener noreferrer"&gt;&lt;strong&gt;Claude Code skill →&lt;/strong&gt;&lt;/a&gt; &lt;code&gt;gh skill install oubakiou/md2idx md2idx-read&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've tried it in your agent workflow, I'd love to hear how it went — drop a comment below or &lt;a href="https://github.com/oubakiou/md2idx/issues" rel="noopener noreferrer"&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>markdown</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The next bottleneck after AI writes your code is reviewing the docs it writes</title>
      <dc:creator>oubakiou</dc:creator>
      <pubDate>Wed, 17 Jun 2026 03:43:15 +0000</pubDate>
      <link>https://dev.to/kiou_ouba_afbd120335456f3/the-next-bottleneck-after-ai-writes-your-code-is-reviewing-the-docs-it-writes-3pc7</link>
      <guid>https://dev.to/kiou_ouba_afbd120335456f3/the-next-bottleneck-after-ai-writes-your-code-is-reviewing-the-docs-it-writes-3pc7</guid>
      <description>&lt;p&gt;Coding agents draft specs, architecture docs, changelogs, and README updates in seconds — but a human still has to judge the quality of all that output.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottleneck shift
&lt;/h2&gt;

&lt;p&gt;A year ago, the typical workflow was: you write a spec, you get comments, you revise, then you implement and get code review. Humans did most of the writing and coding. Now, agents produce first drafts of design docs, API references, runbooks, and onboarding guides — and they do it in seconds.&lt;/p&gt;

&lt;p&gt;Code implementation and code review can now be handled by agents, so those are no longer the bottleneck. What surfaced instead is the step right before: document review. A human has to read 2,000 lines of generated markdown and decide what's wrong. The writing part got dramatically faster. LLMs can assist with document review too, but compared to code implementation and code review, the human judgment required is still larger.&lt;/p&gt;

&lt;p&gt;This asymmetry compounds fast. Every agent-assisted project now has a stack of "needs human review" documents growing in a shared folder. If you're running multiple agent loops in parallel — one for the spec, one for the implementation plan, one for the test strategy — review becomes a pipeline stall. GitHub PRs remain the right tool when you need third-party review. But the step before that — the fast local self-review loop where you and your agent iterate on a draft — doesn't belong in a PR. Branching, diffing, and assigning reviewers is a lot of process for a first draft the agent wrote in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why prose feedback is lossy
&lt;/h2&gt;

&lt;p&gt;The most common workaround today is to have the agent read the document and then fix things based on natural-language feedback:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The error handling in section 3.2 is too vague — be specific about what happens on timeout."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This looks reasonable. The agent reads it, searches for something about error handling, and makes a change. But several things go wrong:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Position is ambiguous.&lt;/strong&gt; If section 3.2 has three paragraphs about error handling, which one did the reviewer mean? The agent guesses, and sometimes guesses wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context is lost.&lt;/strong&gt; The reviewer was looking at a &lt;em&gt;rendered&lt;/em&gt; document — they saw the Mermaid diagram, the table layout, the code blocks with syntax highlighting. The prose feedback carries none of that visual context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Round-trips are vague.&lt;/strong&gt; The agent applies a fix. Did it address the right spot? The reviewer pastes the updated draft back into the chat. No diff. No anchoring. Another round of guessing.&lt;/p&gt;

&lt;p&gt;The fundamental problem: prose feedback loses the structure the reviewer had in mind. The reviewer knows which text range they're commenting on — but that spatial information is discarded the moment they express it in natural language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback as a machine-readable artifact
&lt;/h2&gt;

&lt;p&gt;What if the reviewer's comments came back as structured JSON, with every comment anchored to a precise location in the source markdown?&lt;/p&gt;

&lt;p&gt;That's what &lt;a href="https://github.com/oubakiou/mdxg-redline" rel="noopener noreferrer"&gt;MDXG Redline&lt;/a&gt; (&lt;a href="https://mkdn.review/?url=https%3A%2F%2Fraw.githubusercontent.com%2Foubakiou%2Fmdxg-redline%2Frefs%2Fheads%2Fmain%2FREADME.md" rel="noopener noreferrer"&gt;online demo&lt;/a&gt;) produces. The reviewer selects any text range in a rendered markdown document, leaves an inline comment, and on export the tool writes a JSON file like this:&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;"document"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api-spec.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"docHash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a1b2c3d4e5f6a7b8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exportedAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-15T10:30:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"comments"&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;"f3a1c8b2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"quote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The service retries up to 3 times"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Specify the backoff strategy — is it exponential? Fixed interval? This matters for downstream timeout config."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headingPath"&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="s2"&gt;"## 3. Error Handling"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"### 3.2 Retry Policy"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sourceLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-15T10:28:11.000Z"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every comment carries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;quote&lt;/code&gt;&lt;/strong&gt; — the exact text the reviewer selected (human-readable reference)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;comment&lt;/code&gt;&lt;/strong&gt; — what the reviewer wrote&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;headingPath&lt;/code&gt;&lt;/strong&gt; — the heading ancestry, from shallowest to deepest (&lt;code&gt;["## 3. Error Handling", "### 3.2 Retry Policy"]&lt;/code&gt;), so the agent can navigate the document hierarchy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;sourceLine&lt;/code&gt;&lt;/strong&gt; — the 1-origin line number in the source markdown, so the agent can jump straight to the right spot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(The actual export also includes &lt;code&gt;blockId&lt;/code&gt;, &lt;code&gt;startOffset&lt;/code&gt;, and &lt;code&gt;endOffset&lt;/code&gt; — internal anchoring fields used for round-trip re-import into the next review round. The four fields above are the ones your agent needs.)&lt;/p&gt;

&lt;p&gt;No guessing, no ambiguity. The agent reads the JSON, opens the source file, goes to line 142, and applies the feedback directly. The feedback JSON is a plain file on disk — any agent that can read JSON and edit files can consume it, regardless of framework or provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loop in practice
&lt;/h2&gt;

&lt;p&gt;MDXG Redline is designed around a review loop where an agent and a human pass a document back and forth:&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%2Fxafgo4ftmon3bjqnlzv0.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%2Fxafgo4ftmon3bjqnlzv0.png" alt=" " width="679" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent uses the CLI to generate a &lt;code&gt;&amp;lt;name&amp;gt;-&amp;lt;hash&amp;gt;-review.html&lt;/code&gt; file from the markdown — a self-contained HTML file that renders the document with syntax highlighting, diagrams, and math.&lt;/li&gt;
&lt;li&gt;The CLI auto-launches the reviewer's browser.&lt;/li&gt;
&lt;li&gt;The reviewer reads the rendered document, selects text ranges, and leaves inline comments. One click writes &lt;code&gt;&amp;lt;name&amp;gt;-&amp;lt;hash&amp;gt;-feedback.json&lt;/code&gt; to the same folder.&lt;/li&gt;
&lt;li&gt;The agent monitors in the background, automatically picks up the JSON, and applies the feedback.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ks61u4lkftihldsi8f4.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%2F5ks61u4lkftihldsi8f4.png" alt=" " width="697" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each revision gets a unique hash in the filename, so review/feedback pairs for different revisions never collide.&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%2Fzswc4ffd82iuq3kbvqfx.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%2Fzswc4ffd82iuq3kbvqfx.png" alt=" " width="332" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Claude Code and Codex users, there's a &lt;code&gt;md-review&lt;/code&gt; skill that automates the entire loop — HTML generation, waiting for feedback, and applying revisions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mkdn.review/?url=https%3A%2F%2Fgithub.com%2Foubakiou%2Fmdxg-redline%2Fblob%2Fmain%2Fskills%2Fmd-review%2FSKILL.md" rel="noopener noreferrer"&gt;SKILL.md&lt;/a&gt;&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;# install the skill&lt;/span&gt;
gh skill &lt;span class="nb"&gt;install &lt;/span&gt;oubakiou/mdxg-redline md-review &lt;span class="nt"&gt;--agent&lt;/span&gt; claude-code &lt;span class="nt"&gt;--scope&lt;/span&gt; project

&lt;span class="c"&gt;# then just tell the agent:&lt;/span&gt;
&lt;span class="c"&gt;# "please request a review for spec.md"&lt;/span&gt;
&lt;span class="c"&gt;# or invoke the slash command directly:&lt;/span&gt;
&lt;span class="c"&gt;# /md-review README.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The skill is a convenience wrapper. Since the feedback JSON is a plain file, the loop works with any agent — you can wire it into a custom LangChain pipeline or a simple shell script that polls for the JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it renders
&lt;/h2&gt;

&lt;p&gt;MDXG Redline isn't just a review overlay — it's a markdown rendering engine packed into a single standalone HTML file with no backend and no dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smartphone support&lt;/strong&gt; — On mobile screens, the UI switches to a layout with a footer bar for TOC, Comments, and Search. You can review and comment from your phone — no need to wait until you're back at your desk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax highlighting for ~235 languages&lt;/strong&gt; — The CLI auto-detects which languages your document uses and injects only those Shiki grammars, keeping the file lean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mermaid diagrams and KaTeX math&lt;/strong&gt; — Fenced &lt;code&gt;&lt;/code&gt;`&lt;code&gt;mermaid&lt;/code&gt; blocks render as SVGs; &lt;code&gt;$...$&lt;/code&gt; / &lt;code&gt;$$...$$&lt;/code&gt; math renders via KaTeX. Both are auto-detected and injected only when present.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Word-style stacked pages&lt;/strong&gt; — The document splits at H1/H2 boundaries into paper-like sheets you scroll through vertically, with a sidebar for navigation. Footnotes and left-hand keyboard navigation are also built in.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://github.com/oubakiou/mdxg-redline#features" rel="noopener noreferrer"&gt;full feature list in the README&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it in 30 seconds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No install needed&lt;/strong&gt; — open &lt;a href="https://mkdn.review/" rel="noopener noreferrer"&gt;mkdn.review&lt;/a&gt; and load any public GitHub raw URL. Here's a one-click example that loads the project's own README:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mkdn.review/?url=https%3A%2F%2Fraw.githubusercontent.com%2Foubakiou%2Fmdxg-redline%2Frefs%2Fheads%2Fmain%2FREADME.md" rel="noopener noreferrer"&gt;&lt;strong&gt;Open this README on mkdn.review →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select any text in the rendered document, leave a comment, and click "Copy as JSON" to see the structured output.&lt;/p&gt;

&lt;p&gt;Want to try with your own project? Just replace the URL: &lt;code&gt;mkdn.review/?url=&amp;lt;your-github-raw-url&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local review&lt;/strong&gt; — if you have Node.js:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx mdxg-redline your-draft.md&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This generates a review HTML in the same directory and opens it in your browser. The generated file is fully self-contained — you can email it, drop it in Slack, or put it in a shared folder. Everything stays local; no content or comments are sent anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy note&lt;/strong&gt;: The standalone and CLI builds enforce &lt;code&gt;connect-src 'none'&lt;/code&gt; via CSP — your document body and comments &lt;em&gt;cannot&lt;/em&gt; leave the browser. The online version (&lt;code&gt;mkdn.review&lt;/code&gt;) likewise never sends your content or comments anywhere — the only network request is the &lt;code&gt;?url=&lt;/code&gt; fetch, which retrieves public raw content from a short allowlist (GitHub raw, Gist raw).&lt;/p&gt;

&lt;h2&gt;
  
  
  It's an MDXG implementation
&lt;/h2&gt;

&lt;p&gt;MDXG Redline is a third-party implementation of the &lt;a href="https://github.com/vercel-labs/mdxg" rel="noopener noreferrer"&gt;Markdown Experience Guidelines (MDXG)&lt;/a&gt; by Vercel Labs — the read-only Viewer rendering profile, with a review layer (inline commenting + structured JSON export) added on top. See the &lt;a href="https://github.com/oubakiou/mdxg-redline#mdxg-compliance-status" rel="noopener noreferrer"&gt;compliance table&lt;/a&gt; for details.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;MDXG Redline&lt;/strong&gt; is MIT-licensed and fully open source. If reviewing agent-generated documents is a bottleneck in your workflow, give it a try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mkdn.review/" rel="noopener noreferrer"&gt;&lt;strong&gt;Try the online viewer →&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oubakiou/mdxg-redline" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub repo →&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/mdxg-redline" rel="noopener noreferrer"&gt;&lt;strong&gt;npm →&lt;/strong&gt;&lt;/a&gt; &lt;code&gt;npx mdxg-redline draft.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code skill →&lt;/strong&gt; &lt;code&gt;gh skill install oubakiou/mdxg-redline md-review&lt;/code&gt; (&lt;a href="https://github.com/oubakiou/mdxg-redline#when-an-llm-invokes-the-cli-via-a-skill" rel="noopener noreferrer"&gt;usage details&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've tried it with your agent workflow, I'd love to hear how the structured JSON feedback format worked for you — drop a comment below or &lt;a href="https://github.com/oubakiou/mdxg-redline/issues" rel="noopener noreferrer"&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>markdown</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
