跳到主要內容

arc service

arc service 管理具名 AFS 後臺例項:list、start、stop、restart、status、delete、gc、url、logs。

arc service 管理具名 AFS 後臺例項。arc afs、MCP 橋接、以及 blocklet 服務,都依賴一個正在執行的例項。

對照版本:arc 2.0.0-beta.48,commit 5a5316bde(main,2026-09-10)——不是釋出出去的那個同版本號二進位制;同一個 2.0.0-beta.48 曾同時對應兩份不同的構建,所以本頁釘的是 commit,不是 semver。arc service 現在是九個真子命令(arc service <verb> [options]),每個都有自己的 --help 和 Examples: 塊——不再是一條命令帶一個positional action choice 列表。--json 拒絕路徑在 ArcBlock/arc#5205 之後重測過(error 物件在 stdout——下面 --json 契約 再次糾正這一點);delete 在 ArcBlock/arc#5279 之後成為主動詞名(rm/remove 現在是 alias);子命令化和每條失敗行統一的 ERROR: 字首都來自 ArcBlock/arc#6301。例項名 positional 在 ArcBlock/arc#5713 退役:指定例項的唯一寫法是 --instance / -i。複製 dump 前先跑 arc --version;動詞和 flag 仍可能變。下面的 --help 是英文(LC_ALL=C)——ArcBlock/arc#5244 之後,幫助/報錯文本永遠是英文,不隨你系統的 locale 變化。

下面的例項名、home 路徑和連接埠都簡化成易讀的 docs514a / /tmp/arc-svc-docs-514/... 形式;報錯文本、欄位名、退出碼和 JSON 結構都是真實跑出來的原樣。

bash
arc service <verb> [options]

verb 是下面之一:list(ls、ps)、start、stop、restart、status、delete(rm、remove)、gc(prune)、url、logs(log)。用 --instance <name> / -i 指定例項。省略 --instance 即種子例項 default(home ~,連接埠 4900)。其它名字由核心分配連接埠,除非你傳 --port。

不要 stop / delete 你沒啟動的種子例項。本頁 dump 用的是一次性 registry,沒有碰本機 :4900 上的 default。

隔離

隔離靠具名例項加 --home。ARC_HOME 已退役:CLI 會警告並忽略取值。

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 仍在,但只作用於未具名的種子例項。優先用名字,或傳 --port。

下面 dump 省略了 stderr 上的 splash banner。

子命令

每個子命令都有自己的 --help 和自己的 Examples:(見本頁底部的 --help 一節)。arc service <壞動詞> 和不帶動詞的 arc service 都列印下面這張組級列表,不是某個動詞自己的。

子命令Alias作用
listls、ps列出每個本地例項的狀態、連接埠和 home
start啟動一個例項;首次用即建立
stop停下正在跑的例項,保留記錄和資料
restart按記錄重啟例項——不接受重新配置;要改配置用 stop 再 start
status報告一個例項是否在跑,以及跑在哪個連接埠
deleterm、remove刪除一個例項:它的記錄和資料
gcprune清掉處理程序已經不在了的註冊記錄
url列印例項的 base URL(以及它的 blocklet URL)
logslog列印例項的 daemon 日誌

Flags

每個子命令都接受共享的全域 flag——--json、--view、--home、--instance / -i、--print——外加它自己的額外 flag:

Flag子命令含義
-i、--instance全部這條命令作用在哪個本地 ARC 例項。省略即 default。指定例項的唯一寫法
--home全部例項根。用於 start(建立)、arc did init。在 restart 上它是拿來跟記錄裡的 home 做一致性核對的,不是新配置——一致就是 no-op,指向別的路徑會被拒絕(見 失敗路徑)
--print全部把結果裡的單個欄位(例如 url、port)以純文本列印——不是一種 view,會覆蓋 --json/--view。見下面的 --print
--portstart監聽連接埠(0–65535)。0 = 自動分配。省略時:default 用 4900,具名例項用記錄裡的連接埠或自動分配
--hoststart繫結地址(localhost、0.0.0.0、:: 或單播 IP)。預設 localhost
--advertisestart繫結非 loopback 時通過 mDNS 宣告(預設 true;--no-advertise 關閉)
--blockletstart要服務的 blocklet 父目錄或單個 blocklet 目錄(可重複)。記在例項上
--space-rootstart用 arc space init 建好的 Folder-as-DID-Space。省略則從 --home 派生
--forcedelete先停再刪。預設 false
--dry-rundelete列印會刪掉什麼,不實際刪除。預設 false
--yesdelete跳過 TTY 確認提示。預設 false
--followlogs流式輸出新寫入的行。預設 false

--yaml 已刪除,從未真正實現——見 總覽。

