AI 资讯
Stop your coding agent from cat-ing .env: a Claude Code hooks cookbook
Your coding agent is a process that reads your filesystem and runs shell commands with your credentials. Most of the time that is exactly what you want. Occasionally it is cat .env while debugging - and now your production keys live in a transcript forever - or a confident rm -rf on a path that resolved differently than expected. Everyone's first fix is to add rules to CLAUDE.md: "never read .env, never force push". Those are suggestions to a language model. They work until they don't, and you will not be watching when they don't. Claude Code has a mechanism that is not a suggestion: hooks. A hook is a program you register for specific events - before a tool call, after it, when the session tries to end. It runs outside the model, sees the exact tool call as JSON on stdin, and its verdict is enforced by the harness itself. The model cannot talk its way past it, but it CAN read a structured denial and route around it productively. This is a cookbook for writing them. Everything below is plain Python stdlib and works on current Claude Code as of August 2026. The mechanics in ninety seconds Hooks are registered in settings ( .claude/settings.json in a project, ~/.claude/settings.json globally): { "hooks" : { "PreToolUse" : [ { "matcher" : "Read|Grep|Bash" , "hooks" : [ { "type" : "command" , "command" : "python3 \" ${CLAUDE_PROJECT_DIR}/.claude/hooks/secret-guard.py \" " , "timeout" : 10 } ] } ] } } The matcher filters by tool name. Your command receives a JSON object on stdin describing the event; for PreToolUse it includes tool_name and tool_input (the exact arguments about to run). You respond on stdout with JSON. Three responses cover almost everything: Deny a tool call, with a reason the model will read: { "hookSpecificOutput" : { "hookEventName" : "PreToolUse" , "permissionDecision" : "deny" , "permissionDecisionReason" : "why, and what to do instead" } } Block a session from ending (Stop event), sending work back: { "decision" : "block" , "reason" : "lint failed
AI 资讯
Parallel Coding Agents Need Handoffs, Not More Terminals
The concrete problem Running two or three coding-agent sessions is easy. Knowing when their work is safe to combine is not. One session changes an API while another writes regression tests against the old shape. A third investigates a production failure and quietly edits the same configuration file. Git worktrees prevent immediate filesystem collisions, but they do not explain task dependencies, transfer assumptions, or warn that two agents are solving incompatible versions of the problem. The developer becomes a human message bus: checking terminals, copying commit IDs, repeating context, and deciding which session should wait. The more capable each agent becomes, the less useful a wall of terminal panes is as a coordination interface. The current signal Claude Code now supports messaging between sessions on the same machine. Its documentation describes session discovery, plain-text messages, and a local messaging socket. Agent view separately exposes background-session state, worktrees, pull-request status, and a JSON listing suitable for scripts. Hooks can observe tool input and block a tool call before execution. That does not prove demand for a new product. It does create a concrete implementation moment: the primitives for handoffs and visibility exist, while dependency ownership and conflict negotiation remain a workflow problem. In RayTally's bounded Hacker News snapshot at August 9, 00:33 UTC, the cross-session messaging discussion had 50 points and 26 comments and ranked 18th. Those numbers describe that historical observation only; they are not user counts, market validation, or a prediction of lasting interest. A product direction: a control desk for handoffs The useful product is not another chat window. It is a small local control desk that makes each session declare four things: its goal, worktree, files it expects to touch, and the result another session is waiting for. When the API session finishes, the testing session should receive a compact hando
AI 资讯
What you save when project context stops repeating
Qarinah compiles a compact, cited project-memory pack instead of asking every new coding-agent session to replay the entire available history. The published estimate Across six committed software-task fixtures, the full-history baseline contained 442,113 portable estimated input-context tokens . The Qarinah path used 5,682 . Every required target was still directly covered in the top five results. That is: 436,431 fewer estimated input-context tokens; 98.71% less repeated context; and a 77.81:1 baseline-to-pack ratio. The ratio is not a claim that every provider bill drops by 98.71%, or that an agent session lasts 77.81 times longer. It measures the compared input-context volume in the published six-fixture estimate. What the same token rate would cost The table applies four flat, uncached input-token rates to the same two token estimates. It is arithmetic, not a provider invoice. Flat uncached input rate Full-history baseline Qarinah pack Estimated saving $1 / million tokens $0.442113 $0.005682 $0.436431 $3 / million tokens $1.326339 $0.017046 $1.309293 $5 / million tokens $2.210565 $0.028410 $2.182155 $15 / million tokens $6.631695 $0.085230 $6.546465 The calculation is: estimated tokens / 1,000,000 x flat input rate It deliberately excludes provider-native tokenization, caching, output tokens, reasoning tokens, tool calls, retrieval, hosting, and fixed fees. Real cost depends on the provider, model, cache behavior, context composition, and how often the same history would otherwise be resent. Why the pack remains useful Compression only matters if the next task can still find its evidence. The benchmark checks both volume and retrieval coverage: every required target had to be directly present in the top five. Qarinah preserves the source event ID and content hash for selected context, so a later agent receives a bounded handoff that can be inspected instead of an opaque story. Qarinah also passed 380 of 380 deterministic file-specific exact and typo-tolerant que
开发者
NETO: Chat P2P local para equipos dev sin depender de la nube
¿Tu equipo comparte tokens, contraseñas de staging o discute arquitectura sensible por Slack? Cada mensaje viaja a servidores de terceros. NETO es una alternativa radical: un chat peer-to-peer que funciona exclusivamente en tu red local, sin cuentas, sin nube, con cifrado de extremo a extremo. ¿Qué es NETO? NETO es una herramienta de mensajería diseñada para equipos de desarrollo que comparten la misma red. No hay servidor central, no hay registro, no hay datos que salgan de tu oficina o VPN. Abres la app y empiezas a hablar. ¿Cómo funciona por debajo? Descubrimiento con mDNS : NETO utiliza multicast DNS para encontrar automáticamente a otros peers en la red local. Sin configurar IPs ni puertos manualmente: si estás en la misma red, apareces. Cifrado con X25519 : Cada par de usuarios negocia claves efímeras mediante el
AI 资讯
My Commit-Message Script Has 8 Assertions in --selftest. None of Them Touch the Code That Can Actually Fail.
I have three files in this repo that shell out to something over the network or a subprocess and can fail in interesting ways: publish_devto.py , server.py , and git_commit.py . Two of them have --selftest blocks that stub the risky call and exercise the actual failure branches. One doesn't, and I only noticed because I went looking for a reason to be suspicious of my own test coverage after seeing a trending post about counting assertions in a test suite and not liking what you find. git_commit.py reads a staged diff and calls claude -p to turn it into a commit message. It has five distinct exit paths, all guarding real failure modes I've hit before in this project: try : diff = subprocess . check_output ([ " git " , " diff " , " --staged " ], text = True , timeout = 20 ) except subprocess . TimeoutExpired : print ( " git diff --staged timed out after 20s " , file = sys . stderr ) raise SystemExit ( 1 ) if not diff . strip (): print ( " Nothing staged. Run `git add` first. " ) raise SystemExit ( 1 ) try : raw = subprocess . check_output ( [ " claude " , " -p " , " --safe-mode " , SYSTEM + " \n\n " + diff ], text = True , timeout = 20 , stderr = subprocess . PIPE , ). strip () except subprocess . TimeoutExpired : print ( " claude -p timed out after 20s " , file = sys . stderr ) raise SystemExit ( 1 ) except subprocess . CalledProcessError as e : print ( f " claude -p exited { e . returncode } : { ( e . stderr or '' ). strip ()[ : 200 ] } " , file = sys . stderr ) raise SystemExit ( 1 ) except FileNotFoundError : print ( " claude CLI not found on PATH " , file = sys . stderr ) raise SystemExit ( 1 ) That's a held index lock hanging git diff , an empty staging area, a claude -p call that times out, one that exits non-zero, and one where the claude binary isn't even on PATH . Real scenarios — the timeout on this exact git diff --staged call was itself a bug I'd already found and fixed once ( docs/project_notes/bugs.md , 2026-08-06: a prior fix claimed to add a timeout
AI 资讯
"My Comment-Reply Pipeline Was Feeding Me Garbled HTML Entities Instead of the Actual Comment"
I have a small script, reply_comments.py , that pulls unanswered comments off my DEV.to articles and drafts replies to a markdown file so I can paste them in by hand. The API doesn't let a normal account post comments (that's its own bug I've written about before), so this draft-then-paste loop is the whole workflow. Every reply I've ever sent has come from reading the body field this script prints. Today I went looking for a bug distinct from everything already logged for this repo, and I ended up re-reading strip_html() , the function that turns a comment's raw body_html into the plain text I actually read: def strip_html ( h ): return re . sub ( r " \s+ " , " " , re . sub ( r " <[^>]+> " , " " , h )). strip () It does exactly one thing: strip HTML tags with a regex, then collapse whitespace. It's been in the file since the script was written and nobody had audited it on its own — every prior pass through this pipeline was about pagination, thread-depth walking, or dedup keys, never the text-extraction step itself. Here's the problem. DEV.to's API returns body_html as rendered HTML. A correct renderer has to HTML-entity-escape a commenter's own literal < , > , & , and quote characters, or they'd get mistaken for markup. So a comment that reads, in plain English: isn't it faster with a Q&A cache? Try List instead. comes back from the API as something like: <p> isn ' t it faster with a Q & A cache? Try List < String > instead. </p> strip_html() 's regex only ever targets <[^>]+> — actual tags. It has no idea what to do with ' , & , < , > . Those aren't tags, so the regex leaves them untouched. The whitespace collapse doesn't touch them either. What comes out the other end, into the exact field I read to draft a reply, is: isn't it faster with a Q&A cache? Try List<String> instead. That's not a cosmetic nit. On a dev-focused comment section, & , < , and > show up constantly — generics, comparisons, "foo & bar," code snippets
开发者
Celebrating 10,000 Total Views on DEV! 🥳 Let’s Check the Stats 😸
Hoi hoi! I'm @nyaomaru, a frontend engineer who recently watched a flock of geese march through...
AI 资讯
Claude Code shipped a sandbox. Here's what it protects — and what it doesn't.
Anthropic shipped OS-level sandboxing for Claude Code. If you run an agent against a repo you care about, it's worth understanding precisely what moved — because a fair amount of the commentary treats it as "agents are contained now," and that's not what the documentation says. I read the docs carefully, partly because I build a tool in adjacent territory and needed to know whether I'd just been made redundant. Short answer: no. The longer answer is more interesting, and it starts with a compliment: the docs are unusually honest about their own limits. Most of what follows isn't something I discovered — it's something Anthropic wrote down, and more people should read it. What it actually does The sandbox uses OS primitives — Seatbelt on macOS, bubblewrap on Linux and WSL2. By default, sandboxed commands can write only to your working directory and the session temp directory. No network domains are pre-allowed: the first time a command needs a new host you're prompted, and approving it lasts the session. Crucially, this is enforced by the operating system on the running process , not by the model correctly interpreting a command. The docs put it well: the boundary holds regardless of what the model chose to run, and even if an allowed command does more than its name suggests. That's a real improvement over asking an agent nicely, and it's the right layer for what it solves. The motivation named in the docs is the same one I keep seeing in the wild: reducing the permission prompts that people stop reading. Approval fatigue is the disease; this is a real treatment for part of it. Five things worth knowing before you rely on it It's Bash-only. The sandbox constrains Bash commands and their child processes. Claude Code's own Read, Edit and Write tools don't run through it — they go through the permission system instead. "The sandbox is on" means shell commands are contained, not that every file operation is. Your working directory is inside the boundary by design. The de
开发者
Iter: programar desde la intención
Vista previa técnica: Iter todavía no está publicado en PyPI y no existe un paquete oficial instalable. Abrir un recurso, convertir datos o cambiar de backend suele exigir aprender una interfaz diferente y repetir código de integración. Iter nace de una idea sencilla: Aprende una vez. Usa cualquier biblioteca. iter convert data.json to data.csv El usuario expresa una sola intención. Iter se encarga de abrir el recurso, detectar los formatos, seleccionar un adaptador compatible, convertir los datos y guardar el resultado. Una intención. Una instrucción. ¿Qué busca cambiar Iter? Actualmente, una tarea sencilla puede exigir: importar bibliotecas; aprender APIs diferentes; configurar formatos manualmente; escribir código de integración; seleccionar cada backend. Con Iter, el usuario indica principalmente qué quiere conseguir: iter analyze sales.csv Iter selecciona automáticamente una herramienta compatible. Si el usuario necesita controlar la biblioteca, puede indicarla: iter analyze sales.csv with pandas La automatización es el comportamiento predeterminado. El control detallado sigue siendo opcional. Everything is a Resource Iter representa archivos, datos y recursos web mediante una estructura común llamada Resource . El sistema está organizado alrededor de cinco componentes: Resource : representa el recurso. Resolver : identifica formatos, tipos y backends. Registry : registra y selecciona adaptadores. Adapter : ejecuta operaciones concretas. Engine : coordina el proceso. La meta no es afirmar que todas las bibliotecas son idénticas. La meta es unificar intenciones comunes y conservar las diferencias importantes cuando sean necesarias. Estado actual Iter 0.3.0-rc.2 está en fase de corrección de errores y validación privada. Actualmente: el código principal permanece privado; Iter todavía no está publicado en PyPI; no existe un paquete demostrativo; la sintaxis puede ajustarse antes del lanzamiento; solamente se anunciarán como disponibles las funciones implementadas
AI 资讯
Mendapi 0.5.5: the one bug we shipped on purpose, now fixed
The 0.5.4 release notes carried an unusual section: Known issue shipped with 0.5.4 . We had spent that whole release fixing the first minute of using the CLI — twelve corrections to help text, exit codes, path handling, and MCP behaviour — and in the middle of it we found one more that did not make the cut. mendapi scan -h did not print help. It ran a scan. Every other subcommand normalized -h to --help before dispatching. scan did not, so the short flag fell through to the scanner, which happily ignored an unrecognized argument and started working. Nobody loses data over this. But it is exactly the kind of thing that makes a first-time user close the terminal, and we had just shipped a release about first impressions. We wrote it down rather than quietly patching over it, because a tool whose entire premise is upstream changes should be visible before they surprise you does not get to hide its own. What 0.5.5 does One change. -h is normalized to --help before any subcommand spawns, so all nine subcommands behave identically: $ npx mendapi@0.5.5 scan -h Usage: mendapi scan --repo <path> --provider <name> --change-id <id> --out <file.json> --json --quiet --include-prereleases The regression gate that covers this now asserts on all nine subcommands, plus a negative control that fails if the assertion ever becomes vacuously true. That second part matters more than the fix: a test that passes because it stopped testing anything is worse than no test. Also in this release The MCP registry entry has been refreshed. com.mendapi/mendapi now carries an icon set and a website URL alongside the package metadata, so clients that render a server picker have something to render. Nothing else changed. scan , fix , deps , review , and pr still run entirely on your machine. No network primitives exist in those files at all, and the build fails if any appear. Install npx mendapi@latest scan Or wire it into an agent: claude mcp add mendapi \ -- npx mendapi mcp Requires Node.js 22.13 o
AI 资讯
AI Makes Developers Faster. Why Can It Make Teams Slower?
This was first published on the Vibsync blog . Reposting for the DEV community. The short version: AI reliably makes each developer faster. Whether it makes the team faster is a separate question — and the gap between the two is where a lot of quiet cost hides. Below: the five coordination costs that eat the difference, a ten-question diagnostic, and five operating principles. Picture three developers, three AI coding agents, and one repository. Each developer can now produce candidate code, tests, and refactors faster than before. Yet releases move at the same pace, review queues grow, and the same facts keep getting rediscovered. That's not a paradox, and it isn't a reason to slow anyone down. It's a reminder that individual speed and team speed are different quantities , and AI coding agents scale the first far more easily than the second. Give everyone a faster typewriter and you get more pages — not necessarily a better book, written faster, by a group. Individual output is not team throughput It's worth separating two things we tend to blur: Individual output — how much finished work one developer (plus their agent) produces. Team throughput — how much shippable, coherent work the group produces together, after review, rework, waiting, and reconciling everyone's changes. AI agents lift individual output directly. Team throughput is what's left after the coordination overhead is paid, and that overhead doesn't shrink just because each person got faster. A useful way to hold it in your head — not as a formula to compute, just as a shape: team throughput ≈ the sum of local speed-ups − rework − waiting − reconciliation When you add agents, the first term grows. If nothing else changes, the last three grow too — because there's now more work in flight, produced faster, by people who can't all see what the others are doing. The interesting question for a team lead isn't "how do I make everyone faster?" It's "which of those subtraction terms is my real ceiling?" Ther
AI 资讯
My Comment-Reply Queue Draft One Reply to a Thread and It Went Deaf to Every Follow-Up After That
I have a small script, reply_comments.py , that keeps me from having to re-scan every DEV.to article for new comments by hand. It has two commands: pending (unanswered comments I haven't drafted a reply to yet) and audit (drafted replies I said I'd paste manually but apparently never did). I've already fixed two bugs in this file — one in needs_reply() (a thread stayed "handled" forever after a single reply, even when the other person followed up again) and one in audit() (it only checked direct children, so a reply nested two levels deep was invisible). Today I found a third, in pending() itself, and it's the kind of bug that hides precisely because the first two fixes made everything else in the file look trustworthy. What pending() actually does Comments on DEV.to come back from the API as trees — each top-level comment has a children list, and replies can nest arbitrarily deep. pending() walks each article's top-level comments and decides, for each one, whether it needs a reply: def pending (): try : drafted_text = open ( DRAFTS , encoding = " utf-8 " ). read () except FileNotFoundError : drafted_text = "" drafted_codes = set ( re . findall ( r " ^## (\S+) " , drafted_text , re . M )) out = [] for a in api ( f " /articles?username= { ME } &per_page=100 " ): if not a [ " comments_count " ]: continue for c in api ( f " /comments?a_id= { a [ ' id ' ] } " ): if not needs_reply ( c ): continue if c [ " id_code " ] in drafted_codes : continue out . append ({ " id_code " : c [ " id_code " ], " author " : c [ " user " ][ " username " ], " article " : a [ " title " ], " comment_url " : f " https://dev.to/ { ME } /comment/ { c [ ' id_code ' ] } " , " body " : strip_html ( c [ " body_html " ]), }) return out needs_reply(c) is the fix from a few weeks ago — it recurses the whole subtree and checks who posted the most recent message, not just whether I've ever replied. That part's correct. The bug is in the two lines right after it: c["id_code"] and c["body_html"] . c here i
AI 资讯
Your AI Agent ID Is Not a Version
Yesterday, backend-reviewer inspected pull requests with one model, read only the repository and public documentation, and stopped for human approval before proposing any change. Today it has exactly the same name. The model has changed, the system instructions have been rewritten, incident history is now available as a context source, memory persists between tasks, and database migration changes no longer require approval before they are proposed. The dashboard still shows the same team member. The engineer responsible for quality and risk is looking at a different agent. The identifier stayed. The behavior moved. That distinction is what NexFlow , an open specification for AI developer teams, is trying to make visible. The project does not currently provide a production runtime, a production CLI, or model-provider integrations. Its present job is narrower and, in my view, more important: give teams a language for reviewing agent changes before anything executes. A name answers the wrong question Agent names are useful to people. They distinguish a code reviewer from a documentation writer and establish a long-lived role inside the team. A name says very little about the configuration that produced a particular result. A model change can affect code quality, cost, latency, and the way uncertainty is handled. New instructions alter the order of analysis and the criteria for an acceptable answer. An additional source expands both available knowledge and the exposure surface. Memory carries the consequences of one task into another. A new permission changes more than output style: it changes what an error can damage. For audit purposes, “Which agent did the work?” is therefore incomplete. A second question matters just as much: which version of that agent's definition was active? In draft RFC-0004 , NexFlow separates stable agent identity from a versioned agent definition. Identity contains the role, description, and long-lived responsibility. The definition captures
AI 资讯
136 raw removals, 17 real ones: what a spec diff over-reports
Originally published at mendapi.com . Between two published snapshots of the Cloudflare OpenAPI schema — 7abe88500e55 (2026-03-31) → c92b9b0fde23 (2026-07-27) — a raw structural diff produced 6,354 change records. 136 of them were endpoint path removals, the scariest kind a diff can report: the route your code calls is simply gone from the spec. Except 119 of those 136 were not gone at all. This is the accounting of how we know, per record, with machine evidence. The trap in a raw diff A path removal in a spec diff means one thing: the string key disappeared from the paths object. It does not mean the runtime URL stopped working. Specs get refactored — concrete routes collapse into templated ones, path parameters get renamed, methods get merged — and every one of those refactors shows up as a "removal" if you only look at one side of the diff. An alerting tool that pages you 136 times for this corridor is training you to ignore it. The whole job of the curation layer is to keep that from happening without silently dropping a real break. The ledger: 17 + 119 = 136 Every one of the 136 raw removals has an adjudicated destination. 17 were kept as genuinely client-breaking: the runtime URL or method really disappeared, with no surviving successor. The other 119 were excluded, each with machine evidence from the two spec snapshots that the surface actually survives: Template consolidation — 107 records. Concrete Workers AI model routes like /ai/run/@cf/baai/bge-m3 collapsed into the pre-existing generic /ai/run/{model_name} route. The runtime URL a client sends never changed; the spec just stopped enumerating each model. The evidence rule requires the templated route to exist in both snapshots and to swallow the removed path with a literal-anchored match, so a template that is merely a shape prefix of a genuinely removed endpoint does not count. Parameter rename, runtime-identical — 11 records. Path parameters renamed ( {postfix_id} to {investigate_id} and friends). Afte
AI 资讯
Introducing DevPub - Open Source Dev.to CLI Tool
Recently I went looking for a CLI tool to manage my Dev.to articles from the terminal. I write 4-5 articles per month, track analytics obsessively, and wanted a git-backed workflow. I found 9 existing tools. Tried them all. Here's what happened: devto-cli (Node): Last commit 2 years ago. Broke on install. dev-to-git (Node): Only syncs TO local. Can't push back. slinkity : Abandoned. forem-cli : 3 endpoints implemented out of 40+. Every single tool does the same thing: publish an article. That's it. Maybe pull. Maybe validate tags. Meanwhile the Dev.to API has 40+ endpoints including analytics, semantic search, ML-powered content concepts, follower engagement, trend tracking, and reading list management. Nobody uses them. So I built devpub . Table of Contents What devpub does What I discovered in the API The build story Architecture Try it Contributing What devpub does (that nothing else does) # The basics (every tool does this) devpub push -f articles/my-post.md devpub pull # Analytics in your terminal devpub stats # Views: 246.5K | Reactions: 4.4K | Comments: 402 | Followers: 18.9K # Full dashboard with top articles devpub dashboard # AI-powered search (semantic, not keyword) devpub search "building serverless apps" --semantic # What's trending RIGHT NOW devpub trends # Catch problems before publishing devpub validate The difference isn't one feature. It's coverage. Here's the comparison: Capability devpub Everyone else Publish/update articles Yes Yes Pull articles to local Yes Some Analytics (7 endpoints) Yes No Semantic search Yes No Trend discovery Yes No Article validation Yes No Rate limiting (30 req/30s) Yes No Retry logic for failures Yes No Concepts API (ML topics) Yes No What I discovered in the Dev.to API While building devpub, I found several API endpoints that aren't documented anywhere obvious: 1. Semantic Search -- Dev.to has a full embedding-based search system using Gemini embeddings (768-dimensional vectors) with pgvector. You can search articles b
AI 资讯
My MCP Tool's Audit Log Was Built So a Bad Write Would Leave a Trace. The Log Itself Leaves None.
A few days ago I fixed update_article , one of the tools in this repo's MCP server, because it had a nasty shape: it took a bare integer article_id , PUT whatever fields you gave it straight to the DEV.to API, and if the id was wrong or hallucinated, it would silently overwrite a live published post with nothing left behind to show it had happened. The fix added a fetch-before-write diff and a JSONL audit log: _ARTICLE_UPDATE_LOG = " logs/article_updates.jsonl " def _log_article_update ( article_id , before , fields_changed , after ): os . makedirs ( os . path . dirname ( _ARTICLE_UPDATE_LOG ), exist_ok = True ) entry = { " article_id " : article_id , " fields_changed " : sorted ( fields_changed ), " url " : after . get ( " url " )} for field in fields_changed : entry [ f " { field } _before " ] = before . get ( field ) entry [ f " { field } _after " ] = after . get ( field ) with open ( _ARTICLE_UPDATE_LOG , " a " ) as f : f . write ( json . dumps ( entry ) + " \n " ) The whole point of that function is durability. "Zero trace" was the bug; a JSONL file that records before/after state on every write was the fix. I verified the logging logic itself with an offline unit test against fake before/after states and moved on, same as the diff field. What I never checked is whether logs/article_updates.jsonl outlives the process that writes it. Checking whether the trace actually exists anywhere logs/ isn't in .gitignore — I checked, it's not there. So nothing is actively hiding it. But not-hidden isn't the same as tracked: $ git log --all --oneline -- 'logs/*' $ ls logs/ ls: cannot access 'logs/': No such file or directory Empty output from the first command, across every branch and every commit this repo has ever had (50 commits, not a shallow clone — git rev-parse --is-shallow-repository is false ). Nothing has ever touched logs/ . The directory doesn't even exist right now. Not because anything deleted it — because nothing has ever run update_article in an environment
AI 资讯
My Comment Pipeline Marks a Thread "Handled" the Moment I Reply Once. A Follow-Up Question Proved It Wrong.
I run a small script called reply_comments.py that scans my DEV.to articles for comments I haven't replied to yet, and hands me a JSON list so I can draft responses. It's been running twice a day for over a week. This morning, while re-reading it for something unrelated, I noticed the function that decides whether a thread still needs my attention was answering the wrong question — and had been since the day it was written. Here's the function, unchanged until today: def replied_by_me ( comment ): return any ( c [ " user " ][ " username " ] == ME or replied_by_me ( c ) for c in comment [ " children " ]) It walks a comment's entire reply tree and returns True the moment it finds any message from me, anywhere in the subtree. Then pending() uses it as the skip condition: for c in api ( f " /comments?a_id= { a [ ' id ' ] } " ): if c [ " user " ][ " username " ] == ME or replied_by_me ( c ): continue ... out . append ({...}) The logic reads fine in isolation: "did I already reply to this thread? Skip it." The bug is in what "already replied" is being asked to mean. replied_by_me doesn't check whether the latest message in the thread is mine — it checks whether a message from me exists at all, ever, at any depth. Those are the same question exactly once: the first time someone comments and I reply. They stop being the same question the moment the other person replies again. Proving it I wrote a small repro against the real function rather than trusting my read of it: from reply_comments import replied_by_me thread = { " id_code " : " 3c00h " , " user " : { " username " : " alexshev " }, " created_at " : " 2026-07-24T08:00:00Z " , " children " : [ { " user " : { " username " : " enjoy_kumawat " }, " created_at " : " 2026-07-25T10:00:00Z " , " children " : []}, { " user " : { " username " : " alexshev " }, " created_at " : " 2026-07-26T09:00:00Z " , " children " : []}, ], } print ( replied_by_me ( thread )) # True That's True even though the second child — posted a full day
AI 资讯
Your agent's instructions are promises nobody checks. I counted.
I didn't set out to build a developer tool. For a long time now I've been working with AI on everything in my life — daily conversations about my daughters, planning projects, ideas for ones that don't exist yet. The goal was always the same: ease my life, get more done, and break the barrier between human and AI — stop treating it as a search box, start treating it as a partner. Somewhere along the way, the partnership got serious. The workspace where my projects live grew an instruction system for AI coding agents — the files everyone is writing now: AGENTS.md , CLAUDE.md , a skills directory, rules for how agents should plan, log, and verify their work. Then I asked an uncomfortable question: is any of it actually followed? Not "do the agents seem to follow it." Could anyone tell , from the repository alone, whether an instruction was followed? For most of my rules, the answer was no. My own audit found that the two checks my instructions said must run before every commit were invoked by nothing — no CI, no hook, no scheduled task. The rule had been enforced, for its entire life, by whoever remembered. Replaying my last 200 commits, the index-freshness rule alone would have failed on 29 of 61 eligible commits — roughly half. My instructions were not rules. They were hopes with formatting. So I wondered whether everyone else's are too. I wrote a tool and measured. What I measured, and the two honest limits that come before the numbers I analysed eight public agent-instruction collections — 1,332 instruction units, 17,611 individual instructions — each at a pinned commit SHA, with the raw per-repo JSON published alongside the tool. An instruction counts as CHECKABLE if a reviewer could tell from the repo whether it happened: it's a tick-box, or contains a runnable command, or names a concrete file artifact, or refers to an exit code, a diff, an assertion. Everything else is CLAIMABLE — the only evidence it happened is the agent saying so. Two limits, before any num
AI 资讯
How to Build and Debug MCP Servers for Claude Desktop in 5 Seconds 🔨
How to Build and Debug MCP Servers for Claude Desktop in 5 Seconds 🔨 Model Context Protocol (MCP) by Anthropic is rapidly becoming the open standard for connecting LLMs like Claude Desktop, Cursor, and Windsurf to local dev tools, APIs, and databases. However, setting up an MCP server from scratch, configuring stdio transports, and debugging JSON-RPC requests in the terminal can be tedious. To solve this, I built mcp-forge — an open-source Swiss-Army developer toolkit and inspector for MCP servers. ⚡ What is mcp-forge ? mcp-forge gives you everything you need to build, test, inspect, and run MCP servers with zero setup overhead : 🛠️ npx mcp-forge serve : Launches a built-in suite of developer tools for Claude Desktop (Git summary, System diagnostics, Mermaid syntax validator, HTTP API tester). 🔍 npx mcp-forge inspect <cmd> : An interactive stdio inspector to connect to any MCP server, list tools/resources/prompts, and test executions live. ⚡ npx mcp-forge init <name> : Scaffolds a production-ready TypeScript MCP server in 5 seconds with TypeScript, tsup bundler, and Vitest. 🌐 npx mcp-forge ui : A visual dark-themed web dashboard for real-time WebSocket traffic monitoring. 🚀 Quickstart: Supercharge Claude Desktop in 1 Minute You don't even need to install anything globally! You can run mcp-forge directly via npx . 1. Add mcp-forge to Claude Desktop Add this snippet to your claude_desktop_config.json : { "mcpServers" : { "mcp-forge" : { "command" : "npx" , "args" : [ "-y" , "mcp-forge" , "serve" ] } } } Now Claude can automatically inspect your Git status, fetch system memory/CPU telemetry, validate Mermaid diagram syntax, and test REST endpoints! Scaffold a New MCP Server in 5 Seconds Want to build your own custom MCP server? Run: npx mcp-forge init my-awesome-mcp-server cd my-awesome-mcp-server npm install npm run dev You get a fully-typed MCP server template with @modelcontextprotocol/sdk configured and ready to publish. Inspect & Debug Any MCP Server in Terminal N
AI 资讯
We Audited Our Claude Code Setup Against Anthropic's Own Context-Engineering Rules — Here's What We Found
The question that started this We run Claude Code against a fairly large, fairly automated repository — a farming-assistance platform with a Node.js backend, a Flutter app, a React dashboard, an in-progress Spring Boot microservices migration, and a home-grown "repo memory" layer called gps that captures invariants, lessons, and preferences across sessions. Over several months we'd wired up a lot of automation: session-start hooks, prompt-submit hooks, auto-captured preferences, persona plugins, a mandatory agent-dispatch table. It felt sophisticated. It also felt, some days, slow to get going — every session seemed to start with a wall of text before any real work happened. So when Anthropic published "The New Rules of Context Engineering for Claude 5 Generation Models" , we asked the obvious question: are we actually following our own advice, or have we just accumulated automation that looks like good practice? This post is the audit, the root cause we found, and the fix — including a mistake we made mid-fix that's worth telling on ourselves for. What the blog post actually says Stripped of marketing language, the post boils down to five concrete rules: Keep CLAUDE.md lightweight. Describe gotchas and non-obvious patterns, not everything you know about the repo. Organize by relevance, not comprehensiveness. Progressive disclosure. Load context at the right time — skills, references, and detail should be pulled in when needed, not front-loaded into every session regardless of task. Trust the model's judgment. Remove redundant guardrails and standing instructions that the newer models don't need spelled out every time. Rely on automatic memory, not manual dumps. Don't hand-maintain a giant preferences block in a markdown file — let the memory system surface the right thing at the right time. Design tools and interfaces, not prose. Push instructions into tool schemas and parameter design rather than repeating them in the system prompt. None of this is radical. It's t