惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
C
Cybersecurity and Infrastructure Security Agency CISA
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Know Your Adversary
Know Your Adversary
S
Securelist
I
Intezer
AWS News Blog
AWS News Blog
L
LINUX DO - 热门话题
P
Privacy International News Feed
Recent Announcements
Recent Announcements
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
The GitHub Blog
The GitHub Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Schneier on Security
Schneier on Security
N
Netflix TechBlog - Medium
爱范儿
爱范儿
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
Hacker News: Ask HN
Hacker News: Ask HN
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
Blog — PlanetScale
Blog — PlanetScale
WordPress大学
WordPress大学
S
Secure Thoughts
K
Kaspersky official blog
N
News | PayPal Newsroom
O
OpenAI News
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tor Project blog
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
D
Docker
Hugging Face - Blog
Hugging Face - Blog
T
Threat Research - Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
博客园 - 司徒正美
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
P
Palo Alto Networks Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
HTML Is the New Markdown
Vishal Veera · 2026-05-17 · via DEV Community

A response to Thariq Shihipar's "HTML is the new markdown" post — and a practical answer for anyone watching their per-request costs creep up.


The tweet that started it

On May 8, Thariq Shihipar — a member of the Claude Code team at Anthropic — posted what is now one of the most-discussed dev takes of the quarter:

"HTML is the new markdown. I've stopped writing markdown files for almost everything and switched to using Claude Code to generate HTML for me."

The case he made was genuinely compelling. HTML, he argued, lets Claude do things markdown simply can't:

  • Inline SVG diagrams instead of fenced ASCII art
  • Interactive widgets — sliders, toggles, collapsible sections — so a PR review or architectural doc becomes a navigable artifact instead of a wall of text
  • In-page navigation, color-coded severity, real layout
  • Semantic structure the model can hang richer reasoning on

Thariq's example prompt — "Help me review this PR by creating an HTML artifact… color-code findings by severity" — captures the appeal in one line. The output looks like a small internal tool, not a chat log. Once you see it, going back to plain markdown feels like trading a dashboard for a printout.

Simon Willison agreed enough to write it up the same week. Then the dissents arrived.

The counter-argument: this is expensive

The most-shared rebuttal came from Kurtis Redux's "The Unreasonable Ineffectiveness of HTML". Three points landed:

  1. HTML is 2–4× slower to generate than the markdown equivalent — and roughly 2–4× more output tokens to render the same information.
  2. Verbose markup dilutes model attention. The longer the output, the easier it is for the model to lose the plot, repeat itself, or hallucinate structure halfway down.
  3. Output tokens are the expensive tokens. Across every major API price card, output is 3–5× the cost of input. Recommending 2–4× more output is a real line item.

Then came the uncomfortable subtext from a few corners of the timeline: Anthropic sells by token. Of course a Claude Code engineer wants you generating more of them.

I don't think that's fair to Thariq — he's been shipping thoughtful, often unflattering-to-Anthropic posts about prompt caching and token efficiency for a year. But the structural concern stands: the people best positioned to tell us how to use these tools also have the most to gain when we use them more.

The real question

The argument has been framed as a binary: rich-but-expensive HTML, or cheap-but-flat markdown. Pick a side.

That framing is wrong. The question that actually matters is:

Can I get the HTML output Thariq is excited about — without paying the HTML token bill?

The answer is yes, and most of it has nothing to do with which model you're using. It has to do with everything that happens around the model call. That's the slice I've been working on with Lynkr.

What's actually inflating your token count

Before talking about HTML output, it's worth being honest about where tokens actually go in a Claude Code-style session. In a typical agentic loop, the output HTML is the smallest chunk. The big spenders are:

  • The system prompt and tool definitions — re-sent every single turn. Claude Code ships with 50+ tools, each with verbose JSON schemas. That's tens of thousands of input tokens per turn before the user has typed anything.
  • Conversation history — every prior assistant message, every tool call, every tool result, replayed each step.
  • Tool resultscargo build, pytest -v, eslint ., git diff. A failing test run can dump 40k tokens of stack trace.
  • MCP tool catalogs — wire up half a dozen MCP servers and your tool schema can balloon past 100k tokens.

