跳到正文
DEV Community· Sherotree·· 3 小時前AI 評分61

Local-First DX:哪些工作適合放在瀏覽器,哪些應留在 CLI

Local-First DX — What Belongs in the Browser vs a CLI

AI 導讀

作者提出選擇前端本機工具介面的判斷方法:可重複、以磁碟路徑為輸入,或需供 CI 和 Agent 執行的工作適合 CLI;一次性、需要視覺判斷或處理暫存檔案的工作則適合瀏覽器。文章亦提醒,本機瀏覽器工具不應在未經選擇下把資料 POST 到外部服務,並建議團隊避免維護功能重疊的兩套介面。

正文

I keep two folders of “tools I actually use.” One is a terminal aliases file. The other is a browser bookmarks bar labeled local. Both claim to be local-first. They solve different jobs, and mixing them up costs me more time than picking the slower option on purpose.

This isn’t “CLI good, browser bad.” It’s a decision rule for frontend DX: when should this live in the tab, and when should it stay in the shell?

The false dichotomy

People talk like local tooling is one pile. It isn’t.

  • A CLI is scriptable, pipeable, and great at files that already live on disk. Agents love it. CI loves it. Diffs love it.
  • A browser-local tool is visual, drop-zone friendly, and great at blobs you don’t want to save as tmp-whatever-3.png forever. No install. No chmod +x. Close the tab and it’s gone.

Both can keep data off a third-party server. That’s the local-first part. The UX surface is what actually changes how you work.

Where I default to the CLI

I reach for the shell when most of these are true:

  1. The input is already a path — repo files, dist/, fixtures, screenshots in e2e/artifacts/
  2. I need to repeat it — same transform tomorrow, or in CI, or for every PR
  3. I want a pipe — rg → jq → script → commit message
  4. An agent will do it — coding agents are fluent with argv and stdout; they’re clumsy in a GUI
  5. Exit codes matter — green/red in CI beats “looks fine in the preview pane”

Examples that belong here for me:

  • Lint, typecheck, format, bundle-size budgets
  • Image optimization of a whole public/ folder
  • Converting a design-token JSON into CSS variables as part of build
  • Replaying a failing Playwright run with the same flags

If I have to teach a teammate (or an agent) a click path, I’ve already lost the CLI case.

Where I default to the browser

I open a local page / side panel when most of these are true:

  1. The input is a blob I don’t want on disk yet — paste, drag-drop, clipboard screenshot
  2. I need eyes — color, layout, chart shape, crop, “does this GIF feel right”
  3. One-shot — I’m not putting this in CI; I’m answering a Slack “can you check this file”
  4. Install friction would kill the job — non-dev collaborator, locked-down laptop, hotel Wi‑Fi where npm i is a joke
  5. The output is also a blob — download once, attach, done; no need for a long-lived path in the monorepo

Examples:

  • Quick HEIC / WebP peek before I decide whether to commit it
  • Charting a client CSV I’m not allowed to upload anywhere
  • Diffing two JSON pastes from support tickets
  • Checking contrast on a hex someone dropped in chat

If the “tool” requires me to invent a filename first, the browser usually wins.

The agent angle (this changed my defaults)

Coding agents flipped a few of my old habits.

Agents are excellent at CLI. They can run pnpm test, read the log, and try again. They are mediocre at “open this URL, drop a file, click Export.” So anything I want agents to own — refactors, migrations, CI gates — stays CLI-shaped.

But agents also create a lot of visual leftovers: screenshots, generated SVG, “try this CSS,” chart previews. Those leftovers are terrible as permanent repo files and fine as ephemeral browser transforms. I stopped asking the agent to curl a SaaS converter for those. I either keep a local browser tool bookmarked, or I ask the agent to write a small Node script if the job will recur.

Rule of thumb I use now:

If the agent should do it twice, make a CLI (or a script in the repo).

If a human needs to see it once, keep it in the browser.

A boring decision checklist

When I’m adding a new “helper” for the team, I ask:

Question Lean CLI Lean browser
Will CI run it? yes no
Is the primary input a disk path? yes no (paste/drop)
Is judgment visual? no yes
Should an agent own the loop? yes no
Do non-devs need it without Node? no yes
Is the artifact temporary? maybe usually

If the table splits 3–3, I build the CLI first and add a thin browser UI later only if humans keep bouncing off the flags. Flags are documentation; a drop zone is empathy. Both can exist — just don’t start with two surfaces.

Anti-patterns I’ve paid for

Electron for a one-button transform. Congrats, you shipped an OS update surface for a FileReader job.

“Just paste into this SaaS.” Local-first died the moment the paste left the machine. Browser-local and cloud-paste are not the same category.

CLI with no --stdin / no file args, only interactive prompts. Agents and CI choke. If it’s CLI, make it non-interactive by default.

Browser tool that quietly POSTs “for processing.” Read the network tab once. Local means the heavy work stays in-tab unless I opt in.

How I keep the split sane on a team

  • Repo scripts for anything that gates merges (package.json scripts, just, make — pick one).
  • A short internal doc titled “browser-local helpers” with 5–10 bookmarks, not 40. If it isn’t in the doc, it isn’t a team tool.
  • No duplicate truth — don’t maintain a CLI and a web UI that drift. Prefer one engine (shared WASM / shared Node package) and two thin fronts only when both audiences are real.
  • Name the constraint in the PR — “this is agent-facing → CLI” or “this is designer-facing → browser” stops bikesheds.

Takeaway

Local-first isn’t a single product category. It’s a privacy/ownership promise that still needs a surface.

Put repeatable, path-based, agent-friendly work in the CLI. Put visual, ephemeral, drop-zone work in the browser. Optimize for who (or what) will run the loop next — you once, CI forever, or an agent at 2 a.m.

The wrong surface doesn’t just feel awkward. It quietly pushes people back to uploading files to whoever’s landing page loaded first. Pick deliberately, and the local habit sticks.

來源:DEV Community · dev.to