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

标签:#DevOps

找到 859 篇相关文章

AI 资讯

Building an LLM Cost Dashboard

Cost dashboards usually fail in one of two directions: a single total that nobody can act on, or forty panels that nobody reads. Five charts, each answering a question somebody actually asks out loud, is about the right size — and each of them is a query you can run today. Three audiences ask genuinely different questions of the same data, and a dashboard that ignores the split ends up serving none of them. Finance asks what this month will be and why it differs from last month. Engineering asks what a particular change did. Product asks whether a feature can be afforded at ten times the current user count. The five charts below cover all three, in roughly that order — which is also why the top of the dashboard is a trend line and not a breakdown: the first question anyone has is whether the number is moving, and only then which part of it moved. Everything runs against the llm_request table from the logging page and the daily rollup from per-customer tracking . One rule for all of them: where environment = 'prod' , always, because eval and staging spend contaminates every trend it touches. 1 · Spend and run rate Daily spend, with a month-to-date total and a straight-line projection to month end. The projection is the panel finance looks at; the daily series is what makes a step change obvious. with daily as ( select started_at :: date as day , sum ( cost_usd ) as spend from llm_request where environment = 'prod' and started_at >= date_trunc ( 'month' , now ()) - interval '2 months' group by 1 ), mtd as ( select sum ( spend ) as spend_mtd , count ( * ) as days_elapsed from daily where day >= date_trunc ( 'month' , now ()):: date ) select d . day , d . spend , avg ( d . spend ) over ( order by d . day rows between 6 preceding and current row ) as spend_7d_avg , ( select round ( spend_mtd , 2 ) from mtd ) as mtd , ( select round ( spend_mtd / nullif ( days_elapsed , 0 ) * extract ( day from date_trunc ( 'month' , now ()) + interval '1 month - 1 day' ), 2 ) from mtd )

2026-08-08 原文 →
AI 资讯

Alerting on LLM Metrics Without Alarm Fatigue

Most LLM alerting starts as a threshold on latency and a threshold on error rate, fires nine times in the first week, and is muted by the second. The fix is not better thresholds. It is a different trigger model and a much shorter list of things allowed to page. Level-triggered, not edge-triggered An edge-triggered alert fires on a transition: latency crossed 3 seconds, error rate spiked. It is easy to write and it is why your phone buzzed at 03:00 about a condition that resolved itself in forty seconds. A level-triggered alert asks a different question — is the system currently in a bad state, and has it been for long enough to matter? Concretely, the difference is that the alert condition is evaluated over a window and describes a sustained state, and it clears when the state clears rather than when someone acknowledges it. Every rule below is of that shape. Anything that fires on a single scrape does not belong in a paging policy; put it in a dashboard. Page on symptoms, ticket on causes The reliable partition, straight out of ordinary SRE practice and entirely applicable here: Page when users are being harmed now, and a human can do something about it in minutes. That is a small list: the feature is failing, the feature is unusably slow, or money is leaving the building at an unplanned rate. Ticket when something is degraded, trending wrong, or will bite in days. Rising retry rate. One provider slower than usual while failover is absorbing it. Attribution coverage slipping. Neither for everything else. If nobody would act on it, it is a chart. The distinction matters more for LLM features than for a normal service because so many of the interesting signals are causes : a provider 429 rate, a fallback rate, a cache-hit drop. If failover is working, none of those are user-visible and none of them should wake anyone. They are exactly what you want in the morning ticket queue. Burn-rate alerts, with the numbers The standard design — described in Google’s Site Reliab

2026-08-08 原文 →
AI 资讯

Multi-Repo to Monorepo: How I Automated 6 Go Microservice Releases and Then Made It 15x Faster