The HTML the model writes is real cost, but it's measured in hundreds-to-low-thousands of output tokens. The HTML-vs-markdown debate is fighting over the tip while the iceberg sits unchallenged.

If you want HTML outputs without a wince at the invoice, the lever isn't "stop generating HTML." The lever is "stop sending the model a quarter-million tokens of repeated context to get to that HTML."

How Lynkr attacks the iceberg

Lynkr is a self-hosted proxy that sits between your coding tool (Claude Code, Cursor, Codex CLI, Cline, Continue) and any of 13+ LLM providers. It speaks Anthropic's /v1/messages and OpenAI's /v1/chat/completions, so the client doesn't know it's there. What it does in the middle is the interesting part. A few of the layers most relevant to the HTML-output discussion:

0. Preflight short-circuit (zero tokens)

The most extreme expression of the thesis. Before any model call happens, Lynkr can run a user-supplied shell precondition — pytest path/to/test.py, tsc --noEmit, lint --quiet, whatever proves the work is already done. If every command exits 0, Lynkr returns a synthetic "preflight satisfied" response without calling the LLM at all.

The use case sounds niche until you run a real agent loop: a CI-triggered "fix the failing test" request that arrives 90 seconds after the test was already fixed on another branch. An idempotent agent retry. A scheduled refactor job whose work was finished by a previous run. Today, every one of those wastes a full agentic loop — sometimes hundreds of thousands of tokens — to rediscover that the answer is "nothing to do."

The most expensive HTML output is the one you generate to explain a problem that no longer exists. Preflight is the layer that just doesn't.

Opt-in via preflight_commands in the request payload, gated on LYNKR_PREFLIGHT_ENABLED=true. Inspired by the CodexSaver routing patterns.

1. Smart tool selection (~50–70% token reduction on tool defs)

Claude Code sends every registered tool definition on every turn. Lynkr classifies the incoming request — is this a code edit, a search, a refactor, a "generate an HTML artifact" task? — and ships only the tools that classification actually needs. The model doesn't see the 40 it won't use.

For an "HTML artifact" task specifically, you don't need Bash, Glob, Git, the test runners, or MCP tools. You need read, write, and maybe web search. The savings compound across every turn of the loop.

2. Tool result compression

When the model calls pytest and gets back 40k tokens of output, Lynkr's tool-result compressor detects the pattern (test runner, linter, build, git diff) and compresses it before the model sees it on the next turn — usually keeping the failing assertions and dropping the redundant traceback frames. A tee cache holds the full version if anything downstream needs it.

In an agentic HTML-generation flow ("read the codebase, then produce an HTML report"), tool results are typically the largest single token category. Compressing them shrinks every subsequent turn.

3. History compression (Distill-style structural dedup)

Long sessions accumulate near-duplicate state: the model re-reads the same file four times, re-runs a slightly-different version of the same query, repeats its own reasoning. Lynkr's history compressor deduplicates older turns structurally while preserving the most recent N verbatim. The model still has the context; it doesn't pay for it twice.

4. Code Mode for MCP (~96% reduction)

If you've wired up MCP servers, this one's almost embarrassing. A typical MCP catalog — Linear, GitHub, Notion, Slack, a few internal ones — is 100+ tool definitions and tens of thousands of tokens every turn. Lynkr's Code Mode replaces all of them with four meta-tools (listResources, readResource, callTool, searchTools) and lets the model discover the rest at runtime. Same capability surface, ~96% fewer tokens spent on the catalog.

5. Risk-aware smart routing across model tiers

This is the one most directly relevant to the HTML debate. Generating a polished HTML artifact really does want a strong model. But the fifteen prior turns that gathered the data, ran searches, and figured out what to put in that artifact often don't.

