@delacour/warden

中文文档
0.16.0发布于 2026/11/09MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 4887

AI agent toolkit for React Native and Expo: every coding agent gets its own iOS simulator or Android emulator to drive, debug, profile and E2E test the app, with devices, ports and app builds leased machine-wide

原始使用文档
文档目录18 节
  1. Install
  2. Update
  3. Releasing
  4. Usage
  5. Installing warden in GitHub Actions
  6. Fast new simulators: golden images
  7. Device health
  8. A new Expo app: warden init , warden dev , warden e2e
  9. e2e scripts: warden run
  10. Batches: warden batch
  11. Affected e2e: warden affected / warden e2e
  12. Benchmarks
  13. App builds
  14. Driving a device (agents)
  15. Claude Code
  16. Codex
  17. Development
  18. License

warden

An AI agent toolkit for React Native, Expo and native iOS and Android apps: your agent drives, debugs, profiles and E2E tests the app on its own simulator. Underneath, warden leases iOS simulators, Android emulators, ports and native app builds machine-wide for agents, Orca worktrees, repos and humans sharing one Mac. A device or port leased by one owner is never handed to another.

  • Leases live in one sqlite db (~/.warden/warden.db, WAL). Claims run under BEGIN IMMEDIATE, which serialises them across processes.
  • Owners: a Claude session (hook stdin, CLAUDE_CODE_SESSION_ID, WARDEN_SESSION_ID), CI (CI, GITHUB_RUN_ID), or a user shell (parent pid). The repo and worktree are recorded for messages.
  • Liveness: a lease stays alive while its pid is alive or its heartbeat is within the TTL (default 30 min; a bare warden claim by an agent gets 5 min and prints a hint, so only wrappers or warden heartbeat hold a device longer). Stale leases are reclaimed on every claim and by warden gc. Leases of a warden run / dev / batch / e2e that died go stale after three missed heartbeats (90 s).
  • Devices: warden creates and reuses its own warden-<profile>-N simulators and launches -read-only emulators. It never allocates, shuts down or erases a device it didn't create, unless you pass --adopt.
  • Builds: Expo fingerprint → installed → local cache → EAS → local build. All worktrees of a repo share one cache.

Install

npm i -g @delacour/warden && warden install    # or: bun add -g @delacour/warden && warden install

warden install wires hooks for every detected agent (Claude Code / Codex), showing a diff and asking first. Hooks call ~/.local/bin/warden, which install links to the global package, so npm i -g @delacour/warden@latest upgrades both.

One-shot, nothing installed globally:

npx @delacour/warden install     # or: bunx @delacour/warden install

