Skip to main content

arc service

arc service manages named AFS background instances: list, start, stop, restart, status, delete, gc, url, and logs.

arc service manages named AFS background instances. arc afs, MCP bridging, and blocklet serving all depend on a running instance.

Captured against arc 2.0.0-beta.48, commit 5a5316bde (main, 2026-09-10) — not the published binary of the same version string; two different builds have carried 2.0.0-beta.48 at once, so this page is pinned to the commit, not the semver. arc service is nine real subcommands (arc service <verb> [options]), each with its own --help and Examples: block — not one command with a positional action choice list. --json reject path remeasured after ArcBlock/arc#5205 (error object on stdout — corrected again below, see --json contract); delete became the primary action name after ArcBlock/arc#5279 (rm/remove are now aliases); the subcommand split and the ERROR: prefix on every failure line are both ArcBlock/arc#6301. Positional instance names were removed in ArcBlock/arc#5713: the only way to pick an instance is --instance / -i. Run arc --version before you copy dumps; verbs and flags can still move. --help text below is English (LC_ALL=C) — since ArcBlock/arc#5244, help/error text is always English regardless of your system locale.

Instance names, home paths and ports below are shortened to a readable docs514a / /tmp/arc-svc-docs-514/... form; the message text, field names, exit codes and JSON shapes are copied verbatim from a real run.

bash
arc service <verb> [options]

verb is one of list (ls, ps), start, stop, restart, status, delete (rm, remove), gc (prune), url, logs (log). Pick the instance with --instance <name> / -i. Omit --instance to operate on the seed instance default (home ~, port 4900). Any other name gets a kernel-assigned port unless you pass --port.

Do not stop or delete a seed instance you did not start. The dumps on this page used a throwaway registry and never touched the machine's default on :4900.

Isolation

Named instances plus --home are the isolation mechanism. ARC_HOME is retired: the CLI warns and ignores the value.

bash
export ARC_INSTANCES_DIR=/tmp/arc-svc-docs-514/instances
arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b

ARC_SERVICE_PORT still exists, but it only affects the unnamed seed instance. Prefer a name, or pass --port.

Splash banner lines on stderr are omitted in the dumps below.

Subcommands

Each subcommand carries its own --help and its own Examples: (see the --help section at the bottom of this page). arc service <bad-verb> and arc service with no verb both print the group listing below, not a per-verb one.

SubcommandAliasesWhat it does
listls, psList every local instance with its status, port and home
startStart an instance, creating it on first use
stopStop a running instance, keeping its record and data
restartRestart an instance from its recorded config — does not reconfigure; stop then start for that
statusReport whether an instance is running, and on which port
deleterm, removeDelete an instance: its record and its data
gcpruneDrop registry records whose process is gone
urlPrint an instance's base URL (and its blocklets')
logslogPrint an instance's daemon log

Flags

Every subcommand accepts the shared globals — --json, --view, --home, --instance / -i, --print — plus its own extra flags:

FlagSubcommand(s)Meaning
-i, --instanceallNamed local ARC instance this command operates against. Omit for default. This is the only way to pick an instance
--homeallInstance root. Used by start (create) and arc did init. On restart it is cross-checked against the recorded home rather than accepted as new config — matching it is a no-op, naming a different path is rejected (see Failures)
--printallPrint one result field (for example url, port) as plain text — not a view; overrides --json/--view. See --print below
--portstartListen port (0–65535). 0 = auto-assign. Omit: default uses 4900, named instances use the recorded port or auto-assign
--hoststartBind address (localhost, 0.0.0.0, ::, or a unicast IP). Default localhost
--advertisestartAdvertise over mDNS when bind is non-loopback (default true; --no-advertise disables)
--blockletstartBlocklet-parent or single-blocklet dir to serve (repeatable). Recorded on the instance
--space-rootstartFolder-as-DID-Space from arc space init. Omit to derive from --home
--forcedeleteStop a running instance before deleting it. Default false
--dry-rundeletePrint what would be removed without deleting it. Default false
--yesdeleteSkip the TTY confirmation prompt. Default false
--followlogsStream new lines as they are written. Default false

--yaml was removed, never implemented — see Overview.

restart has none of start's config flags in its own --help — passing one is refused with a dedicated message, not yargs' generic "unknown argument" (that generic path is what genuinely-removed flags like --blocklet-dir hit; see Removed and retired):