Lynkr routes on two orthogonal axes: a 15-dimension complexity analysis (how hard is the task) and an independent risk score (how dangerous is it if the model gets this wrong). A request that touches auth/*, payments/*, migrations/*, .env, or .github/workflows, or that names high-risk concepts like authentication or deployment, is forced to the COMPLEX tier regardless of complexity score. Cheap tier for the cheap turns; frontier tier whenever the blast radius warrants it.

The four configurable tiers — TIER_SIMPLE, TIER_MEDIUM, TIER_COMPLEX, TIER_REASONING — let you map each to whatever provider:model pair makes sense. A greeting goes to a local Ollama model and costs zero. A file-read summarization goes to Haiku. The final "now write the HTML artifact" call goes to Opus or Sonnet, where it belongs.

Pay frontier prices for frontier work and high-risk work. Pay nothing for the rest.

Optionally, LYNKR_VISIBLE_ROUTING=true attaches a human-readable interaction block to each response — tier, provider, model, risk level, estimated savings — so the routing decision shows up inside Claude Code instead of buried in headers no one reads.

6. Semantic and prompt caching

Identical requests hit the prompt cache (SHA-256 keyed LRU, 5min TTL). Near-identical requests — same intent, different phrasing — hit the semantic cache (embedding cosine similarity at 0.95). For repeated "generate an HTML report of X" prompts within a working session, the second call can be effectively free.

7. Headroom sidecar (optional ML compression)

For users who really want to push it, there's an optional Python sidecar running LLMLingua-style transforms (Smart Crusher, Continuous Context Reduction, Tool Crusher, Cache Aligner, Rolling Window). Pure context-side compression — the model output doesn't change, the input it operates on gets smaller.

8. Token budget enforcement

Each model's context window is tracked. At 85% utilization, Lynkr automatically applies adaptive compression rather than letting the request blow past the window mid-generation. You don't get the 400-error-then-retry burn that costs you the input tokens twice.

What this looks like in practice

A concrete scenario: you ask Claude Code to "review this PR and produce an HTML report grouped by severity" — exactly Thariq's example.

Without a proxy layer, that's 8–12 model turns. Each turn re-sends the full system prompt, 50+ tool definitions, the growing conversation history, and accumulated tool results. The final turn produces ~2,000 tokens of HTML. Total input cost across the run: somewhere between 400k and 1.2M tokens depending on repo size. The HTML output is maybe 0.5% of the bill.

With Lynkr in the middle:

  • If the PR's findings are already merged or the failing check has self-resolved, preflight returns "satisfied" without a single model token spent.
  • Smart tool selection trims the per-turn tool-def overhead by ~60%.
  • Tool result compression keeps git diff and test output from dominating subsequent turns.
  • History compression dedupes the redundant intermediate state.
  • Risk-aware routing sends the search/read turns to a cheap tier; the final HTML generation — and anything touching protected paths — goes to your strongest model.
  • The semantic cache catches the second time you ask for the same review.

You keep the rich HTML output. You stop paying for the parts of the run that don't earn their tokens.

The takeaway

Thariq is right. HTML output really is better for the kinds of artifacts coding agents produce — and "we should use markdown because tokens are expensive" is an argument from a 32k-context-window world we no longer live in.

The critics are also right. HTML is more expensive than markdown to generate, the cost matters, and "use the richer format" without a story for cost control is a recommendation that benefits the seller more than the buyer.

What's missing from both sides of the timeline is the recognition that the output format is not the cost lever. The cost lever is everything upstream of the final response: which tools you send, how you compress prior turns, which tier you route to, what you cache, whether the work even needs to run at all.

Generate the HTML. Then put a smarter proxy in front of the model so you can afford to do it again tomorrow — and so that sometimes, when the answer is already on disk, you don't have to.


Lynkr is open source (Apache 2.0) and self-hosted: https://github.com/Fast-Editor/Lynkr. Install with npm i -g lynkr, point your coding tool's base URL at localhost:8080, and you're routing.

If you've measured your own HTML-vs-markdown token deltas in real workflows, I'd love to compare numbers — reply with your results.