This copies the binary to ~/.local/bin/warden and wires the hooks. It only puts warden on your PATH if ~/.local/bin is already on it (macOS doesn't add it by default). If warden isn't found afterwards, use the global install above. To update a one-shot install, run warden update, which fetches it from npm, or re-run npx @delacour/warden@latest install.

The npm package is a small node shim plus one prebuilt binary per platform (@delacour/warden-{darwin,linux}-{arm64,x64}, installed as an optional dependency). Windows isn't supported. Package managers that skip optional dependencies (--omit=optional) leave the shim without a binary, and it says so.

From source:

bun install
bun run --cwd apps/cli install:global   # local build of this checkout → ~/.local/bin/warden
warden install                           # binary + hooks for every detected agent (Claude Code / Codex); shows diff, asks first
warden install --claude                  # force Claude Code only: skill + SessionEnd hook
warden install --codex                   # force Codex only: hooks in $CODEX_HOME/hooks.json
warden doctor

Working on warden itself: bun run cli:link points ~/.local/bin/warden at this checkout's source (no rebuilds), and bun run cli:unlink puts back whatever was there before.

Agent skill only, for Claude Code, Codex, Cursor and others via the skills CLI:

warden skill show | pbcopy                 # raw SKILL.md to paste by hand
warden skill show --file references/ui.md  # print one file of the skill folder
warden skill install                       # bunx skills add ~/.warden/skill --skill warden -g (this binary's copy)
warden skill install --from github         # bunx skills add delacournz/warden --skill warden -g (updatable via `skills update`)
warden skill install --project -a claude-code -y   # into the current project, one agent, no prompts

The skill is a folder, skills/warden/ (SKILL.md + references/{ui,specs,suites,troubleshooting}.md), embedded in the binary. npx is used when bunx isn't available; --dry-run prints the command.

For source builds and one-shot installs, ~/.local/bin must be on PATH. Set WARDEN_HOME to override ~/.warden.

Update

warden update does the right thing for however warden was built (warden version shows which):

Buildwarden update
dev: running from source (bun apps/cli/src/cli.ts update)compiles a local binary from this checkout → ~/.local/bin/warden
local: compiled from a checkoutrebuilds from the checkout it was built from, in place (--release switches to releases)
release: downloaded from GitHubgh release view → newer? download warden-<os>-<arch> → verify sha256 → self-check → swap in place. If GitHub releases can't be reached (no gh, no repo access), it falls back to npm
release: copied by npx/bunx @delacour/warden installnpm registry: @delacour/warden/latest → newer? download @delacour/warden-<os>-<arch> → verify sha512 dist.integrity → self-check → swap in place
npm: @delacour/warden via npm / bun / pnpm / npx / bunxprints the package manager's upgrade command (e.g. npm i -g @delacour/warden@latest, npx @delacour/warden@latest install) and leaves node_modules alone; --to <path> still installs a standalone release binary

The binary is swapped atomically at the same path, so the next warden in your current shell runs the new version. No new shell or source is needed; if PATH resolves warden elsewhere, update warns you. Flags: --check (report only), --release (install the latest GitHub release; also switches a dev/local build to it), --force, --to <path>, --json. Releases come from the public delacournz/warden repo through gh. Set WARDEN_RELEASE_REPO to use another repo, and WARDEN_NPM_REGISTRY to use another npm registry.

Releasing

  1. PRs target develop. One that changes what @delacour/warden ships adds a changeset: bun changeset, pick @delacour/warden, choose patch / minor / major, write a one-line summary. @delacour/warden-e2e follows in lock-step. Docs-only and internal-only PRs need none.
  2. Every push to develop opens or updates the "🔖 chore(release): vX.Y.Z" PR, titled with the version it will ship. It bumps the versions, writes CHANGELOG.md and consumes the changesets.
  3. Merge that PR. promote.yml fast-forwards main to the merge commit and pushes tag v<version>. Nobody pushes main or tags by hand.
  4. main is what the docs site deploys. The tag runs .github/workflows/release.yml, which checks the tag matches the version, runs typecheck/check/test, builds warden-{darwin,linux}-{arm64,x64} plus checksums.txt and publishes the GitHub release.
  5. The same workflow stages the npm packages (bun run --cwd apps/cli build:npm → apps/cli/dist/npm/) and publishes @delacour/warden-<os>-<arch>, then @delacour/warden, then @delacour/warden-e2e, with public access and provenance through npm trusted publishing (OIDC, no token). Versions already on npm are skipped, so a re-run finishes a partial publish.

Never edit version by hand. bun run release <version> is a break-glass for when CI is down: it bypasses changesets and the version PR.

Usage

warden claim ios --json                          # lease 1 sim (reuse → boot → create), booted + ready
warden claim android --profile pixel-10 --count 2
warden claim ios --count 2 --wait 10m --ttl 1h --label e2e
warden claim ios --priority high --no-wait       # WARDEN_CAPACITY=on + host full → queue by priority (default --wait 30m); --no-wait fails fast
warden capacity [--json]                         # host budget (RAM + perf cores), usage, what binds, whether limits are enforced (off by default)
warden queue [--json]                            # claims waiting for a boot slot: position, priority, age
warden release --mine [--label x] [--shutdown]   # or <leaseId…> | --udid X | --session S; --label = only --mine leases with that label; --shutdown = warden-created or self-booted sims
warden release <leaseId> --bad [reason]          # release + quarantine the device (claims skip it); clear: warden sim unquarantine <udid>
warden sim slim <udid> [--restore] [--except <ids>] # iOS sims warden creates are slim by default (--no-slim / WARDEN_SLIM=0 opts out); a plain `warden claim` no longer restores, --restore does
warden sim profiles | warden sim measure [udid]     # slim categories for --except; a sim's real memory (also: warden devices --mem)
warden ls                                        # leases: resource, state, owner, repo/worktree, age, heartbeat
warden clone <udid|name> [--name x]              # duplicate a shut-down sim into the pool (seconds, no first boot)
warden golden ensure|ls|prune [--all]            # golden iOS images / Android snapshots new devices start from
warden arrange                                   # tile warden simulator windows in name order (macOS; also runs after iOS claims)
warden telemetry [status|enable|disable]         # anonymous usage telemetry: on by default, commands + flag names only; off with WARDEN_TELEMETRY_DISABLED=1 / DO_NOT_TRACK=1
warden doctor [--json]                           # check home, db, device tools, helper, install method, hooks, stale leases
warden devices [ios|android]                     # every sim/emulator (booted or not) + AVDs, warden-owned?, leased by (alias: list)
warden sims [--max-size 40G]                     # disk audit: every sim + runtime, size, owner, lease, what can go
warden sims prune [--dry-run|--yes]              # delete idle/orphaned/broken warden sims (+ LRU over --max-size)
warden sims delete [udids...|--suggested] [-y]   # multi-select → confirm → delete sims; stale/dead/duplicate ones pre-ticked (--dry-run)
warden check --udid <udid>                       # exit 2 if another owner holds it
warden heartbeat --mine
warden gc [--idle 20m]                           # reclaim stale leases, shut down idle warden devices

warden port claim --from 8091 --span 20 --json
warden port release --mine

Installing warden in GitHub Actions

The npm package is not required for CI: the release workflow attaches a compiled single-file binary per platform (warden-darwin-arm64 …, plus checksums.txt) to each GitHub release, and a composite action in this repo installs the right one:

- uses: delacournz/warden/.github/actions/install-warden@main
  # with:
  #   version: v0.1.0   # optional pin; token defaults to github.token

token (it drives gh) defaults to the workflow's own github.token, which is enough because the repo is public, so no PAT and no Actions access setting are needed. The action verifies the sha256 and puts warden on PATH. A bare script works too: gh release download --repo delacournz/warden --pattern warden-darwin-arm64 --pattern checksums.txt.

A clean macOS runner needs no prior state: the --profile is created on claim (cloned from a golden image that is built on first use, about a minute or two; cache ~/Library/Developer/CoreSimulator/Devices between runs to keep it) and falls back to simctl create. The runner must have the iOS runtime installed.

Fast new simulators: golden images

A brand-new simulator's first boot (Apple logo + progress bar) takes 1–10 min, and about 80% of that is the one-time data migration. The salient e2e measurements (SAL-GOLDEN):

ScenarioTime
fresh create + first boot146–239 s
clone of a settled golden + boot3.7 s + 11.9 s
3 clones booted in parallel~20 s

So when warden claim ios needs a new pool device, it simctl clones it from a golden image. That is a sim warden booted once, waited on until its data migration had finished (DMLastMigrationResults, since bootstatus -b can return early) and its CPU had settled, then shut down. The golden is built on first use and keyed by Xcode build + runtime + runtime build + device type + recipe, so an Xcode or runtime upgrade simply builds a new one (warden golden prune removes old ones). Clones are APFS copy-on-write (~30 MB each). If cloning fails, warden falls back to simctl create. Set WARDEN_GOLDEN=0 to turn cloning off.

  • warden golden ensure [--profile iphone-17]: build ahead of time, so the first claim doesn't pay for it.
  • A claim that has to build the golden prints building golden for <profile> … prewarm with: warden golden ensure --profile <profile> on stderr first.
  • warden clone <udid|name> [--name x]: duplicate any shut-down sim, e.g. one you've set up by hand, into warden's pool. warden refuses a booted source rather than shutting it down.
  • Goldens are never allocated, adopted, booted by gc or counted in the pool, and warden devices labels them golden.
  • A pool device that already exists is always reused first; a second boot takes ~6.5 s.

Device health

  • After booting (or reusing) an iOS sim, warden claim probes it: simctl spawn <udid> launchctl print system must answer within 5 s and SpringBoard must be running. A sim that fails is quarantined (and shut down) and another one is claimed, up to 2 retries, then a clear error. Foreign devices that fail are only skipped. Android has no probe yet.
  • warden release <id> --bad [reason] quarantines the released warden device by hand. warden devices shows quarantined / slim. warden sim unquarantine <udid|serial> clears it.
  • warden app ensure re-installs when the app on the device no longer matches the cached build (iOS: CFBundleVersion, executable size and main.jsbundle size).

A new Expo app: warden init, warden dev, warden e2e

warden init --bundle-id com.example.app   # bundle id → app.json, warden.config.ts, e2e/smoke.e2e.ts
warden dev                                # lease a sim, build / reuse the dev client, own Metro port, open the app
warden e2e --count 3                      # the e2e/ specs on the dev client, spread over 3 leased sims
  • warden dev [platform] defaults to iOS. Every run leases its own Metro port (8081:100), so agents in different worktrees iterate side by side. Before leasing anything it checks for the bundle id and expo-dev-client and prints the fix.
  • The default local iOS build prepares a fresh checkout itself: expo prebuild when ios/Podfile is missing, pod install when the Pods are missing or out of sync, then expo run:ios. A configured build.ios is run as written.
  • With no e2e suite in the config, warden e2e runs every *.e2e.ts spec under e2e/ with @delacour/warden-e2e (one bun test process per device) over 2 simulators, on the dev client and a Metro warden starts. warden init writes that suite out so you can edit it. It names the packages to install (expo-dev-client, @delacour/warden-e2e@<warden version>) and installs nothing.

e2e scripts: warden run

warden run ios --count 2 --port 8091:20 --port 3208:20 [--app] -- bun run e2e

warden run claims the devices and ports, then runs the command with WARDEN_UDIDS, WARDEN_UDID_<i>, WARDEN_LEASE_IDS, WARDEN_PORTS and WARDEN_PORT_<i> set. It heartbeats every 30 s, forwards SIGINT/SIGTERM, releases everything on exit and passes the exit code through. With --app, it first ensures the dev build is installed on each device (WARDEN_APP_PATH / WARDEN_APP_HASH).

Batches: warden batch

ls specs | warden batch ios --count 5 --max 5 --port 8091:20 --serve "bun run metro" --serve-ready tcp:8091 --jobs-from - --retry 1 -- bun run e2e:spec {job} --device {udid}

warden batch claims N devices and runs a job queue across them, one worker per device: {job}, {udid}, {worker} and {seq} are substituted into the command, which also gets WARDEN_UDID, WARDEN_WORKER, WARDEN_JOB and WARDEN_JOB_SEQ. --serve starts a long-lived process (Metro) first and waits for --serve-ready. A live grid tracks every device, and --record <dir> (iOS) captures each simulator, the grid and a batch.json timeline (scripts/demo/compose.ts tiles them into one video). It exits 0 only when every job passed.

Save a batch in warden.config.ts and run it by name:

export default defineConfig({
  batches: {
    "salient-e2e": {
      project: "salient", platform: "ios", count: 5, max: 5, profile: "iphone-17",
      ports: ["8091:20"], app: true, retry: 1,
      env: { E2E_SESSION_FILE: "e2e-artifacts/batch/session.json" },
      serve: "bun scripts/e2e/run-ios.ts --session", serveReady: "file:e2e-artifacts/batch/session.json", serveTimeout: "20m",
      jobsFrom: { command: "bun scripts/e2e/select-specs.ts --list --offline" },
      cmd: ["bun", "scripts/e2e/run-ios.ts", "--attach", "{job}", "--device", "{udid}"]
    }
  }
});
warden batch salient-e2e                        # the preset as-is
warden batch salient-e2e --count 2 -- bun e2e {job}   # passed flags and -- <cmd> override it

Flags you pass override the preset (commander defaults don't). --jobs / --jobs-from replace its jobs source, and -- <cmd> replaces cmd. With project, serve, jobs and jobsFrom.command run in that project's root, relative preset paths resolve against it and app installs that project's build. Without project, the preset's cwd is the config file's directory. CLI paths resolve against your cwd. env is added to serve and job env. label defaults to the preset name and applies to the port leases too. Fewer jobs than count claims one device per job.

Affected e2e: warden affected / warden e2e

warden affected mobile --base origin/main --explain   # which specs this branch needs, and why
warden e2e mobile --base origin/main --count 2        # run them on leased devices; exit 1 if a required one fails

An e2e.<suite> in warden.config.ts maps spec files to the screens they drive (entries) and globs (paths). Warden takes the git diff against the merge-base, walks each spec's import graph with the TypeScript resolver (tsconfig paths, workspace packages, per-platform .ios / .android files, type-only imports dropped), and runs only the specs a changed file reaches, with runAll globs (lockfile, native dirs) selecting everything. warden e2e runs them like warden batch, each passes times, and writes e2e-report.json. See the Affected e2e guide.

Dev-client suites add metro: {}: warden e2e <suite> then leases a port, starts its own Metro in the project root, waits until that port is proven to serve this checkout (another worktree's Metro on it fails the run instead of being attached to), prewarms the bundle and exports WARDEN_METRO_URL / WARDEN_PORT to the spec processes. devices: [{ profile, count, env, default }] runs several device legs concurrently (--devices all), a spec process runs per device over its share of the specs (isolate: "spec" runs one per spec), and jobTimeoutMs (default 10 min per spec) kills a hung spec process.

Specs are *.e2e.ts specs written with @delacour/warden-e2e (bun add -d @delacour/warden-e2e, same version as warden) and run by bun test --preload @delacour/warden-e2e/preload (or a bunfig.toml preload): test("…", async ({ app, device, screen }) => { await expect(screen.getByTestId("x")).toBeVisible(); }). warden e2e leases the devices, installs the build, sets WARDEN_UDID / WARDEN_BUNDLE_ID / WARDEN_LAUNCH_ARGS and friends, and judges each spec from the spec's results.jsonl; spec: { bundleId, launchArgs, timeout, actionTimeout, assertionTimeout } on the suite tunes it, warmDrivers: false (or --no-warm) skips the iOS helper pre-warm. A failed test leaves failure.png, screen-at-failure.txt and trace.jsonl under <batchDir>/e2e/<worker>-<seq>/. See the docs guide Write specs (e2e/specs).

Benchmarks

packages/e2e-bench runs the same 8-test suite through warden, Maestro, Detox and the retired Argent, agent-device and tester.army on one leased device and writes a Markdown + HTML report (suite and per-test timings, cold start, resources, residue).

Latest iOS run on EAS (2026-10-25, warden 0.3.1): warden ran the warm suite in 86.30 s, 1.56× faster than Argent, 1.06× faster than agent-device and 1.54× faster than tester.army, with a per-step median of 85 ms against 321 to 481 ms. Full tables and every artifact: warden.co.nz/docs/e2e/bench/comparison.

bun run bench doctor && bun run bench run --platform ios --runs 3

See packages/e2e-bench/README.md for fairness rules and caveats, and docs/bench/ for published results.

App builds

warden app fingerprint ios
warden app ensure ios --udid <udid> --json   # { appPath, hash, source: installed|cache|eas|build, installed }
warden builds ls | prune --max-size 20G | import <App.app> --hash <h>

Optional warden.config.ts at the repo root (bun add -d @delacour/warden for autocompletion; warden.config.json still works):

import { defineConfig } from "@delacour/warden/config";

export default defineConfig({
  projects: [{
    name: "salient",
    root: "apps/salient/app",
    bundleId: { ios: "com.example.salient", android: "com.example.salient" },
    fingerprint: { command: "bun run --silent fingerprint:{platform}" },
    eas: { profile: "development-simulator", workflow: ".eas/workflows/dev-build.yml", trigger: false },
    build: { ios: "bunx expo run:ios --no-install --no-bundler" }
  }]
});

With no config, warden detects a single project from app.json / app.config.* (pass --bundle-id for a dynamic config). It resolves builds in this order: already installed at this hash → ~/.warden/builds/<projectKey>/<platform>/<hash> → legacy caches → EAS (build:list --fingerprint-hash, then download; waits for builds in flight; triggers the workflow only if trigger is set) → local build, which is verified against the fingerprint. A build lock stops two agents from downloading or building the same hash twice.

warden install wires hooks into every agent it detects: Claude Code (~/.claude or claude on PATH) and Codex ($CODEX_HOME / ~/.codex or codex on PATH). --claude / --codex force one (or both) regardless of detection. Every agent config change shows a diff and asks first (--yes skips, --dry-run only prints, a non-TTY without --yes skips). Merges are idempotent and keep all other config.

Driving a device (agents)

Claim, then pass the device explicitly: warden claim ios --json → use the returned udid (Android: the serial) on every call. A bare agent claim lasts about 5 min and nothing refreshes it; only warden dev / run / batch / e2e or an explicit warden heartbeat <leaseId> hold a device longer. For exploration, run warden dev ios --json in the background (claims and holds a device + a Metro port, starts a Metro verified to serve this checkout, opens the dev client) and target the udid from its first stdout line. Subagents never call release --mine: use release <leaseId>, or claim with --label x and release --mine --label x. Look at and drive the device with warden ui, an agent CLI over the same driver the specs use: warden ui open <bundleId> --udid <udid> → snapshot -i (the screen as @eN lines) → press @e3 --settle / fill id=email "…" / scroll down --until text=Done → wait id=todos-screen / is / get → close --release. It checks the lease on every call (exit 2 on a foreign or missing one; --claim leases a device) and --json prints one {ok, …} document. Selectors: id=… label=… text=… role=… value=… editable=… nth=…. Guide: apps/docs agents/ui.

To create an e2e spec, drive the journey between warden ui record start <id> and warden ui record stop: record note|undo|status|cancel shape it, stop writes e2e/<id>.e2e.ts and runs it once on the same device (--no-verify skips; --helper <module#fn> writes a reusable function instead). snapshot -i marks elements without a testID [no-id]; fill --secure reads WARDEN_UI_SECRET_<NAME>. Guide: apps/docs guides/author-specs.

Claude Code

warden install --claude adds:

  • a SessionEnd hook, which shuts down the session's sims and releases its leases, so nothing is left running. Only sims warden created, or that the session booted itself (they were off when it first touched them), are shut down. A sim that was already running when the agent picked it up, such as your own Simulator.app one, is released but left on. On /clear (reason clear) sims keep running: the conversation restarts, the work usually continues, and the new session re-claims the sim with its next warden claim. Leases a still-running warden e2e / batch / run / dev holds are kept too; a run whose leases are released under it stops and says so.
  • Sessions that die without SessionEnd (killed or terminal closed): their leases go stale after their TTL (30 min; 5 min for a bare agent claim). warden gc then shuts those sims down under the same rule, but only 10+ min after the lease went stale and never while a non-Apple app is running on the sim. gc runs automatically in the background at most every 10 min, triggered by claim/run (WARDEN_AUTO_GC=0 turns this off), as well as on demand.
  • the skill folder (SKILL.md + references/), staged in $WARDEN_HOME/skill/warden/ and installed with the vercel skills CLI (bunx skills add <dir> --skill warden -g -a claude-code -y, npx fallback; --dry-run prints the command), which places it at ~/.agents/skills/warden and symlinks ~/.claude/skills/warden. Without bun or node this step is skipped; use warden skill show. It also writes, directly, the rule ~/.claude/rules/warden.md. A leftover ~/.claude/rules/agent-device.md or argent.md from the retired setup is reported but never deleted.

It also removes the PreToolUse device-lease hook older versions installed (warden hook pretool stays a no-op, so an old config keeps working).

Codex

warden install --codex merges the SessionEnd hook into $CODEX_HOME/hooks.json (default ~/.codex/hooks.json; hooks already declared in config.toml [[hooks.*]] tables count as installed). Codex hooks use Claude's format and stdin JSON, so warden hook session-end serves both agents unchanged:

{
  "hooks": {
    "SessionEnd": [{ "hooks": [{ "type": "command", "command": "$HOME/.local/bin/warden hook session-end", "timeout": 3 }] }]
  }
}
  • Codex skips new or changed hooks until you trust them: run /hooks in Codex once after installing.
  • Codex caps SessionEnd hooks at 3 s and always sends reason other, so the /clear keep-sims-running exception never applies there. Anything the SessionEnd hook can't finish in time is picked up by warden gc once the leases go stale.
  • For the skill in Codex, use warden skill install.

Development

bun run test        # turbo: core + cli (incl. cross-process race tests)
bun run typecheck
bun run check       # biome

See AGENTS.md and the plan in docs/plans/wdn-warden-cli.md.

License

MIT

版本与发布记录

@delacour/warden 共发布 19 个版本,首次发布于 2026/10/19;过去 12 个月发布了 19 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.16.0latest2026/11/092 天前
0.15.02026/11/093 天前
0.14.02026/11/065 天前
0.13.02026/11/065 天前
0.12.12026/11/066 天前
0.12.02026/11/066 天前

关于 @delacour/warden 的常见问题

@delacour/warden 是什么?

AI agent toolkit for React Native and Expo: every coding agent gets its own iOS simulator or Android emulator to drive, debug, profile and E2E test the app, with devices, ports and app builds leased machine-wide

如何安装 @delacour/warden?

在项目目录运行 npm install @delacour/warden,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 warden,可以用 npx warden 直接运行。

@delacour/warden 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@delacour/warden 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@delacour/warden 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@delacour/warden 可以商用吗?

@delacour/warden 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@delacour/warden 的下载量有多少?

根据 npm 官方下载统计,@delacour/warden 在 2026/10/12 – 2026/11/10 这 30 天内被下载 4,887 次,日均约 163 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@delacour/warden 还在维护吗?

最新版本 0.16.0 发布于 2026/11/09(2 天前);至今共发布 19 个版本,其中过去 12 个月发布了 19 个;首次发布于 2026/10/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。