bash
$ arc service restart --instance docs514a --port 4910
ERROR: restart does not reconfigure. use `stop` then `start` to change --port

--home is the one exception: it is a global flag, so restart --home <same path as recorded> succeeds silently (a no-op), and only a different path is rejected — with a different message and exit code than the config-flag guard above:

bash
$ arc service restart --instance docs514a --home /tmp/somewhere-else
ERROR: --instance "docs514a" and --home "/tmp/somewhere-else" name different instances (instance "docs514a" is registered at "/tmp/arc-svc-docs-514/home-a")

(exit 5, versus exit 1 for --port/--host/--advertise/--space-root/--blocklet.)

States

StatusMeaning
startingRecord claimed, process not yet up
upProcess is listening
stoppedProcess exited through stop. start / restart reuse the record
deadProcess gone without a clean stop. gc removes only this state

list shows the recorded port for every non-up row, suffixed * to mark it last-known rather than live (stopped/dead both get the suffix); - appears only when there is no recorded port at all (an instance that never reached up):

NAME          ID                PORT    STATUS   HOME                          SOURCES
docs514a      b719db414c5cc62  61497*  stopped  /tmp/arc-svc-docs-514/home-a  1

status exits 0 for up, 3 for starting / stopped, and 4 for dead. For anything but up it still reports the pid / port / URL from the last run, and marks them as such (lastKnown in --json, a Note: line in the human view).

Start, list, status, url

Empty registry:

bash
$ export ARC_INSTANCES_DIR=/tmp/arc-svc-docs-514/instances
$ arc service list
NAME          ID                PORT   STATUS   HOME                          SOURCES
(no instances)

Start a named instance. Port 61497 was kernel-assigned, not 4900:

bash
$ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a
  Instance: docs514a
  ID:       b719db414c5cc624
  Status:   up
  PID:      95665
  Port:     61497
  URL:      http://127.0.0.1:61497
  Home:     /tmp/arc-svc-docs-514/home-a
  Space:    /tmp/arc-svc-docs-514/home-a/.afs/spaces
  Sources:  -
  Version:  2.0.0-beta.48
  Commit:   5a5316bde
  Checkout: /tmp/arc-svc-docs-514/project
  Host:     localhost
  Started:  2026-09-10T01:52:25.130Z (up 2s)

Progress, log path, build id, and endpoints went to stderr. The instance record went to stdout — stderr on this capture (omitting the banner):

Starting AFS service...
AFS Service started
  Log:  /tmp/arc-svc-docs-514/home-a/.afs/daemon.log
  Build: 2.0.0-beta.48+5a5316bde (debug)
  Exec:  /path/to/arc/runtimes/node/dist/cli.mjs

  Endpoints:
    http://127.0.0.1:61497/            AUP Web Client
    http://127.0.0.1:61497/explorer    Explorer UI
    http://127.0.0.1:61497/ws          WebSocket (Explorer)
    http://127.0.0.1:61497/afs/*       REST API
    http://127.0.0.1:61497/mcp         MCP Streamable HTTP

Build / Exec come from <home>/.afs/daemon.build.json, which the daemon writes on boot; on an older daemon that has no sidecar the two lines are omitted rather than guessed. Version / Commit / Checkout describe the binary that is actually serving the instance — see Identity fields below.

Record a blocklet source with --blocklet (repeatable). Same flag accepts a parent directory or a single blocklet directory:

bash
$ arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b \
    --blocklet /path/to/arc/blocklets/afs-preview-fixture --host 127.0.0.1 --no-advertise
  Instance: docs514b
  ID:       b719db414c5cc625
  Status:   up
  PID:      95666
  Port:     61498
  URL:      http://127.0.0.1:61498
  Home:     /tmp/arc-svc-docs-514/home-b
  Space:    /tmp/arc-svc-docs-514/home-b/.afs/spaces
  Sources:  /path/to/arc/blocklets/afs-preview-fixture
  Version:  2.0.0-beta.48
  Commit:   5a5316bde
  Checkout: /tmp/arc-svc-docs-514/project
  Host:     127.0.0.1
  Started:  2026-09-10T01:49:56.435Z (up 7s)

stderr for that run added an Extra blocklet dirs: line before the banner-omitted AFS Service started, and a Blocklet: block after Endpoints::

Starting AFS service...
  Extra blocklet dirs: /path/to/arc/blocklets/afs-preview-fixture