restart 自己的 --help 裡沒有 start 那組配置 flag——傳了會被一條專門的報錯拒絕,不是 yargs 通用的「unknown argument」(那條通用路徑是真正被刪除的 flag,比如 --blocklet-dir,才會撞上的;見已刪除與已退役):

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

--home 是唯一的例外:它是全域 flag,所以 restart --home <和記錄一致的路徑> 會靜默成功(no-op),只有指向不同路徑才會被拒絕——報錯和退出碼都跟上面的配置 flag 守衛不一樣:

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")

(退出碼 5,而 --port/--host/--advertise/--space-root/--blocklet 是 1。)

狀態

狀態含義
starting記錄已佔用,處理程序還沒到 up
up處理程序在聽連接埠
stopped經 stop 退出。start / restart 會複用這條記錄
dead處理程序沒經過乾淨 stop 就沒了。gc 只清這種

list 對每個非 up 的行都顯示記錄裡的連接埠,並加 * 字尾標註這是最後已知值而非即時值(stopped/dead 都會加);只有完全沒有記錄過連接埠時(一個從沒到過 up 的例項)才顯示 -:

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

status 的退出碼:up 是 0,starting / stopped 是 3,dead 是 4。非 up 時它照樣報上一次的 pid / port / URL,並明確標註(--json 裡是 lastKnown,人類視圖裡是一行 Note:)。

Start、list、status、url

空 registry:

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

啟動一個具名例項。連接埠 61497 是核心分配的,不是 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)

進度、日誌路徑、build id、endpoints 走 stderr。例項記錄走 stdout——這次捕獲的 stderr(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 來自 daemon 啟動時寫的 <home>/.afs/daemon.build.json;老 daemon 沒有這個 sidecar 時這兩行直接不打,不猜。Version / Commit / Checkout 描述的是真正在服務這個例項的那個 binary——見下面的身份欄位。

用 --blocklet 記錄 blocklet 源(可重複)。同一個 flag 既接受父目錄,也接受單個 blocklet 目錄:

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 在被省略的 banner 和 AFS Service started 之間多了一行 Extra blocklet dirs:,Endpoints: 之後多了一個 Blocklet: 塊:

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 報得出 start 報過的每一件事——對一個不是你剛起的例項也一樣,stdout/stderr 的分法也一樣:

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)

日誌路徑、build id、endpoints、blocklet URL,以及(非 loopback 繫結時的)LAN 診斷走 stderr;記錄走 stdout。start 和 status 對同一個例項報同一個 URL——兩邊都用登錄檔裡的 http://127.0.0.1:<port> 形式。加 --json 時 stderr 的這些塊不打,全部作為資料出現在 payload 裡。

如果這臺機器的 project root 裡有很多 blocklet,status 只展開你用 --blocklet 點名的那些,其餘只報個數——這是對著一個完整的 dev checkout 跑出來的真實數字,不是編的:

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

--json 裡的 urls.blocklets 永遠是全的。

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

stderr(banner 已省略),和 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 只把例項 URL 寫到 stdout(這次捕獲沒有尾斜槓),退出碼 0。$(arc service url --instance NAME) 仍是這一行。Agent 要 blocklet 地址用 --json 裡的 Host URL(http://afs-preview-fixture.localhost:…)。?blocklet= 是 Safari 兜底,掛不上 /blocklets/<name> 的 RPC。

身份欄位

Version / Commit / Branch / Sha / Checkout 描述的是服務這個例項的那個 binary,不是你敲的那個 arc。daemon 在啟動時算好並寫進自己的登錄檔行,所以在任何 shell 裡 status 出來的值,和 curl http://127.0.0.1:<port>/.well-known/arc/instance 一致。

對 up 的例項,status 會直接問 daemon,答案放在 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 }
}

登錄檔行和 daemon 不一致時——arc upgrade 就是這種情況,它在處理程序不重啟的前提下換掉 binary——兩個值都報,不一致的欄位列在 drift 裡:

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

這個探針是盡力而為。如果處理程序還活著但 loopback 上一時沒人應答——這條是從一個被 SIGSTOP 暫停的 daemon 上抓到的,所以措辭是超時而不是拒絕連線——status 會退回純登錄檔檢視並說明原因,退出碼不變:

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

(處理程序徹底沒了而不只是暫時無應答時報的是 dead——見狀態——這種情況根本不做探針。)

Restart、logs、stop、delete、gc

restart 複用記錄,不接受新的 --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 打的是 AFS Service restarted(不是 started),其它跟上面 start 的 stderr 一樣。

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"}

後面的 boot 行省略。--follow 會先重打已有行再流式輸出。

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