Last month I spent more than an hour cutting a release across six Go microservice repos. Tag log, wait for CI. Update sdk's go.mod to point at the new log SHA, push, wait for CI. Repeat for utils. Then do api, cli, and worker in parallel - except I forgot to bump cli's dependency and the build broke at 11pm. That was the last manual release I did. This is the story of automating that entire workflow with Jenkins + Python + GitLab, then realizing the multi-repo architecture was the real problem, and collapsing everything into a Go monorepo that's 15x faster at cutting releases. The full setup runs on my laptop. You can fork it and try it yourself. Table of Contents The Six Modules The Stack Phase 1: Multi-Repo Automation Phase 2: The Monorepo Pivot The Unified CI Pipeline Real Numbers Caveats and Gotchas Try It Yourself The Six Modules The project simulates a real production system with six Go modules that have strict dependency ordering: Module Role Tag Scheme Depends On log Logger (leaf, no deps) v0.x.0 - sdk API client v0.x.0 log utils Shared utilities v0.x.0 log, sdk api/backend Backend APP-x.y.z log, utils cli CLI cli-x.y.z log, sdk worker Background v0.x.0 log, utils The first three modules are sequential - sdk can't tag until log is tagged, utils can't tag until sdk is tagged. The last three are terminal - they can process in parallel once the sequential chain is done. Every module lives on three long-lived branches: develop → release → master . A release means moving code through all three, in all six repos, in the right order. That's the problem. Do it manually and you're juggling 6 repos × 3 branches × dependency ordering. One forgotten go mod tidy and you're debugging at midnight. The Stack Everything runs on a MacBook. No cloud CI, no SaaS - just local tools wired together. MacBook GitLab.com +-------------------+ ngrok tunnel +------------------------+ | Jenkins LTS | <===============> | Webhooks (push / MR) | | (brew service) | | Commit status API | | :

2026-08-08 原文 →
AI 资讯

The Same Setting, Three Different Answers: Why 0.0.0.0 Isn't Always What You Want

There is a line in almost every Python web tutorial that nobody explains: uvicorn main:app --host 0.0.0.0 --port 8000 I copied it for weeks without thinking about it. Then I deployed the same application three times — to a local VM, to a production server, and into a container — and the correct value was different every time. Twice it was 0.0.0.0 . Once, in the place that mattered most, it was not. That gap is worth writing about, because the setting itself is trivial and the reasoning behind it is not. What the Flag Actually Controls A server process doesn't "open a port." It creates a socket and binds it to an address. The bind address answers one question: which network interfaces should this socket accept connections from? A machine has more than one interface: lo (loopback) — reachable only from inside the machine ( 127.0.0.1 ). Packets addressed there never reach a physical network card; the kernel loops them straight back. 0.0.0.0 — a wildcard meaning every interface this machine has , including ones added later. So the flag isn't about security or convenience. It's about reachability — and reachability depends entirely on what sits in front of the process. Case 1: The Local VM — 0.0.0.0 I was running the service inside a Multipass VM and wanted to hit it from the browser on my laptop. The laptop is outside the VM, so binding to loopback would have made the service invisible to it. curl inside the VM would work; the browser outside would get connection refused. Decision: wildcard bind. Nothing sits in front of the process, and nothing needs protecting. Case 2: Production — 127.0.0.1 Here I copied the same line at first, and it was wrong. The production box has a public IP. Binding to 0.0.0.0 there means the application is directly exposed to the internet: no TLS, no rate limiting, no authentication. Within hours of provisioning that server, its SSH logs showed hundreds of automated login attempts against usernames like admin and oracle . The same scanners try

2026-08-07 原文 →
AI 资讯

Rootly Drops Small PR Rule as Agentic AI Changes Code Review Economics

Incident management platform provider Rootly has published an account of its decision to drop its long-standing small pull request rule, arguing that the practice no longer serves its purpose now that AI agents generate most of its code. The company describes a shift from measuring PR size to assessing blast radius, with feature flags and rollback capability taking precedence over line counts. By Matt Saunders

2026-08-07 原文 →
AI 资讯

Random Forest Is Horizontal Scaling for Predictions