AFS Service started
  Log:  /tmp/arc-svc-docs-514/home-b/.afs/daemon.log
  Build: 2.0.0-beta.48+5a5316bde (debug)
  Exec:  /path/to/arc/runtimes/node/dist/cli.mjs

  Endpoints:
    http://127.0.0.1:61498/            AUP Web Client
    http://127.0.0.1:61498/explorer    Explorer UI
    http://127.0.0.1:61498/ws          WebSocket (Explorer)
    http://127.0.0.1:61498/afs/*       REST API
    http://127.0.0.1:61498/mcp         MCP Streamable HTTP

  Blocklet: afs-preview-fixture
    http://afs-preview-fixture.localhost:61498/
    http://localhost:61498/?blocklet=afs-preview-fixture    (Safari / universal)
bash
$ arc service list
NAME          ID                PORT   STATUS   HOME                          SOURCES
docs514a      b719db414c5cc624  61497  up       /tmp/arc-svc-docs-514/home-a  0
docs514b      b719db414c5cc625  61498  up       /tmp/arc-svc-docs-514/home-b  1

status reports everything start reported, for an instance you did not just start — same stdout/stderr split:

bash
$ arc service status --instance docs514b
  Instance: docs514b
  ID:       b719db414c5cc625
  Status:   up
  PID:      95666
  Port:     61498
  URL:      http://127.0.0.1:61498
  Home:     /tmp/arc-svc-docs-514/home-b
  Space:    /tmp/arc-svc-docs-514/home-b/.afs/spaces
  Sources:  /path/to/arc/blocklets/afs-preview-fixture
  Version:  2.0.0-beta.48
  Commit:   5a5316bde
  Checkout: /tmp/arc-svc-docs-514/project
  Host:     127.0.0.1
  Started:  2026-09-10T01:49:56.435Z (up 3m)

Log path, build id, endpoints, blocklet URLs and (on a non-loopback bind) the LAN diagnostic go to stderr; the record goes to stdout. start and status print the same URL for the same instance — both use the registry's http://127.0.0.1:<port> form. --json suppresses the stderr blocks and carries all of it as data instead.

On a machine whose project root exposes many blocklets, status expands only the routes you named with --blocklet and counts the rest — this is a real capture against a full dev checkout, not a contrived number:

  Blocklets: 51 route(s) served — 50 not expanded; `arc service url` or --json lists them all

--json always carries every route in urls.blocklets.

bash
$ arc service url --instance docs514b
http://127.0.0.1:61498/

stderr (banner omitted), same printer as start:

  Blocklet: afs-preview-fixture
    http://afs-preview-fixture.localhost:61498/
    http://localhost:61498/?blocklet=afs-preview-fixture    (Safari / universal)
bash
$ arc service url --instance docs514b --print url
http://127.0.0.1:61498