stopped 的例項照樣報上一次的 pid / port / URL,並且明說這些是歷史值(退出碼 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.

--json 裡同一件事是 "lastKnown": true,並且沒有 live 鍵——stopped 例項不做探針。list 對 PORT 打 <port>*(見狀態)。同名再 start 會複用記錄。

本頁每個程式碼塊都是獨立的一次捕獲;例項名在不同小節裡重複出現(docs514a、docs514b)並不意味著一條連續的工作階段——下面 delete 的四個例子都用全新的一次性名字,正因為這樣,它們誰都不是在刪一個前面例子已經刪掉的名字。

delete 現在對成功有兩種輸出形態,按 view 分——跟 arc afs delete 一樣的分法(ArcBlock/arc#6055):預設(機器、非 TTY)檢視是一句光禿禿的 OK <name>——write 的形狀——--view human 是一句說清楚刪了什麼的話。下面兩個例項在刪除前都是 stopped:

bash
$ arc service delete --instance docs514x
OK docs514x

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

正在跑的例項,delete 不帶 --force 會失敗——這也是 ArcBlock/arc#6301 字首修復真正體現出來的地方:本頁每一條失敗行現在都以 ERROR: 開頭,而舊的捕獲完全沒有字首:

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

--force 先停再刪——上面那條拒絕的 accept-path 對應項,同一個例項,同一個動詞:

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

--dry-run 只預覽,不動手,對 stopped 或 running 的例項都能用:

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 這裡的意思是「一次真正的執行會刪掉這個 home 目錄」,不是說已經刪了——同一個物件上的 removed: false / dryRun: true 已經說明了這一點;把這三個欄位放在一起讀,別只看 homeRemoved。

--yes 跳過互動式 TTY 確認。實際上這在真終端之外幾乎不起作用:確認本來就是只在 TTY 裡才問的設計(interactive 要求 stdin 和 stdout 都是真 TTY),所以 agent、管道、測試——包括產出本頁這些 dump 的那些呼叫——都不會看到那個提示,加不加 --yes 都一樣。給一個可能有一天會在終端裡跑的指令碼加上它仍然是對的。

gc 只收集 dead(處理程序沒走 stop 就沒了)。stopped 會留下:

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

$ arc service gc
No dead instances to collect

之後 list 仍有 stopped 和 up 行;docs514dead 沒了。已經沒有 dead 時,gc 用一行說明這件事,退出碼仍然是 0。另一個完全空的 registry(零個已註冊例項,不是上面那個)用來說明 kept 是一個真的數,能數到 0,不是一個空答案——跟下面 --print 那條「渲染出零個字元,不是 falsy」的規則是同一條:

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

--print

--print <field> 從命令的正常結果裡讀一個欄位,以純文本寫到 stdout,完全繞開 --json/--view。ArcBlock/arc#6301 改了「算沒算有值」的判據:以前是falsy(false、0、"" 都被當成不存在,列印為空還照樣退出 0——和一個真的空答案分不出來);現在是渲染出零個字元。false 和 0 分別是五個字元和一個字元,所以是真答案,照樣退出 0。查欄位用的是 Object.hasOwn,不是 in(後者會走原型鏈,讓 --print __proto__ 答出 {})。

Accept path——一個真實值是布林 false 的欄位照樣列印並退出 0(這個例項是用 --no-advertise 起的):

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

Accept path——一個真實值是數字 0 的欄位照樣列印並退出 0(空 registry,所以 gc 的 kept 計數真的是零):

bash
$ arc service gc --print kept
0

(同一條規則也覆蓋 0 的連接埠;那個具體情形沒法從一次真實繫結裡跑出來——OS 從來不會真的把連接埠分配成 0——所以 CLI 自己的正控單測直接對一個合成的 { port: 0 } 物件跑:runtimes/node/test/daemon/service-print-contract.test.ts:135。)

Reject path——一個存在但沒有值的欄位(沒有 .git 的 checkout 上的 branch / sha / commit)會被拒絕,不是悄悄列印成空:

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

stderr(banner 已省略):ERROR: field "branch" in result has no value

Reject path——一個結果里根本不存在的欄位,報錯不一樣,退出碼一樣:

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

stderr:ERROR: no field "nosuchfield" in result

--print "" 以前被當成「沒給 --print」而落回完整的預設檢視——所以 arc service status --print "$FIELD" 在 $FIELD 沒設時會列印整個人類檢視,而不是報錯。現在不會了:空欄位名跟別的欄位名一樣被查,查不到,和上面 nosuchfield 一樣被拒絕:

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

stderr:ERROR: no field "" in result

--json 契約

只有成功時 JSON 才在 stdout。拒絕時 stdout 永遠是空的(0 位元組)——每一條失敗都是,不是「有些是」。 這糾正了本頁早先的一個說法,那時寫著拒絕路徑會把 { "error": "…" } 放到 stdout 上;對 arc service 來說那從來都不是真的,ArcBlock/arc#6301 的修復說明也確認修完之後的契約明確是它九個拒絕場景裡「stdout 0 位元組」。報錯文本走 stderr,帶 ERROR: 字首,處理程序以非零碼退出。

兩種不同的拒絕都落到同一個「stdout 0 位元組」形狀上——值得放在一起看,因為它們走的是不同的程式碼路徑:

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

stderr:ERROR: no instance named "no-such-xyz". `arc service list` shows 2——這條根本沒走到動作自己的 executor,例項解析這一步就先失敗了。

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

stderr:ERROR: instance "docs514b" is running. stop it first, or use --force——這條是在 delete 自己的 executor 裡跑的,executor 在成功解析出例項之後才決定失敗。

兩條路徑同一個形狀:stdout 空,stderr 帶 ERROR: 字首,退出碼非零。--json 對這些都沒有影響——它只改變一次成功的執行本來會列印什麼。

成功時,JSON 是人類檢視的超集。 終端打出來的每一條 URL / 主機名 / 路徑都在 payload 裡——logFile、endpoints、blockletUrls、lan、build——agent 永遠不需要去刮 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
    }
  }
}