Classic Machine Learning Through the Eyes of an SRE — Part 3 The random forest is the first ML algorithm that made me feel at home. Not because of the math — because it's an SRE idea wearing a stats costume. Many independent workers. No single point of failure. Majority vote. If one worker goes weird, the fleet absorbs it. We've been building systems this way for decades; the forest just applies it to prediction. The problem it exists to fix Last article: a single decision tree is readable but unstable — small data change, whole tree flips, explanation rewrites itself. That instability is variance, and it's exactly what scared me about trusting one tree in production. The forest's move: grow hundreds of trees, each on a random resample of the data, and — this is the part that matters — force each split to choose from only a random subset of features. That second randomization is the whole difference between a random forest and plain bagging. Bagging alone gives you many trees on resampled data, but if one feature is strongly predictive, every tree grabs it first and they all end up looking alike. Starving each split of features is what makes the trees genuinely different from each other. The randomness isn't sloppiness. It's manufactured disagreement. The instability doesn't get fixed. It gets CANCELLED. Each tree is still jumpy, but they're jumpy in different directions, and the average is calm. What surprised me No new loss function. Each tree still minimizes impurity exactly like a lone tree. The forest adds zero new objectives. The entire gain is a bias-variance bargain: variance drops hard, bias barely moves. You give up readability and get back trustworthiness. Embarrassingly parallel. Trees are independent, so training scales horizontally — throw cores at it. Boosting, its sequential cousin, is the opposite: each model depends on the last. Map-reduce versus a pipeline. The smoothness illusion. A forest's decision boundary looks smooth, almost like regression'

2026-08-07 原文 →
AI 资讯

AWS Aurora, ElastiCache Patterns & DynamoDB — The Complete Data Layer

Part of my AWS learning journey — transitioning from Systems Engineer to Cloud/DevOps. This session completes the database picture — Aurora's read/write architecture, ElastiCache caching strategies, and DynamoDB from table creation to production-ready query patterns. 📋 Topics Covered # Topic Type 1 Aurora Endpoints — Writer vs Reader Concept + Interview 2 What Happens When the Aurora Writer Fails Concept + Cert 3 ElastiCache Caching Patterns — Lazy Loading, Write Through, Session Store Concept + Interview 4 Cache Invalidation Concept + Interview 5 DynamoDB — What It Is and When to Use It Concept + Interview 6 DynamoDB Table Creation — Keys and Settings Concept + Lab 7 Table Classes — Standard vs Standard-IA Concept + Cert 8 Capacity Modes — On-Demand vs Provisioned Concept + Cert 9 Warm Throughput Concept + Cert 10 DynamoDB Items & Attributes — CRUD Operations Concept + Lab 11 Query vs Scan — The Critical Difference Concept + Interview 12 Local Secondary Index (LSI) vs Global Secondary Index (GSI) Concept + Cert 13 Bonus Concepts — Streams, DAX, Consistency, Transactions Concept + Interview 14 Interview Questions Interview 15 Practice Tasks Practice Aurora Endpoints — Writer vs Reader Aurora doesn't give you just one database endpoint — it gives you two, each serving a different purpose and routing to different parts of the cluster. Writer Endpoint (Primary Endpoint): Always points to the current primary/writer instance. All write operations (INSERT, UPDATE, DELETE) go here. If a failover happens and a replica is promoted, Aurora automatically redirects this endpoint to the new writer — your application's configuration never needs to change. Reader Endpoint: A load-balanced endpoint that distributes read-only queries (SELECT) across all available Aurora Replicas. You don't manage which replica serves each query — Aurora handles the routing, spreading read traffic evenly across however many replicas exist. Why this architecture matters: In a typical application, read

2026-08-07 原文 →
开发者

My Terraform Drift Pipeline Fixed the Change, Then Forgot It