--print url writes only the instance URL to stdout (no trailing slash in this capture), exit 0. $(arc service url --instance NAME) stays that one line. Agents that need a blocklet address use --json and the Host URL (http://afs-preview-fixture.localhost:…). ?blocklet= is the Safari fallback; it does not mount /blocklets/<name> for RPC.

Identity fields

Version / Commit / Branch / Sha / Checkout describe the binary serving this instance, not the arc you typed. The daemon computes them at boot and writes them into its registry row, so a status from any shell reports the same values as curl http://127.0.0.1:<port>/.well-known/arc/instance.

For an up instance, status asks the daemon directly and reports the answer under live:

json
"live": {
  "ok": true,
  "url": "http://127.0.0.1:61498/.well-known/arc/instance",
  "record": { "version": "2.0.0-beta.48", "commit": "5a5316bde", "pid": 95666, "port": 61498, "blocklets": 1 }
}

If the registry row and the daemon disagree — which is what arc upgrade does, swapping the binary under a running process — both values are reported and the differing fields are listed under drift:

json
"drift": [{ "field": "version", "registry": "2.0.0-beta.48", "live": "2.0.0-beta.49" }]

The probe is best effort. If the process is alive but nothing answers on loopback in time — captured here from a SIGSTOPped daemon, which is why the exact wording is a timeout rather than a refused connection — status falls back to the registry view and says so; the exit code is unchanged:

  Live:     unreachable (The operation was aborted due to timeout) — registry values only

(A daemon that is fully gone rather than merely unresponsive reports dead instead — see States — and is not probed at all.)

Restart, logs, stop, delete, gc

restart reuses the record. It does not take a new --port:

bash
$ arc service restart --instance docs514b
  Instance: docs514b
  ID:       b719db414c5cc625
  Status:   up
  PID:      95700
  Port:     61498
  URL:      http://127.0.0.1:61498
  Home:     /tmp/arc-svc-docs-514/home-b
  Space:    /tmp/arc-svc-docs-514/home-b/.afs/spaces
  Sources:  /path/to/arc/blocklets/afs-preview-fixture
  Version:  2.0.0-beta.48
  Commit:   5a5316bde
  Checkout: /tmp/arc-svc-docs-514/project
  Host:     127.0.0.1
  Started:  2026-09-10T01:58:00.472Z (up 3s)

stderr says AFS Service restarted (not started), otherwise the same shape as start's stderr above.

bash
$ arc service logs --instance docs514b
{"ts":"2026-09-10T01:58:01.683Z","level":"info","service":"arc-node","ns":"node:boot","message":"boot vault-ready +652ms"}
{"ts":"2026-09-10T01:58:01.686Z","level":"info","service":"arc-node","ns":"node:boot","message":"boot did-space-ready +656ms"}
{"ts":"2026-09-10T01:58:02.235Z","level":"info","service":"arc-node","ns":"node:boot","message":"[code-agents] recover ok: claimed=0 marked=0 orphaned=0 deferred=0 locksScanned=0 locksReclaimed=0"}

Later boot lines omitted. --follow reprints existing lines then streams.

bash
$ arc service stop --instance docs514b
Service stopped: docs514b

A stopped instance still reports its last pid / port / URL, and says in words that those are historical (exit 3):

bash
$ arc service status --instance docs514b
  Instance: docs514b
  ID:       b719db414c5cc625
  Status:   stopped
  PID:      95700
  Port:     61498
  URL:      http://127.0.0.1:61498
  Home:     /tmp/arc-svc-docs-514/home-b
  Space:    /tmp/arc-svc-docs-514/home-b/.afs/spaces
  Sources:  /path/to/arc/blocklets/afs-preview-fixture
  Version:  2.0.0-beta.48
  Commit:   5a5316bde
  Checkout: /tmp/arc-svc-docs-514/project
  Host:     127.0.0.1
  Started:  2026-09-10T01:58:00.472Z
  Note:     PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process.

In --json the same fact is "lastKnown": true, and there is no live key — a stopped instance is not probed. list prints <port>* for PORT (see States). start on the same name reuses the record.

Each code block on this page is its own capture; instance names repeat across sections (docs514a, docs514b) without implying one continuous session — the four delete examples below use fresh throwaway names for exactly that reason, so none of them is a delete on a name a previous example already removed.

delete now has two output shapes for success, split by view the same way arc afs delete is (ArcBlock/arc#6055): the default (machine, non-TTY) view is a bare OK <name> — write's shape — and --view human is a sentence naming what was removed. Both instances below were stopped before the delete:

bash
$ arc service delete --instance docs514x
OK docs514x

$ arc service delete --instance docs514y --view human
Removed instance "docs514y"

delete of a running instance fails without --force — this is also where the ArcBlock/arc#6301 prefix fix actually shows up: every failure line on this page now starts ERROR: where the old capture had no prefix at all:

bash
$ arc service delete --instance docs514z
ERROR: instance "docs514z" is running. stop it first, or use --force

--force stops first, then deletes — the accept-path counterpart to the reject above, same instance, same verb:

bash
$ arc service delete --instance docs514z --force --yes
OK docs514z

--dry-run previews without touching anything, and works on either a stopped or a running instance:

bash
$ arc service delete --instance docs514w --dry-run
Would delete instance docs514w at /tmp/arc-svc-docs-514/home-w (dry-run)

$ arc service delete --instance docs514w --dry-run --json
{
  "name": "docs514w",
  "removed": false,
  "home": "/tmp/arc-svc-docs-514/home-w",
  "dryRun": true,
  "homeRemoved": true
}

homeRemoved here means "the home directory would be removed by a real run", not that anything was removed — removed: false / dryRun: true on the same object say that already; read the three fields together, not homeRemoved alone.

--yes skips the interactive TTY confirmation prompt. In practice this rarely matters outside a real terminal: confirmation is TTY-only by design (interactive requires stdin and stdout to be a real TTY), so an agent, a pipe, or a test — anything already used to produce this page's dumps — proceeds without ever seeing the prompt, --yes or not. Pass it anyway for a script that might one day run from a terminal.

gc only collects dead (process gone without stop). stopped is kept:

bash
$ arc service gc
Collected 1 dead instance
  docs514dead
kept 1

$ arc service gc
No dead instances to collect

After that list still showed the stopped and up rows; docs514dead was gone. With nothing dead left, gc says so in one line and still exits 0. A separate, freshly-emptied registry (zero instances registered at all, not the one above) makes the point that kept is a real count down to 0, not an empty answer — the same "renders to zero characters, not falsy" rule the --print section covers next:

bash
$ arc service gc --json
{
  "removed": [],
  "kept": 0
}

--print

--print <field> reads one field out of the command's normal result and writes it to stdout as plain text, bypassing --json/--view entirely. ArcBlock/arc#6301 changed the rule for when a field counts as "no value": it used to be falsy (false, 0, "" were all treated as absent, printing nothing while still exiting 0 — indistinguishable from a real empty answer); it is now renders to zero characters. false and 0 are two-and-one characters respectively, so they are real answers and stay exit 0. Object.hasOwn is used to find the field, not in (which would walk the prototype chain and answer {} for --print __proto__).

Accept path — a field whose real value is the boolean false still prints and exits 0 (this instance was started with --no-advertise):

bash
$ arc service status --instance docs514b --print advertise
false

Accept path — a field whose real value is the number 0 still prints and exits 0 (an empty registry, so gc's kept count is genuinely zero):

bash
$ arc service gc --print kept
0

(The same rule covers a 0 port; that specific case cannot be produced from a live bind — the OS never actually hands back port 0 — so the CLI's own positive-control unit test drives it directly against a synthetic { port: 0 } object: runtimes/node/test/daemon/service-print-contract.test.ts:135.)

Reject path — a field that exists but carries no value (branch / sha / commit on a checkout with no .git) is refused, not silently printed empty:

bash
$ arc service status --instance docs514b --print branch
$ echo $?
1

stderr (banner omitted): ERROR: field "branch" in result has no value

Reject path — a field that does not exist in the result at all gets a different message, same exit code:

bash
$ arc service status --instance docs514b --print nosuchfield
$ echo $?
1

stderr: ERROR: no field "nosuchfield" in result

--print "" used to be folded into "no --print given" and fall through to the full default view — so arc service status --print "$FIELD" with an unset $FIELD printed the entire human view instead of failing. It no longer does; an empty field name is looked up like any other, does not exist, and is refused the same way nosuchfield above is:

bash
$ arc service status --instance docs514b --print ""
$ echo $?
1

stderr: ERROR: no field "" in result

--json contract

JSON is stdout only on success. On reject, stdout is always empty (0 bytes) — every failure, not just some. This corrects an earlier version of this page that claimed the reject path put { "error": "…" } on stdout; that was never true for arc service, and ArcBlock/arc#6301's fix note confirms the post-fix contract is explicitly "0 bytes of stdout" on every one of its nine reject scenes. The error message goes to stderr, ERROR: -prefixed, and the process exits non-zero.

Two different kinds of reject both land on this same 0-byte-stdout shape — worth checking side by side because they come from different code paths:

bash
$ arc service status --instance no-such-xyz --json
$ echo $?
1

stderr: ERROR: no instance named "no-such-xyz". `arc service list` shows 2 — this one never reaches the action's executor at all; instance resolution fails first.

bash
$ arc service delete --instance docs514b --json
$ echo $?
1

stderr: ERROR: instance "docs514b" is running. stop it first, or use --force — this one runs inside delete's own executor, which decides to fail after resolving the instance successfully.

Same shape either way: empty stdout, ERROR: -prefixed stderr, non-zero exit. --json does not change any of that — it only changes what a successful run would have printed.

On success, the JSON is a superset of the human view. Every URL, hostname and path the terminal prints is somewhere in the payload — logFile, endpoints, blockletUrls, lan, build — so an agent never has to scrape stderr.

bash
$ arc service status --instance docs514b --json
{
  "name": "docs514b",
  "id": "b719db414c5cc625",
  "status": "up",
  "port": 61498,
  "url": "http://127.0.0.1:61498",
  "home": "/tmp/arc-svc-docs-514/home-b",
  "spaceRoot": "/tmp/arc-svc-docs-514/home-b/.afs/spaces",
  "blocklets": [
    "/path/to/arc/blocklets/afs-preview-fixture"
  ],
  "pid": 95666,
  "version": "2.0.0-beta.48",
  "commit": "5a5316bde",
  "branch": null,
  "sha": null,
  "checkout": "/tmp/arc-svc-docs-514/project",
  "startedAt": "2026-09-10T01:49:56.435Z",
  "urls": {
    "ui": "http://127.0.0.1:61498/",
    "blocklets": {
      "afs-preview-fixture": "http://127.0.0.1:61498/?blocklet=afs-preview-fixture"
    }
  },
  "host": "127.0.0.1",
  "advertise": false,
  "uptime": "3s",
  "logFile": "/tmp/arc-svc-docs-514/home-b/.afs/daemon.log",
  "endpoints": [
    { "url": "http://127.0.0.1:61498/", "label": "AUP Web Client" },
    { "url": "http://127.0.0.1:61498/explorer", "label": "Explorer UI" },
    { "url": "http://127.0.0.1:61498/ws", "label": "WebSocket (Explorer)" },
    { "url": "http://127.0.0.1:61498/afs/*", "label": "REST API" },
    { "url": "http://127.0.0.1:61498/mcp", "label": "MCP Streamable HTTP" }
  ],
  "blockletUrls": {
    "afs-preview-fixture": [
      { "url": "http://afs-preview-fixture.localhost:61498/", "label": "" },
      { "url": "http://localhost:61498/?blocklet=afs-preview-fixture", "label": "(Safari / universal)" }
    ]
  },
  "build": {
    "id": "2.0.0-beta.48+5a5316bde (debug)",
    "exec": "/path/to/arc/runtimes/node/dist/cli.mjs"
  },
  "live": {
    "ok": true,
    "url": "http://127.0.0.1:61498/.well-known/arc/instance",
    "record": {
      "version": "2.0.0-beta.48",
      "commit": "5a5316bde",
      "branch": null,
      "sha": null,
      "checkout": "/tmp/arc-svc-docs-514/project",
      "pid": 95666,
      "port": 61498,
      "blocklets": 1
    }
  }
}

Field groups: the first ten keys are the instance record; versionurls come from the registry row; logFilebuild are what the human view printed; live / drift are the reconciliation against the running daemon. lan appears instead of nothing when the instance is bound to a non-loopback address, and carries the whole LAN diagnostic as lines.

list reports the record keys for every instance and omits the printed-facts keys — it prints no banner per row and does not probe. Note sha is populated here (a real git checkout) where the single-instance example above had null (a checkout with no .git) — both are real, from two different runs:

bash
$ arc service list --json
{
  "instances": [
    {
      "name": "docs514a",
      "id": "b719db414c5cc624",
      "status": "up",
      "port": 61497,
      "url": "http://127.0.0.1:61497",
      "home": "/tmp/arc-svc-docs-514/home-a",
      "spaceRoot": "/tmp/arc-svc-docs-514/home-a/.afs/spaces",
      "blocklets": [],
      "pid": 95665,
      "version": "2.0.0-beta.48",
      "commit": "5a5316bde",
      "branch": null,
      "sha": "5a5316bdece751ee90416382b3ad851e565afa22",
      "checkout": "/tmp/arc-svc-docs-514/project",
      "startedAt": "2026-09-10T01:49:44.207Z",
      "urls": { "ui": "http://127.0.0.1:61497/", "blocklets": {} },
      "host": "localhost",
      "advertise": true,
      "uptime": "5s"
    }
  ]
}

version on every list row is the binary each instance is actually running — a quick way to see which instances an upgrade did not reach.

bash
$ arc service stop --instance docs514b --json
{
  "name": "docs514b",
  "id": "b719db414c5cc625",
  "stopped": true,
  "pid": 95700
}

$ arc service delete --instance docs514b --json
{
  "name": "docs514b",
  "removed": true,
  "home": "/tmp/arc-svc-docs-514/home-b"
}

--view json is the same channel as --json.

logs is a stream and refuses --json — same 0-byte-stdout / stderr shape as every other reject:

bash
$ arc service logs --instance docs514a --json
$ echo $?
1

stderr: ERROR: logs is a stream and does not support --json

yargs-level errors (unknown verb, missing required argument) also print no JSON even with --json — they never reach the point where --json would matter, and they print the subcommand's help on stderr instead (see Failures).

Failures

Starting an instance that is already up (exit 1). The hint now names the --home you started it with, not just the bare verb, because restart needs it too when --home was passed at start time:

bash
$ arc service start --instance docs514b --home /tmp/arc-svc-docs-514/home-b
ERROR: instance "docs514b" is already running
       pid 95666, port 61498, started 39s ago
       use `arc service restart --instance docs514b --home /tmp/arc-svc-docs-514/home-b` or pick another name

restart --port (and the other config-only flags — see Flags for which ones and why --home is different) (exit 1):

bash
$ arc service restart --instance docs514b --port 4910
ERROR: restart does not reconfigure. use `stop` then `start` to change --port

--space-root must already be a DID Space:

bash
$ arc service start --instance docs514c --home /tmp/arc-svc-docs-514/home-c \
    --space-root /tmp/arc-svc-docs-514/not-a-space
ERROR: /tmp/arc-svc-docs-514/not-a-space is not a DID Space. create it with `arc space init`

Unknown verb (exit 5). yargs treats it as "not enough / wrong positional", prints the group's --help (shown in full under --help) on stderr, and both together are prefixed once:

bash
$ arc service foo
ERROR: Invalid values:
  Argument: action, Given: "foo", Choices: list, start, stop, restart, status, delete, gc, url, logs

arc service

Manage AFS background service

Commands:
  arc service list     List every local instance with its status, port and home
                       [aliases: ls, ps]
  ...

arc service with no verb at all is the same mechanism, different reason (exit 5):

bash
$ arc service
ERROR: Not enough non-option arguments: got 0, need at least 1

arc service
...

A leftover positional instance name (the verb, then a bare name, no --instance) is rejected on every verb, including list / gc — same mechanism again, this time printing the subcommand's own --help (exit 5):

bash
$ arc service status somename
ERROR: positional instance name was removed; use `--instance <name>` / `-i`

arc service status

Report whether an instance is running, and on which port
...

Removed and retired

These used to be documented. They are gone:

OldNow
arc service <action> [op] [dir] [options]arc service <verb> [options]
arc service <action> [name]arc service <verb> --instance <name> / -i
--blocklet-dir--blocklet (parent or single dir)
--saveRecorded automatically on the instance
ARC_BLOCKLET_DIRGone. Pass --blocklet
arc service blocklet-dir add/listGone
arc service restart --port 4900restart refuses config flags
ARC_HOMERetired. Warns and ignores

Genuinely-removed flags no longer get a bespoke error — they now hit yargs' own unknown-argument handler, which offers a "Did you mean?" suggestion and dumps the subcommand's --help:

bash
$ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a --blocklet-dir /tmp/nope
ERROR: Unknown arguments: blocklet-dir, blockletDir

Did you mean?
  --blocklet

arc service start
...

$ arc service start --instance docs514a --home /tmp/arc-svc-docs-514/home-a --save
ERROR: Unknown argument: save

arc service start
...

ARC_HOME is unaffected by the subcommand split — the warning still fires, still on its own line before the banner, and is not ERROR: -prefixed (it is a warning, not a fail(), so ArcBlock/arc#6301's unification does not touch it):

bash
$ ARC_HOME=/tmp/retired-home arc service list
warning: ARC_HOME is ignored; instance root comes from the service name and --home, not env

--help

The group-level --help — this is what an unknown verb also dumps (see Failures):

text
arc service

Manage AFS background service

Commands:
  arc service list     List every local instance with its status, port and home
                       [aliases: ls, ps]
  arc service start    Start an instance, creating it on first use
  arc service stop     Stop a running instance, keeping its record and data
  arc service restart  Restart an instance from its recorded config (does not
                       reconfigure — stop then start for that)
  arc service status   Report whether an instance is running, and on which port
  arc service delete   Delete an instance: its record and its data [aliases: rm,
                       remove]
  arc service gc       Drop registry records whose process is gone [aliases:
                       prune]
  arc service url      Print an instance's base URL (and its blocklets')
  arc service logs     Print an instance's daemon log  [aliases: log]

Options:
      --json      Output in JSON format  [boolean]
      --view      Output view format (json is equivalent to --json). llm is
                  accepted globally; commands without an llm renderer fail
                  closed (declare ⇒ execute; arc#6037). [string] [choices:
                  "default", "llm", "human", "json"] [default: "default"]
      --home      Instance root — to pick which instance, use --instance. Used
                  by `arc service start` (create) and `arc did init` (identity).
                  In `--standalone`, sets DID Space and configDir; mounts come
                  from a cwd-walk of `.afs-config/config.toml`, not from --home.
                  [string]
  -i, --instance  Named local ARC instance this command operates against (see
                  `arc service list`). Omit for the default instance. [string]
      --print     Print one result field (e.g. url, port) as plain text — not a
                  view; overrides --json/--view [string]
  -h, --help      Show help  [boolean]
  -v, --version   Show version number  [boolean]

Examples:
  arc service list
      Show every local instance
  arc service start -i alice
      Start (or create) named instance alice
  arc service status -i alice
      Is alice running, and on which port?
  arc service logs -i alice
      Print alice's recent daemon logs
  arc service stop -i alice
      Stop alice without deleting it
  arc service delete -i alice --dry-run
      Preview deleting instance alice without removing it

Two of the nine subcommands' own --helpstart (the widest flag set) and delete (the one with a destructive-verb flag trio) — to show the shape the other seven follow:

text
arc service start

Start an instance, creating it on first use

Options:
      --json        Output in JSON format  [boolean]
      --view        Output view format (json is equivalent to --json). llm is
                    accepted globally; commands without an llm renderer fail
                    closed (declare ⇒ execute; arc#6037). [string] [choices:
                    "default", "llm", "human", "json"] [default: "default"]
      --home        Instance root — to pick which instance, use --instance. Used
                    by `arc service start` (create) and `arc did init`
                    (identity). In `--standalone`, sets DID Space and configDir;
                    mounts come from a cwd-walk of `.afs-config/config.toml`,
                    not from --home. [string]
  -i, --instance    Named local ARC instance this command operates against (see
                    `arc service list`). Omit for the default instance. [string]
      --print       Print one result field (e.g. url, port) as plain text — not
                    a view; overrides --json/--view [string]
      --port        Port to listen on (0-65535). 0 = auto-assign. Omit: default
                    uses 4900; named instances use the recorded port or
                    auto-assign [number]
      --host        Bind address (localhost, 0.0.0.0, ::, or a unicast IP)
                    [string] [default: "localhost"]
      --advertise   Advertise this instance over mDNS when bind is non-loopback
                    (use --no-advertise to disable) [boolean] [default: true]
      --blocklet    Blocklet-parent or single-blocklet dir to serve
                    (repeatable). Recorded on the instance. [array]
      --space-root  Folder-as-DID-Space created with `arc space init` (omit to
                    derive from home) [string]
  -h, --help        Show help  [boolean]
  -v, --version     Show version number  [boolean]

Examples:
  arc service start -i alice
      Start (or create) named instance alice

arc service delete

Delete an instance: its record and its data

Options:
      --json      Output in JSON format  [boolean]
      --view      Output view format (json is equivalent to --json). llm is
                  accepted globally; commands without an llm renderer fail
                  closed (declare ⇒ execute; arc#6037). [string] [choices:
                  "default", "llm", "human", "json"] [default: "default"]
      --home      Instance root — to pick which instance, use --instance. Used
                  by `arc service start` (create) and `arc did init` (identity).
                  In `--standalone`, sets DID Space and configDir; mounts come
                  from a cwd-walk of `.afs-config/config.toml`, not from --home.
                  [string]
  -i, --instance  Named local ARC instance this command operates against (see
                  `arc service list`). Omit for the default instance. [string]
      --print     Print one result field (e.g. url, port) as plain text — not a
                  view; overrides --json/--view [string]
      --force     Stop a running instance before deleting it [boolean] [default:
                  false]
      --dry-run   Print what would be removed without deleting it [boolean]
                  [default: false]
      --yes       Skip the TTY confirmation prompt  [boolean] [default: false]
  -h, --help      Show help  [boolean]
  -v, --version   Show version number  [boolean]

Examples:
  arc service delete -i alice --dry-run
      Preview deleting instance alice without removing it

The remaining seven (stop, restart, status, gc, url, logs plus the group's own list) follow the same shape as start/delete above minus the flags this page's Flags table already scopes to start/delete/logslogs adds only --follow.

--json, --view, --home, and --instance / -i are global (declared once, apply to every arc command). --home is the instance root; to pick which instance, use --instance. See Overview.