今日已更新 133 条资讯 | 累计 37382 条内容
关于我们

标签:#devto

找到 175 篇相关文章

开发者

Testare e debuggare estensioni Chrome con un coding agent: DevTools for agents in pratica

Caricare un’estensione da disco, aprirne il popup e automatizzare verifiche UI: un workflow più completo per chi sviluppa estensioni e usa agenti. Sviluppare un’estensione Chrome oggi significa spesso alternare tre modalità: codice “a mano”, generazione assistita da un coding agent e una fase di verifica nel browser che resta comunque imprescindibile. Il problema è che molti agenti riescono ad aprire pagine e cliccare elementi, ma si fermano quando entrano in gioco le estensioni: installazione, gestione del popup, interazioni con la UI dell’estensione, verifica rapida dei cambiamenti. Chrome DevTools for agents colma proprio quel vuoto: aggiunge al set di strumenti dell’agente la possibilità di installare e pilotare un’estensione durante i test, oltre a renderne più pratico il debugging. Quando è davvero utile Ci sono alcuni scenari tipici in cui il supporto “estensioni-aware” fa la differenza: Ciclo di feedback più rapido : compili/packi l’estensione, la carichi in Chrome e verifichi subito il popup o una content script UI. Test end-to-end più realistici : invece di simulare una UI in una pagina fittizia, testi l’estensione nel suo contesto reale (action popup, permessi, storage, ecc.). Validazione automatizzata : l’agente può controllare che l’estensione si installi correttamente, che il popup si apra e che i componenti principali siano presenti e interagibili. In pratica: se il tuo agente sa “guidare” il browser ma non sa “gestire” le estensioni, la qualità del test rimane limitata. Setup: abilitare esplicitamente gli strumenti per le estensioni Un dettaglio importante: per ragioni di sicurezza e controllo (in particolare per l’uso dei token e del contesto in cui operano gli agenti), le funzionalità specifiche per estensioni non sono abilitate di default . Dopo aver installato Chrome DevTools for agents, serve quindi un passaggio esplicito nella configurazione MCP: individua il tuo file di configurazione MCP ; abilita la categoria dedicata alle estensioni aggiung

2026-08-29 原文 →
AI 资讯

Parallel coding agents without the carnage

We build GPTree with several coding agents working the same repository at once: Claude Code, Codex, and Cursor, each in its own git worktree. The failure that finally made us build tooling for it was small and completely silent. One session was told to replace PaymentService with a Stripe-specific implementation. Another was told to add PayPal support to PaymentService . Different worktrees. Different files. Zero textual conflict. Git merged both branches cleanly, and the second change now depended on an extension point the first had deleted. Nothing in the toolchain had an opinion about it at any moment. Git compares diffs. It cannot compare plans. Worktrees isolate files, not plans Worktrees became the standard answer to parallel agents for a good reason: two sessions editing one checkout will overwrite each other's files and poison each other's context. Isolated checkouts fix that completely. But three failure modes survive file isolation, because they were never about files: Destructive versus additive. One agent removes or replaces a thing another agent is building on. The example above. Merges clean, breaks the design. Duplicate work. Two agents solve the same problem from different angles because nothing assigned ownership. You pay twice and then pay again to reconcile. Contract drift. One agent changes an API, a schema, or a config contract while another codes against the old shape. Compiles, runs, disagrees at runtime. A shared task list helps with the second one, if every agent reads it, every time. Nothing in that setup catches the first or third, because the collision is between intentions, and intentions live in prompts, not in any file a tool can watch. Declare the work before doing it Foremerge is the internal tool we built for this, open-sourced this week. It is a coordination protocol that sits above Git: agents declare what they are about to do, before they do it, in a form precise enough to check. A declaration is an intent with one or more semant

2026-08-28 原文 →
AI 资讯

How I automated my content distribution with a DSH plugin I scaffolded myself