欄位分組:前十個鍵是例項記錄;version … urls 來自登錄檔行;logFile … build 是人類檢視打過的那些;live / drift 是對活 daemon 的對帳。例項綁在非 loopback 地址上時會多一個 lan,整塊 LAN 診斷在它的 lines 裡。

list 只報記錄類欄位,不帶「列印過的事實」那幾個——它每行不打 banner,也不做探針。注意這裡 sha 有值(一個真的 git checkout),而上面單例項的例子裡是 null(一個沒有 .git 的 checkout)——兩個都是真的,來自兩次不同的執行:

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"
    }
  ]
}

list 每行的 version 就是那個例項真正在跑的 binary——一眼能看出哪些例項沒被 upgrade 覆蓋到。

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 和 --json 是同一個通道。

logs 是流,拒絕 --json——跟其它拒絕一樣的「stdout 0 位元組 / stderr 報錯」形狀:

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

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

yargs 級錯誤(未知動詞、缺必填引數)同樣即使加了 --json 也不打 JSON——它們根本沒走到 --json 會起作用的地方,而是把子命令的 help 打到 stderr(見失敗路徑)。

失敗路徑

對已經 up 的例項再 start(退出碼 1)。提示語現在會點名你啟動時用的那個 --home,不只是光禿禿的動詞——因為 restart 在 start 時傳了 --home 的情況下也需要它:

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(以及別的純配置 flag——具體哪幾個、為什麼 --home不一樣,見Flags)(退出碼 1):

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

--space-root 必須已經是 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`

未知動詞(退出碼 5)。yargs 把它當成「positional 不夠/不對」處理,把這個組的 --help(下面 --help 一節有全文)打到 stderr,兩者一起只加一次字首:

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 是同一個機制,原因不同(退出碼 5):

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

arc service
...

多出來的 positional 例項名(動詞後面直接跟一個名字,沒有 --instance)在每個動詞上都會被拒絕,包括 list / gc——同一個機制,這次打的是子命令自己的 --help(退出碼 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
...

已刪除與已退役

這些以前寫進文件,現在沒了:

舊寫法現在
arc service <action> [op] [dir] [options]arc service <verb> [options]
arc service <action> [name]arc service <verb> --instance <name> / -i
--blocklet-dir--blocklet(父目錄或單個目錄)
--save自動記在例項上
ARC_BLOCKLET_DIR已刪除。傳 --blocklet
arc service blocklet-dir add/list已刪除
arc service restart --port 4900restart 拒絕配置 flag
ARC_HOME已退役。 警告並忽略

真正被刪除的 flag 不再有專門的報錯——現在會撞上 yargs 自己的「未知引數」處理,它會給一個「Did you mean?」建議,並傾瀉子命令的 --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 不受子命令化影響——警告照樣打,照樣在 banner 之前獨佔一行,而且不帶 ERROR: 字首(它是個 warning,不是 fail(),ArcBlock/arc#6301 的統一沒碰它):

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

組級的 --help——未知動詞打出來的也是這個(見失敗路徑):

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

九個子命令裡挑兩個自己的 --help——start(flag 最多的)和 delete(帶一組三個破壞性動詞專屬 flag 的)——看看其它七個跟的是什麼樣子:

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

其餘七個(stop、restart、status、gc、url、logs,再加組自己的 list)跟上面 start/delete 長得一樣,少的是本頁Flags表裡已經限定給 start/delete/logs 的那些——logs 只多一個 --follow。

--json、--view、--home、--instance / -i 都是全域選項(只宣告一次,作用於每一條 arc 命令)。--home 是例項根;要指定作用在哪個例項,用 --instance。見 總覽。