My Terraform drift pipeline could detect a manual EC2 tag change, classify it as LOW, and run Terraform to remove it. Then the pipeline moved on. The evidence existed, but it was spread across CodeBuild output, Lambda logs, and an SNS message. If I wanted to know what changed, how it was classified, and whether remediation started, I had to reconstruct the event from multiple AWS services. The pipeline could act on drift. It could not remember drift. Phase 4 added that memory: a durable DynamoDB record, a read only API, and a small dashboard that turns the event history into something I can inspect without opening three AWS consoles. The Stack Terraform drift event ↓ SNS ↓ Severity Lambda ├── classifies HIGH / MEDIUM / LOW ├── starts remediation for eligible LOW drift └── writes the audit event to DynamoDB ↓ API Gateway HTTP API ↓ Read only Lambda ↓ DynamoDB Query ↓ CloudFront → static dashboard ↑ private S3 bucket The browser receives static HTML, CSS, and JavaScript from CloudFront. JavaScript calls API Gateway, the API Lambda queries DynamoDB, and the returned JSON becomes the live dashboard. There is no EC2 web server and no application process running continuously. Step 1: Store Every Classified Event I created a DynamoDB table with a composite key: resource "aws_dynamodb_table" "drift_events" { name = "terraform-drift-events" billing_mode = "PAY_PER_REQUEST" hash_key = "project" range_key = "timestamp" attribute { name = "project" type = "S" } attribute { name = "timestamp" type = "S" } } project groups the history for one Terraform project. The ISO 8601 timestamp orders its events. DynamoDB only requires attribute definitions for keys and indexes. Fields such as high_count , changes , and status still belong in each item, but they do not belong in the table schema block. I passed the table name into the existing severity Lambda instead of putting it directly in the code: environment { variables = { DRIFT_EVENTS_TABLE = aws_dynamodb_table . drift_events . name

2026-08-07 原文 →
AI 资讯

How to Turn Any Android Tablet into a Production-Grade Dev Rig in 5 Minutes. Published in #developer #android #terminal #productivity

If you've ever tried coding on an iPad, Galaxy Tab, or Chromebook, you know the frustration: Standard desktop tutorials assume a Mac or high-spec Linux laptop. Neovim configuration takes 4 hours of plugin debugging. Touch input on mobile terminals sucks without a dedicated extra-keys bar. I built DevDock (dock) to solve this permanently. What is DevDock? DevDock is a turnkey developer environment manager built specifically for mobile devices, Termux, Chromebooks, and low-spec hardware. Instead of fighting configuration files, one command installs a complete, high-performance terminal stack: bash curl -fsSL https://get.devdock.io | bash -s -- --profile=fullstack ⚡ Key Features Sub-5ms Terminal Rendering: Uses Starship prompt + Zsh lazy-loading tuned for ARM chips. Termux Touch Optimization: Automatically injects an ESC/TAB/CTRL touch bar and enables mouse scrolling in Tmux. Low-Memory Neovim: Starts in <50ms and uses under 50MB RAM while providing full Language Server Protocol (LSP) support for TS, Go, Python, and Rust. Curated Profiles: fullstack: Web + API tools frontend: React, TS, Vite & Tailwind preset backend: Go, Rust, Python, Postgres & Redis CLI tools devops: Kubectl, Helm, Terraform, and Cloud CLIs 🛠 Trying It Out bash Check your mobile terminal health: dock doctor View available developer stacks: dock profiles Initialize a frontend stack: dock init frontend 🔗 Open Source & Community DevDock is 100% open source under the MIT License! GitHub Repo: github.com/devdock/devdock Web Showcase: devdock.io Give it a spin on your Android phone, tablet, or cloud shell and let me know what you think in the comments below!

2026-08-06 原文 →
AI 资讯

I made stale coding-agent context fail CI instead of failing silently

A coding agent with no context usually hesitates, searches, or asks a question. A coding agent with stale context can be much more confident. That is the dangerous case. The file still exists. The instructions look deliberate. The generated JSON is valid. The agent follows it exactly — into a package that stopped owning the feature two weeks ago. Nothing looks broken until the edit is already in the wrong place. I wanted repository context to have an expiration signal that CI could verify, not a date someone had to remember to check. The failure is not missing documentation Imagine a monorepo where packages/auth owns token validation. The repository publishes a machine-readable handoff: { "startHere" : "docs/for-agents/packages/auth.md" , "editRoots" : [ "packages/auth" ], "checks" : [ "pnpm --filter @example/auth test" ] } Later, token validation moves to packages/security . A maintainer updates the source documentation but forgets to regenerate the handoff index. There are now two internally consistent answers in the same repository: the source documentation says packages/security ; the generated agent context still says packages/auth . The old answer is not malformed. That is precisely why it is risky. I reproduced the drift with one edit I tested this against the public fixture in Doc Bridge , using version 1.2.6. The first index and freshness check passed: Index is fresh expected: 359355e5... actual: 359355e5... Then I changed one agent-facing source document: - Package: packages/os-core - Layer: L1 + +Token validation now belongs to packages/security. I did not touch the generated index. The next check returned exit code 1: ak-docs gate run index-freshness Index is stale. Run: ak-docs index expected: b099695d... actual: 359355e5... After I ran ak-docs index , reviewed the generated change, and ran the gate again, both hashes matched and the check passed. The hashes are not trying to prove that the documentation is true. No checksum can do that. They prove a na

2026-08-06 原文 →
AI 资讯

Cybersecurity Meets Patient Safety: Building an ECG STRIDE Threat Model

* *The purpose of this light version threat model is to demonstrate how STRIDE can be applied to an ECG device. It is intended for readers learning system decomposition and threat modelling techniques. The example includes a simplified set of components, threats, and mitigations for educational purposes and is not intended to represent a comprehensive medical device cybersecurity assessment or any regulatory submission. **Assumption: This example models a typical ECG device, which may include network connectivity in a clinical environment. Trust Boundaries: Trust boundaries exist between the ECG device, hospital network, and external clinical systems. System Definition: ECG is the abbreviation for an Electrocardiogram. It is used to detect electrical activity of the heartbeat in the form of P wave, QRS complex and T wave to identify and diagnose irregularities in heartbeat. Electrodes are placed on patient’s limbs and chest to measure the electrical potentials. It translates tiny electrical signals into digital wave patterns. These waveforms are used by the doctors to evaluate the heart rhythm and check for cardiac damage. Components • Electrodes • Lead wires • Amplifier and filters • Analogue-to-Digital Converter (ADC) • Main processing unit • Display/printer • Local storage • Network interface (Ethernet/Wi-Fi/Bluetooth), if supported. Data Flow Diagram: Electrodes → Lead wires → Amplifier and filters → Analogue-to-Digital Converter (ADC) → Main processing unit → Display / Printer / Local storage / Network interface (if supported) |TRUST BOUNDARY|→ Electronic Health Record (EHR) / Clinical Information System 2. STRIDE Threats: Threats Description Spoofing in general ** - Spoofing is the act of impersonating a legitimate user, device, or system to gain unauthorized access to resources or services. Violates authentication. * Spoofing in ECG * - An attacker may impersonate an authorized clinician, connected medical device, or trusted clinical system to gain unauthoriz

2026-08-06 原文 →
AI 资讯

Sentry Alternatives: When Error Tracking Bills Grow Faster Than Your User Base

If your Sentry bill is climbing faster than your signups, the usual cause isn't more users — it's more events per user . Error trackers meter on event and transaction volume, and a single bad deploy, a noisy third-party SDK, or one uncaught exception in a hot loop can burn a monthly quota in an afternoon. Before you migrate, the honest first move is to fix what you're sending. If you've already done that and the economics still don't work, GlitchTip, self-hosted Sentry, Bugsnag, Rollbar, and an OpenTelemetry-based stack are the realistic exits — each with a different trade. Why does the bill scale with events instead of users? Error tracking is priced on the thing that's expensive to store and index: individual events. Sentry, Rollbar, Bugsnag, and most SaaS competitors bill primarily on captured errors (and, increasingly, performance/tracing spans and session replays as separate meters). A product with 500 daily active users can generate millions of events if one component throws in a render loop or a retry storm hammers a failing endpoint. That decoupling is the whole problem. Your revenue tracks users; your observability bill tracks failures and instrumentation depth . When you add performance monitoring and session replay — both of which emit far more events than plain error capture — the meters multiply independently of how many humans are actually using the app. The takeaway: before you evaluate a single alternative, confirm whether you have a pricing problem or a volume-hygiene problem, because migrating won't fix a firehose. Can you cut the bill without switching tools? Often, yes — and it's worth an afternoon before any migration. The levers that matter most: Sample transactions, not just errors. Performance/tracing volume is usually the bigger line item once enabled. A tracesSampleRate of 0.1 or lower is fine for most apps; you rarely need every transaction. Filter noise at the SDK, before it's billed. ignoreErrors , denyUrls , and beforeSend let you drop

2026-08-06 原文 →
AI 资讯

When Your Content Bot Hits an LLM Quota, Ship the Fallback

A publishing bot that depends on one LLM provider has a boring failure mode: the workflow is green, but nothing gets published. I hit that during cycle #1287. The dev.to key was present, the command was read, and the article module simply returned no action after generation failed with LLM unavailable . That is the kind of failure that looks harmless in CI and expensive in a content pipeline. The fix is not more optimism. The fix is a fallback path that produces a plain, useful, bounded article without calling another model. The Failure Mode Most automation code treats content generation and content publishing as one step. That is convenient until the generator fails after the scheduler, secrets, and publishing client have all done their jobs. Separate Generation From Delivery The publishing client should not care whether an article came from an LLM, a template, or a human-reviewed draft. Give it a strict article object and keep the fallback close to the generation boundary. Make the Fallback Honest A fallback article should not pretend it has fresh benchmarks, citations, or provider-specific pricing. It should explain the operational lesson in front of it. Key Takeaways Treat article generation and article publishing as separate failure domains. Return a fallback article when LLM generation fails instead of returning an empty action list. Keep fallback content honest: no invented benchmarks, prices, or citations. Record the original error type so a successful publish does not hide provider trouble. Prefer deterministic recovery for unattended workflows that are expected to produce public output. Next Steps This fallback article is a temporary solution. The long-term strategy is to: Implement a multi-LLM provider system that can switch automatically Add a quota monitoring dashboard to track usage across providers Create a content buffer that stores pre-generated articles for emergencies

2026-08-06 原文 →
AI 资讯

Vercel vs Netlify vs Cloudflare Pages: Where Your Side Project Should Actually Live

For a side project, the short answer is: Cloudflare Pages if you want the cheapest ceiling and never think about bandwidth, Vercel if you're on Next.js and want the smoothest developer experience, Netlify if you want a mature all-in-one with forms and identity baked in. All three have a free tier that will host a hobby app fine. The differences that actually bite you show up later — when a post gets traffic, when your build gets slow, or when you outgrow static files and start running server code. I've deployed personal projects on all three over the last couple of years. Below is how I'd choose today, with the real trade-offs rather than the marketing version. What are you actually deploying? Before comparing platforms, be honest about your app, because it changes the answer more than any feature chart: Pure static site (docs, a marketing page, a SPA that talks to an external API): all three are excellent and free. The decision barely matters. Static frontend + a few serverless functions (a contact form handler, an auth callback, a small API): now runtime, cold starts, and function limits matter. A full framework app with server rendering (Next.js App Router, SvelteKit, Remix): now framework-specific adapters and edge/runtime compatibility matter a lot. The takeaway: pick based on your heaviest workload, not your current one — migrating hosts after you've wired up auth and functions is the annoying part. How do the free tiers really compare? This is where these platforms differ the most for hobby use. The headline distinction, as of mid-2026: Cloudflare Pages does not meter bandwidth on its free plan , while Vercel and Netlify both count usage (bandwidth, function invocations, build minutes) against free-tier limits and will ask you to upgrade — or throttle — when you cross them. Concern Vercel (Hobby) Netlify (Free) Cloudflare Pages (Free) Bandwidth Metered, capped Metered, capped Unlimited Build minutes Limited Limited Limited (per-month build count) Serverless/e

2026-08-06 原文 →
AI 资讯

The Check That Only Confirmed a Name

The owner had already asked for the alert emails to stop. A fix shipped. Then another email landed. Then another. "ong it just ssent me abother email," he said, voice-dictated, unedited. Fifteen minutes later: "go another one." The system was reporting an outage that did not exist. The Transport That Only Ever Failed A 14-PR merge train had just moved every cron producer's alerting off shared email and onto Buzz, a Nostr-relay team chat. One producer per PR, each with its own liveness contract and a bead receipt. It shipped cleanly. But the library backing those producers carried a default that had only one job: fail. AF_BUZZ_CMD = " ${ AF_BUZZ_CMD :- af_default_buzz_post } " af_default_buzz_post returned 1 with "no Buzz transport injected". Every caller that sourced the library (which is every cron producer) exhausted its Buzz retries and fell through to the email floor. The system reported a false Buzz outage while the relay was healthy. It did this 2 to 5 times per hour. Evidence arrived in the logs: 581 dedup markers, a steady stream of "[INTENT ALERT FLOOR: Buzz unreachable]" emails, and sweep.log showing buzz=ok only for the handful of callers invoked through the CLI entrypoint rather than by sourcing the library. That asymmetry was the bug. The CLI had a one-line fixup swapping in the real transport, annotated in a comment as "the library path is unchanged". The library path did not, and the cron producers all take the library path. The fix promoted the real transport to the default for both seams. af_buzz_transport already discovers the installed buzz-notify.sh and already fails closed when it is genuinely missing. The dead CLI fixup was deleted. Fail-closed behavior survives, but now it is conditional on genuine absence rather than on every caller remembering to opt in. Why not migrate callers one at a time? Because the per-caller route leaves the next new producer to rediscover this the same way. Flipping the default fixes the class, not the instance. The

2026-08-06 原文 →
AI 资讯

I tried using an AI agent to set up a fresh Windows PC and Reddit was right about Ninite

I tried the obvious nerd experiment on a fresh Windows machine: let an AI agent handle setup. It looked clever for about two minutes. Then I watched OpenClaw get stuck on installer checkboxes, pause on modal windows, and generally do the digital equivalent of forgetting why it walked into the room. While it was still fighting one installer, I switched tactics: Ninite for the common app bundle WinGet for package installs I wanted to keep and rerun PowerShell for the boring system-level stuff GPT-5 or Claude for planning, not clicking That combo finished 18 app installs before the agent recovered. And after reading through this r/openclaw thread , I think the real lesson is bigger than Windows setup: GUI-driving agents are the wrong abstraction for deterministic work. If the task is "figure out what this machine needs," use a model. If the task is "install these 18 things and stop being interesting," use scripts. The mistake: asking an agent to be a mouse I’m not anti-agent. I’m anti-fragile-automation. OpenClaw, GPT-5, and Claude are useful when the problem is ambiguous: "Set this machine up for Python, Docker, VS Code, Node, and a local Ollama stack" "Compare package managers and suggest the cleanest install path" "Draft a setup script and explain what might fail" They are much less useful when the problem is fully deterministic: Click Next Decline the bundled toolbar Choose default install path Wait Repeat 17 times That second category is where WinGet, Ninite, and PowerShell win by being boring. Boring is good. This is the same pattern you see in real automations in n8n, Make, Zapier, or custom agent workflows: let GPT-5 or Claude interpret messy input let deterministic steps execute the plan keep the model out of the loop unless judgment is required That architecture is faster, easier to debug, and usually cheaper. What actually worked on a fresh Windows setup Here’s the split I’d use again. Job Best tool Install common desktop apps fast Ninite Create a repeatable

2026-08-06 原文 →
AI 资讯

I let an AI agent into my repo. Here's what I lock down first.

An AI coding agent isn't autocomplete. It runs shell commands, reads your files, installs packages, and opens things you never pointed it at. That's the whole reason to have one. It's also why I don't start projects the way I used to. Nothing dramatic happened to me, by the way. I'm not writing this from the wreckage of a dropped production table. I'm writing it because I spent an afternoon going through what could plausibly go wrong, expecting a long list of hard problems, and instead found that most of it is handled by about ten minutes of config nobody mentions on day one. So here's the ten minutes. Prose isn't protection This is the bit that took me embarrassingly long to get. You can tell an agent things two ways. A rule is prose it reads and weighs - good for judgement calls like naming, style, when to stop and ask. A ban is a config entry that makes something impossible. The trap is using the first for the second job. Writing "never force-push" into a CLAUDE.md feels like a control. It isn't. It's a request sitting in a context window next to a few thousand other tokens, competing with whatever you actually asked for. It'll usually win. Usually is fine for naming conventions. It's not fine for git push --force . 1. The deny list .claude/settings.json : { "permissions" : { "deny" : [ "Bash(rm -rf:*)" , "Bash(git push --force:*)" , "Bash(git push -f:*)" , "Bash(git reset --hard:*)" , "Bash(psql*production*)" , "Bash(*DROP DATABASE*)" , "Bash(*DROP TABLE*)" , "Bash(*TRUNCATE*)" , "Read(./.env)" , "Read(./.env.local)" , "Read(./.env.*.local)" ] } } These don't run. Not "the agent is discouraged" - they don't run, including in the scenario the list exists for, which is you at midnight approving a plan you skimmed. Two things to know before you test it. It takes effect from the next session, not immediately. So you write the file, try the blocked command in the same session, watch it go through, and conclude the whole feature is broken. Restart first. Keep the .env

2026-08-05 原文 →