How I automated my content distribution with a DSH plugin I scaffolded myself Posting is easy. Posting everywhere, consistently, is the hard part. I wanted a single command that takes one markdown article and pushes it to Dev.to, GitHub (as a gist), and eventually Bluesky and Mastodon — without my ever touching those web editors again. So I built it as a plugin for DSH (DeepSeek Harness) , using a scaffolding tool that I published myself. Here's the story, the 3 pitfalls that cost me the most time, and how you can get the same thing running in about a minute. Why automate distribution at all? Writing in public is the cheapest compounding asset a developer has. But cross-posting manually has two failure modes: You skip platforms — the "I'll do it later" tab that stays open forever. You lose the content graph — each platform becomes a silo with a slightly different version. A plugin that accepts content + title + [platforms] and returns per-platform status + links removes both. One source, many destinations, audited every time. What I built A DSH content-automation plugin ( dsh-crosspost ) with: Platform adapters : Dev.to (real), GitHub gist (real), Bluesky + Mastodon (stubs, next milestone). BYOK credentials : your tokens live in your DSH profile config — never in code, no platform approval needed from the plugin author. Error classification : every adapter wraps HTTP in try/catch and returns auth / rate-limit / bad-request instead of a raw stack trace, so an agent can decide to retry or skip per platform. Parallel orchestration : one platform failing never blocks the others. The 3 pitfalls that cost me the most time 1. The stale latest dist-tag (the big one) npm install @deepseek-ai/dsh-tools gives you a stale 0.0.1-rc.1 — the real line lives under the next tag. Wasted an evening debugging failures that were purely "wrong version resolved." Lesson: check dist-tags before installing anything in a fast-moving young ecosystem ( npm view pkg dist-tags ). 2. Pure ESM + b

2026-08-27 原文 →
AI 资讯

MCP Was a Mistake. Here Are 200,000 Tokens That Prove It.

MCP Was a Mistake. Here Are 200,000 Tokens That Prove It. "mcp were a mistake. bash is better." — Peter Steinberger, OpenClaw founder I didn't want to believe it either. MCP was supposed to be the USB-C of AI — one protocol to connect everything. Anthropic, OpenAI, Google all backed it. 97 million monthly downloads. 17,000 servers. But then I measured what MCP actually does to your context window. The Setup I connected 10 popular MCP servers to a token counter. Here's what happened before I typed a single word: Server Tools Tokens Injected Filesystem 11 3,847 Brave Search 8 2,103 Sequential Thinking 3 890 Memory 9 2,567 Puppeteer 15 5,890 Postgres 19 8,231 Notion 24 13,780 GitHub 28 12,440 Slack 22 14,672 Google Drive 31 47,293 Total 170 111,713 111,713 tokens. Before your first message. That's not a typo. Connecting 10 MCP servers to Claude means over 100K tokens of JSON schemas get injected into your context window. You haven't asked a question yet. You haven't made a tool call. The schemas are just... sitting there. The Math That Made Me Angry At Claude 3.5 Sonnet pricing ($3/M input tokens): Every conversation starts with 111K tokens of overhead: $0.33 20 conversations per day: $6.67/day 22 working days per month: $147/month Annual cost of JSON schemas: $1,764 That's more than a Claude Pro subscription. You're paying $1,764/year to read JSON braces describing tools you might never use. But Wait — It Gets Worse The 111K is just the schema injection. When you actually call a tool, MCP wraps the result: { "content" : [ { "type" : "text" , "text" : "{ \" file \" : \" app.py \" , \" size \" : 1024}" } ] } The actual content is 38 characters. The wrapping is 47 characters. 55% of your result tokens are JSON overhead. With 20 tool calls per conversation: Schema injection: ~111K tokens Result wrapping: ~18K tokens Total overhead: ~130K tokens per conversation Your $0.54 conversation now has 130K tokens that serve zero purpose. What Garry Tan Was Right About When YC's CE

2026-08-23 原文 →
AI 资讯

Claude Code Is Burning Your Token Budget. Here's the Receipt.

Claude Code Is Burning Your Token Budget. Here's the Receipt. I found $2,500/year of hidden token waste in my Claude Code setup. It was the MCP servers. The Discovery Last week I noticed my Claude Code conversations were dying at around message 15. Context window full. The model starts forgetting earlier instructions. Tool calls fail. The conversation degrades into hallucination. I assumed it was my fault — too many messages, too much context. So I started measuring. Here's what I found: Session start: Claude system prompt: ~8,000 tokens MCP schema injection: ~111,000 tokens User's first message: 50 tokens ────────────────────────────────────────── Total before any work: ~119,000 tokens Remaining context: ~81,000 tokens I was starting every conversation with 60% of my context already consumed. The culprit wasn't my prompts. It was the 10 MCP servers I had proudly configured in my claude_desktop_config.json . The Receipts I measured each server's schema injection using tiktoken: Server Why I Installed It Token Cost Times Used/Week GitHub PR reviews, issues 12,440 3 Slack Message reading 14,672 0 Google Drive Doc access 47,293 1 Notion Knowledge base 13,780 2 Postgres Query DB 8,231 4 Puppeteer Screenshots 5,890 0 Filesystem File access 3,847 15 Brave Search Web search 2,103 5 Memory Context persistence 2,567 0 Sequential Thinking Reasoning 890 2 Total 111,713 Look at the "Times Used/Week" column. Three servers were used zero times. Two more were used once or twice. But every single one of them was injecting 100% of its schema into every conversation. I was paying $0.33 per conversation — $2,500/year — to load schemas for tools I barely used. The Moment I Realized Everyone Has This Problem I posted my findings on Bluesky. Within hours: "I had the same issue. Removed 6 MCP servers and my conversations went from dying at message 15 to lasting 40+ messages." — @developer1 "GitHub MCP is 12K tokens but Claude Code already has gh CLI built in. Why did I install it?" — @dev

2026-08-23 原文 →
AI 资讯

Garry Tan Was Right: "MCP Sucks Honestly." I Have the Token Receipts.

Garry Tan Was Right: "MCP Sucks Honestly." I Have the Token Receipts. "MCP sucks honestly. Context window eats too much, auth is a mess. I wrote a CLI wrapper in 30 minutes and it works better." When YC's CEO says this on X, people listen. But nobody had the data to back it up. Until now. What Garry Tan, Perplexity's CTO, and 97 Million Downloads Can't Hide Three things happened in the last 6 months that changed how I think about MCP: Peter Steinberger (OpenClaw founder) tweeted: "mcp were a mistake. bash is better." Eric Holmes wrote "MCP is dead. Long live the CLI" — it hit HN frontpage Denis Yarats (Perplexity CTO) publicly announced they're replacing MCP with REST API + CLI internally Garry Tan (YC CEO) replied: "MCP sucks honestly" The community split into two camps: "MCP is dead" — CLI is simpler, cheaper, faster "MCP is fine" — 97M downloads, 17K servers, it's the standard Both are wrong. The problem isn't MCP. The problem is what MCP does to your context window. The 47,000-Token Problem Nobody Measured I connected 10 MCP servers to a token counter. Here's what I found: MCP Server Tools Token Cost Equivalent Sequential Thinking 3 890 This blog post Brave Search 8 2,103 A short email Filesystem 11 3,847 A README Memory 9 2,567 A meeting note Puppeteer 15 5,890 A chapter of a book Postgres 19 8,231 A whitepaper GitHub 28 12,440 A court filing Notion 24 13,780 A legal contract Slack 22 14,672 A novella chapter Google Drive 31 47,293 Half of a novel Total 170 111,713 A short book One MCP server — Google Drive — injects 47,293 tokens into your context before you ask a single question. The entire works of Shakespeare is 900K tokens. Google Drive's schema is 5% of Shakespeare. For listing files. The Cost Breakdown (So You Can Get Angry Too) At Claude 3.5 Sonnet pricing ($3/M input tokens, $15/M output): Scenario Tokens Cost Annual Cost 1 server (minimal) 3,847 $0.01/conv $4.40/yr 3 servers (common) 14,528 $0.04/conv $19.40/yr 5 servers (typical) 33,061 $0.10/conv $4

2026-08-23 原文 →
AI 资讯

I Benchmarked 10 MCP Servers — One of Them Burns 47K Tokens Just to Say Hello

I Benchmarked 10 MCP Servers — One of Them Burns 47K Tokens Just to Say Hello 10 popular MCP servers. 847 tools total. 312K tokens of JSON schemas. One server alone wastes more tokens than a full GPT-3 conversation. Here are the results. What I did I installed the 10 most popular MCP servers from the official registry. Connected each one to a token counter. Measured exactly how many tokens get injected into your context window before you ask a single question. The servers: # Server Tools Token Cost 1 Filesystem 11 3,847 2 GitHub 28 12,440 3 Postgres 19 8,231 4 Puppeteer 15 5,890 5 Brave Search 8 2,103 6 Memory 9 2,567 7 Sequential Thinking 3 890 8 Slack 22 14,672 9 Google Drive 31 47,293 10 Notion 24 13,780 Totals: 847 tools across 10 servers 111,713 tokens of JSON schemas 200,000+ tokens including server status messages, headers, and error schemas That's right — connecting 10 MCP servers to Claude means 200K tokens of overhead before your first message . The worst offender: Google Drive Google Drive's MCP server exposes 31 tools. Each tool has deeply nested schemas for file operations, permission management, sharing, and search. The full schema dump: { "name" : "drive.files.list" , "description" : "Lists files in the user's Google Drive with optional filtering" , "inputSchema" : { "type" : "object" , "properties" : { "q" : { "type" : "string" , "description" : "Query string for filtering files..." }, "corpora" : { "type" : "string" , "enum" : [ "user" , "domain" , "sharedDrive" , "allDrives" ]}, "includeItemsFromAllDrives" : { "type" : "boolean" }, "orderBy" : { "type" : "string" }, "pageSize" : { "type" : "integer" }, "pageToken" : { "type" : "string" }, "spaces" : { "type" : "array" , "items" : { "type" : "string" }}, "supportsAllDrives" : { "type" : "boolean" }, "fields" : { "type" : "string" } }, "required" : [] } } That's ONE tool. 31 of them. At ~1,525 tokens per tool average. 47,293 tokens. Just for Google Drive. For comparison, the entire works of Shakespea

2026-08-23 原文 →
AI 资讯

How to structure your RSS Feed for DEV.to Ingestion

A guide to formatting an RSS 2.0 feed so DEV.to imports your articles, images, and tags with zero formatting errors. 1. Quick Checklist: What to Do [ ] Wrap full article HTML inside <content:encoded><![CDATA[...]]></content:encoded> . [ ] Convert all image src , srcset , and link href attributes to absolute URLs ( https://domain.com/... ). [ ] Sanitize tags ( <category> ): alphanumeric only ( a-z0-9 ), max 20 chars, max 4 tags per post. [ ] Provide a unique <guid isPermaLink="true"> to prevent duplicate imports. [ ] Provide cover images via <enclosure> and as the first <img> inside <content:encoded> . [ ] In DEV Settings, keep "Mark RSS source as canonical" checked and "Replace self-referential links" unchecked. 2. RSS Field Reference <item> Fields Field Requirement What It Does on DEV.to <title> Required Article headline. Escape XML special characters. <link> Required Canonical link back to original post. <guid> Required Unique ID. Prevents re-importing duplicates on sync. <content:encoded> Required Full HTML body wrapped in <![CDATA[...]]> . Converted to Markdown by DEV. <description> Fallback Excerpt/summary. Used as body only if <content:encoded> is missing. <pubDate> Recommended UTC date ( Wed, 19 Aug 2026 10:00:00 GMT ). Sets publication/draft date. <category> Optional (Max 4) Becomes post tags. Must be alphanumeric and $\le$ 20 chars. <enclosure> Optional Sets the post's cover/hero image ( type="image/webp" or image/png ). <author> Optional email@domain.com (Author Name) 3. Strict Formatting Rules Rule 1: Tags ( <category> ) DEV.to rejects or corrupts tags that don't match [a-zA-Z0-9] : Remove special chars: next.js $\rightarrow$ nextjs , web-dev $\rightarrow$ webdev , c# $\rightarrow$ csharp . Truncate: Maximum 20 characters per tag. Limit: Maximum 4 tags per post. Rule 2: Images & Links (Must Be Absolute) DEV.to cannot resolve relative paths like /images/hero.png . ❌ <img src="/images/hero.png"> ✅ <img src="https://yourdomain.com/images/hero.png"> ❌ <a href

2026-08-20 原文 →
AI 资讯

A 2-Token Prompt and a 39,966-Token Bill: Measuring What My Agent Actually Costs

There is a small cluster of posts going around right now about auditing your LLM invoice, and about how cost calculators get the numbers wrong. I went to check mine and hit a problem before I got to the arithmetic: my pipeline doesn't produce an invoice, and the plumbing I built two months ago is the reason why. This project has a script, git_commit.py , that turns a staged git diff into a Conventional Commit message. It shells out to the Claude CLI. There is no ANTHROPIC_API_KEY anywhere in the project, on purpose — an early version used urllib against the API directly and broke immediately for anyone running on an OAuth session instead of a raw key, so every AI call in the repo goes through a claude -p subprocess instead. That decision is still right. It also means there is no API key, so there is no per-key usage dashboard, so there is no line item to audit. For several months this script has been making a model call on essentially every commit, and I have never once known what any of them cost. The call site throws the numbers away Here is the actual invocation, trimmed: raw = subprocess . check_output ( [ " claude " , " -p " , " --safe-mode " , SYSTEM + " \n\n " + diff ], text = True , timeout = 20 , env = _claude_subprocess_env (), ) subprocess.check_output returns stdout. With the CLI's default output format, stdout is the commit message string and nothing else. Every number I would want — tokens in, tokens out, dollars — is computed on the other side of that call and then discarded, because I asked for a string and a string is what I got. This is the part I want to flag for anyone wiring up a headless model call the same way. It isn't that the metering is missing. It's that the default output format is lossy in exactly the dimension you'd later want to audit, and you won't discover that by reading your own code, because your own code looks fine. It asks for text, it gets text. The fix is one flag: raw = subprocess . check_output ( [ " claude " , " -p " , " -

2026-08-19 原文 →
AI 资讯

Vector Search Lands in DynamoDB Natively — Issue #89

This week shipped one of the more consequential infrastructure changes in a while: DynamoDB absorbed vector search, collapsing a common two-database architecture into one. Meanwhile, a CMU study put hard numbers on something senior engineers have suspected about AI coding tools, and a 3B parameter model posted reasoning scores that have no business coming from a model that size. DynamoDB adds native vector search without a separate database AWS added a SearchVectors API to DynamoDB, letting you store embeddings alongside your application data and query them directly—no Pinecone, no Weaviate, no synchronization layer between your transactional store and your vector index. This matters because the dual-database pattern is genuinely painful at scale. You write to DynamoDB, you write to your vector DB, you manage consistency between them, you pay for two systems, and you debug failures in both. For RAG pipelines and semantic search on data that already lives in DynamoDB, that overhead exists purely because vector search wasn't available where your data was. Now it is. Setup requires picking an embedding model (Bedrock, Cohere, or OpenAI), configuring a vector index with dimensions and distance function, and rewriting retrieval queries to SearchVectors . Vector operations are billed separately per GB across writes, reads, and storage—so run the math before assuming this is cheaper than your current setup. Verdict: Ship if you're already on DynamoDB and maintaining a separate vector DB. The architectural simplification is real. Start with a proof-of-concept on a non-critical workload to validate cost and latency before migrating production RAG infrastructure. AI coding speed spike vanishes in three months Carnegie Mellon tracked 806 repositories after Cursor adoption and found that the velocity boost disappears by month three. What doesn't disappear: a 30% increase in warnings and 41% higher code complexity that persists indefinitely and cuts future velocity by 50–64%. Th

2026-08-18 原文 →
AI 资讯

My linter kept warning the people who did it right. Three times, in the same direction

The warning landed on the only people who had done it properly I maintain a linter that reads agent config files — SKILL.md , AGENTS.md , CLAUDE.md — and fails CI when they bake in something that only works on the author's machine. One of its rules says: if you call an external CLI, declare it, or the next person won't have it. Declaring it means naming it in frontmatter: requires : codex Except that anyone with more than one dependency writes the list form, because that's what YAML is for: requires : - codex - gemini My implementation only read the first shape. So the block list — the normal way, the way you write it the moment you have two of anything — was invisible to the linter, and it warned you for an undeclared CLI that you had, in fact, declared. Read that back slowly. Authors who ignored the dependency question entirely were never flagged, because they never wrote a requires: key at all. Authors who sat down and wrote the contract properly got a warning telling them they hadn't. The rule was inverted with respect to the thing it was trying to encourage. I shipped that. It went out in a patch release, and I only found it because a commenter used the phrase "dependency contract" and I went to re-read my own implementation of it. Then it happened again. Twice, in one release Two comments on a post of mine turned into new rules. One of them, unverified-write , reports a file that changes external state — git push , npm publish , an INSERT — and never reads that state back anywhere. Before publishing, I ran it over 586 real skill files pulled from a public registry, found two false-positive shapes in the data, fixed both, and re-measured. Fire rate 0.7%, and every hit I could check by hand was genuine. I felt good about it. Then I handed the diff to a different model for a pre-publish read, and it produced this input in about a minute: Never run `git push --force` from this skill. That is a git push in a code span, in a file with no read-back anywhere. My rule

2026-08-17 原文 →
AI 资讯

GoFullPage got pulled. Here is how to take a full-page screenshot without any extension.

On 11 August the GoFullPage extension disappeared from the Chrome Web Store and got disabled in Chromium browsers. Eleven million users, one Tuesday. It was not a hack. The developers say it was a copyright dispute over a design element, that it was "definitively not a security issue", and that they are working with Google on getting it back. Chrome shows the same "might be unsafe" string for every kind of Web Store policy breach, so the warning read far worse than the cause. Two things came out of it. A short list of fixes, and a longer thought about where our tools live. Get working again in a minute Re-enable it. Open chrome://extensions . If Chrome disabled the extension rather than deleting it, the toggle is still there. Use Edge. GoFullPage was never removed from the Edge add-ons store. Install the beta. The team published a separate build at ID kehafhfdnkhdgbnpeofmhmbibmpnjaof , and it can sit alongside the original. That is the practical answer. The more interesting one is that most of us never needed the extension. Five ways to capture a full page with no extension at all 1. Chrome DevTools, no code Open DevTools, press Cmd/Ctrl + Shift + P , type screenshot , choose Capture full size screenshot . This has been in Chrome for years and most people have never found it. It handles scroll-height pages properly and drops a PNG in your downloads. 2. Firefox, even shorter In the Firefox console: :screenshot --fullpage Add --dpr 2 for a retina-density capture, or --clipboard to skip the file. 3. Chrome DevTools Protocol, if you want it scripted The thing the extension was wrapping is one CDP call: await client . send ( ' Page.captureScreenshot ' , { format : ' png ' , captureBeyondViewport : true , }); captureBeyondViewport is the flag that does the work. Everything else in a full-page screenshot tool is UI around it. 4. Playwright import { chromium } from ' playwright ' ; const browser = await chromium . launch (); const page = await browser . newPage ({ viewport

2026-08-16 原文 →
AI 资讯

Gemini 3.7 Flash: Coding Speed Breakthrough

This week's tooling landscape is defined by two themes: cost compression on capable models and protocol-level standardization across agent runtimes. Gemini 3.7 Flash cuts inference spend while measurably improving first-pass code accuracy, and the AI SDK's ACP harness layer is quietly making multi-agent wiring less of a bespoke nightmare. Here's what's worth your attention. Gemini 3.7 Flash launches with coding performance gains Gemini 3.7 Flash ships at half the cost of 3.6 Flash with benchmark improvements that actually map to real workloads: FrontierCode jumps from 34.4% to 43.6%, and document reasoning on GDP.pdf goes from 22.0% to 34.0%. These aren't marginal deltas—a 9-point gain on code generation means materially fewer retries in agentic pipelines where each failed generation compounds latency and cost. For teams running Flash in production for code generation or document extraction, the math is straightforward: same API surface, half the token cost, better first-pass accuracy. Introductory pricing holds through year-end, so the window to lock in the savings is finite. Verdict: Ship. Drop-in swap via the Gemini API—no config changes required. If you're already on Flash for coding or document processing workloads, migrate now. The performance gains on code generation are large enough to reduce retry loops in multi-step planning tasks, which compounds into real infrastructure savings at scale. GLM 5.2 free for eve agents through August 27 Z.ai's GLM 5.2 is a 1M-token open-weights model now set as the default on eve agents, with free access through Vercel's AI Gateway until August 27. The 1M context window is the practical differentiator here—it's large enough to hold entire codebases in context for generation tasks that would otherwise require chunking or retrieval. The cost is zero during the trial window, and the integration is a one-line config change: set model: "zai/glm-5.2" in agent/agent.ts or run eve set --model zai/glm-5.2 . That's a trivially low bar

2026-08-14 原文 →
AI 资讯

We Invented a Layered Wiki Pattern on Top of Graphify — Here's the Concept and How to Approximate It Today

"Graphify turns codebases into queryable knowledge graphs. We designed a layered monorepo wiki extension — per-layer .graphify/ folders with staleness hooks — that doesn't exist yet. Here's the full spec and how to get 90% of it right now." Transparency note: This post describes a design pattern we invented on top of graphify , an existing open-source tool. The core tool is real. The layered wiki structure and .graphify/ folder convention described here are not official graphify features — they are a proposal. We'll clearly mark every invented part. The "how to approximate it today" sections use only real, working graphify commands. The Problem: One Graph, Many Layers If you haven't used graphify yet, the short version: you run /graphify . inside Claude Code (or graphify . --wiki from your terminal), and it turns your entire codebase into a queryable knowledge graph. Claude can then answer questions like "how does the checkout flow work?" or "what calls PaymentService?" with file-and-line citations instead of hallucinated guesses. It works brilliantly for single-service repos. But for a monorepo that looks like this: my-repo/ ├── frontend/ ← TypeScript / React ├── api/ ← Java / Spring Boot ├── services/ │ ├── order-service/ ← .NET / C# │ └── notification-worker/ ← Python └── database/ ← SQL stored procedures …you hit a wall. Run graphify . at the root and everything lands in a single flat graphify-out/ folder. The community articles generated by the --wiki flag end up mixing TypeScript React components with Java Spring controllers with SQL stored procedures. When you're deep inside the frontend layer fixing a component, Claude is also loading a wiki article about your database trigger — noise you don't need. The real question: what if each layer had its own scoped graph and wiki, colocated with the source it describes? The Concept: Layered Graphify Wiki ⚠️ Everything in this section is a design proposal — not official graphify. The folder names, behaviours, and some

2026-08-14 原文 →
AI 资讯

My Frontmatter Parser Checks for Too Few Delimiters. It Never Checked for Too Many.

I fixed this script's frontmatter parser a week ago. A draft with an unclosed --- block used to blow up with a bare ValueError: not enough values to unpack , and I patched it to raise a clean, actionable error instead. I wrote that fix up, verified it with a stubbed repro, added a --selftest case for it, called it done. Then I went back to write today's articles and actually looked at the line I "fixed" instead of the error path around it. def parse ( text ): meta = {} body = text if text . lstrip (). startswith ( " --- " ): parts = text . lstrip (). split ( " --- " , 2 ) if len ( parts ) < 3 : raise ValueError ( " frontmatter opened with ' --- ' but never closed with a second ' --- ' delimiter " ) _ , fm , body = parts ... split("---", 2) doesn't split on lines that are --- . It splits on the literal substring "---" , anywhere in the text, and stops after the second one it finds. My fix only handles the case where it finds fewer than two — an unclosed fence. It says nothing about what happens when the second "---" it finds isn't the closing fence at all, because a third one showed up first, buried inside a frontmatter value. That's not a hypothetical. I write these article titles myself, and "before/after" is a phrase I reach for constantly: --- title : My Before---After Refactor tags : ai, python, refactor published : true --- real body starts here split("---", 2) finds the em-dash-style --- inside the title before it finds the real closing fence on its own line. So the split points land in the wrong place entirely: >>> from publish_devto import parse >>> meta , body = parse ( text ) >>> meta { ' title ' : ' My Before ' } >>> body ' After Refactor \n tags: ai, python, refactor \n published: true \n --- \n real body starts here \n ' The title got truncated to "My Before" . tags and published never got parsed as frontmatter fields at all — they're sitting in the body now, as literal text, along with the real closing fence and a stray leftover --- . If I ran this thr

2026-08-13 原文 →
产品设计

NETO: Chat P2P local para equipos dev — sin nube, sin excusas

¿Tu equipo comparte credenciales por Slack? ¿Discuten arquitectura en plataformas que almacenan cada mensaje en servidores ajenos? Existe una alternativa que no depende de la nube: NETO . ¿Qué es NETO? NETO es un chat peer-to-peer diseñado para redes locales . No hay servidor central, no hay cuentas, no hay datos saliendo de tu oficina. Abres el navegador, y los compañeros de tu LAN aparecen automáticamente gracias a mDNS (Multicast DNS), el mismo protocolo que usa Bonjour para descubrir impresoras y servicios locales. Sin registro. Sin configuración. Sin fricción. Cifrado de extremo a extremo real Cada conexión entre peers se establece mediante WebRTC , creando canales de datos directos entre navegadores. Antes de intercambiar un solo mensaje, NETO realiza un intercambio de claves con X25519 (Curve25519 en

2026-08-12 原文 →
AI 资讯

My Comment-Reply Pipeline Picks One Winner Per Thread. Two Commenters Broke That.

reply_comments.py is the script that tells me which DEV.to comments still need a reply. It walks every comment tree on every article I've published and reports the ones I haven't answered yet. I've fixed two bugs in it already: needs_reply() used to think a thread was "handled" forever after a single reply, even if the other person followed up again, and a dedup check was keyed on the thread's root comment instead of whichever message actually needed the reply, so a second round of conversation went permanently invisible. Both fixes are in --selftest now, and both looked, from the outside, like they'd covered this file's tree-walking logic pretty thoroughly. They hadn't. Today I found a third bug in the same handful of functions, and it survives even with both prior fixes applied. What the existing code assumes Comments on DEV.to come back from the API as trees. A top-level comment has a children list, and each child can have children of its own. The function that decides whether a thread needs attention is needs_reply() , built on latest_message() : def latest_message ( comment ): """ The most recently created message anywhere in this comment ' s subtree. """ latest = comment for c in comment [ " children " ]: candidate = latest_message ( c ) if candidate [ " created_at " ] > latest [ " created_at " ]: latest = candidate return latest def needs_reply ( comment ): return latest_message ( comment )[ " user " ][ " username " ] != ME This walks the whole subtree and returns exactly one message: whichever one has the latest timestamp, anywhere in the tree. _pending_entry() (the function pending() actually calls) is built directly on top of that single answer — it checks whether the latest message needs a reply, and if so, returns one entry for the whole thread. That's a reasonable design if a thread only ever grows one message at a time: root comment, my reply, their follow-up, my reply, and so on. Every test case in this file's --selftest , and both of the earlier bug

2026-08-12 原文 →
AI 资讯

A Space Before the `=` in My .env File Made a Credential Silently Disappear

I have four different load_env() functions in my MCP server project ( my-git-manager ) — one in server.py , one in publish_devto.py , one in reply_comments.py , one in scripts/list_all_published_titles.py . All four exist for the same dumb reason: this repo has no dependency on python-dotenv , so each script that needs GITHUB_TOKEN or DEV_TO_API reads .env by hand. I went digging for a fresh bug in this repo this week — I write a lot about it, and the well is getting shallow — and decided to actually diff all four load_env() implementations against each other instead of reading them one at a time like I usually do. They'd never been compared side by side before. That's how I found this one. The line that started it Every one of them does roughly this: for line in f : line = line . strip () if " = " in line and not line . startswith ( " # " ): k , v = line . split ( " = " , 1 ) os . environ . setdefault ( k , v . strip (). strip ( '"' ). strip ( "'" )) Look closely at what gets .strip() ed there. v — the value — gets stripped of whitespace and surrounding quotes. k — the key, the actual name of the environment variable — gets nothing. That's fine if your .env file looks like this: DEV_TO_API = abc123 It's not fine if it looks like this: DEV_TO_API = abc123 Spaces around = are a completely normal thing to type. Plenty of .env examples online use them. Plenty of people reach for that style out of habit from other config formats. And line.split("=", 1) doesn't care — it splits on the first = no matter what's next to it, so k comes out as "DEV_TO_API " , trailing space included. What that trailing space actually does os.environ.setdefault("DEV_TO_API ", "abc123") sets an environment variable. It's just not the one anything is looking for. Every caller in this repo does os.environ.get("DEV_TO_API") — no trailing space, because that's the name everyone actually types. That lookup returns None , or whatever was already sitting in the environment before .env ever got read. I

2026-08-12 原文 →
AI 资讯

How to Catch Android UI Layout Bugs in Seconds (Without Constant Screenshots)

Every mobile developer knows the frustration of "Design QA Day." You finish building a screen and send it to your UI/UX team or QA engineer. Then you receive a list of minor padding mismatch tickets. "This card padding should be 16dp, not 12dp." "The title baseline is slightly off on smaller device densities." Usually, fixing these issues means taking screenshots on devices, placing them onto a Figma canvas, lowering the opacity, and measuring pixels. You can streamline this entire process directly on your physical Android test devices using Designer Tools. Overlay Figma Comps Directly Over Live Apps Instead of comparing your app build side-by-side with a Figma preview on a monitor, you can overlay the target design file onto your screen using SYSTEM_ALERT_WINDOW permissions. Export your frame from Figma as a PNG. Load it into Designer Tools under Image Mockup Overlay. Set the opacity to 50%. When you open your app build underneath, any layout misalignment, incorrect text scaling, or constraint issue will become quickly visible as a drop-shadow ghost. Verify Density-Independent (dp) Grids Testing layouts across different device densities (mdpi, hdpi, xxhdpi) often results in unexpected spacing bugs. With the Custom Grid System in Designer Tools, you can create a grid native to dp: Set standard 4dp/8dp vertical and horizontal spacing grids. Set origin points (Top-Left, Center, or Safe Area bounds). You can verify component placement on target hardware instantly without manual measurements. Infinite Alignment Guides For measuring dynamic list items, headers, or bottom sheets, you can place interactive vertical and horizontal guidelines directly onto the active screen. This removes uncertainty about distances between different UI elements. Try It Out Designer Tools is lightweight and privacy-focused, as all image assets stay strictly on-device. It is built for Android engineers, QA teams, and UI designers. Download on Google Play: ( Pro Design: Designer Tools ) How doe

2026-08-12 原文 →