arc space は、DID Space を支える per-app・per-user のストレージである、ローカルの DID Space データを管理します。ユーザー向けのサブコマンドは 10 個:3 つが読み取り、1 つがデータを移動、1 つが削除、5 つが folder-backed な space を管理します —— さらに 11 番目の内部コマンドがあります。本ページ末尾の sync-bench を参照してください。
arc 2.0.0-beta.48、commit 5a5316bde(main、2026-09-10)に対して取得したものです —— pin しているのは semver ではなく commit です:別のビルドが同じ 2.0.0-beta.48 という文字列を持っていたことがあります。dump をコピーする前に arc --version を実行してください。
arc space <subcommand> [options]グローバルフラグ(概要 を参照):--json、--view、--instance / -i(どのローカル ARC インスタンスか;省略すると default)、および --home(インスタンスのルート;どのインスタンスにするかを選ぶには --instance を使う)。
検査用のサブコマンド(list、tree、path、rm)は、どの DID Space に対して操作するかを選ぶ --scope を受け付け、加えてそのデータがどこにあるかを上書きする --root-path/--user-did も受け付けます。--scope all を受け付けるのは list だけです。tree、path、rm は instance|user を受け付けます。フォルダ系のサブコマンド(init、check、repair、set、migrate、sync)は、ディレクトリを直接指定します —— パスそのものが、それがどの space に属するかを示しています。
各サブコマンドのデフォルト(非 TTY)ビューは、それぞれ独自です —— これは本ページ自体を再取得する際に見つかった、本ページ自身のズレです:list のデフォルトは既に、以下に示す完全な人間可読ブロックそのものです。check と migrate のデフォルトはテキストではなくJSONです。sync のデフォルトは、長い説明ではなく、拒否理由を 1 行に圧縮したサマリーです。--view human は、すべてのサブコマンドを通じて安定して一貫している唯一のビューであり、本ページのこれ以降のすべての例が使っているものです —— サブコマンドごとに異なり本ページの契約でもないデフォルトに頼るのではなく、明示的に渡してください。--json はこれらの影響を受けません —— それは常に完全な構造化ペイロードです。
以下の例では、デモ用の space パスは ~/notes に短縮されています。それ以外はすべて実際の実行結果からそのままコピーしたものです。
保存されているものを確認する
arc space list
app space を、ファイル数と root と一緒に一覧表示します。
使用法
arc space list [options]--scope <instance|user|all>:どの DID Space に対して操作するか(デフォルトall)--root-path <path>:DID Space ストレージの root path、config を上書きする--user-did <did>:user DID、config を上書きする;root path は config のデフォルトにフォールバックする--all:すべてのエントリを表示する(デフォルトは上限 100)
root の下に app space が 1 つもない場合、list は scope ごとに 1 つのブロック(Instance DID Space と User DID Space)を表示し、それぞれが (no app spaces) と表示します —— 「ここには何もない」という単一行の空状態はなく、どの応答も scope ごとの形になっています:
$ arc space list --root-path ~/spaces
Instance DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G
Root: ~/spaces
(no app spaces)
User DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G
Root: ~/spaces
(no app spaces)少なくとも 1 つの app が存在する場合、各ブロックには (no app spaces) の代わりに小さなテーブルが表示されます:
$ arc space list --root-path ~/spaces --view human
Instance DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G
Root: ~/spaces
DID Files Last Modified
─── ───── ─────────────
did:abt:notes-app 0 —
User DID Space z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G
Root: ~/spaces
DID Files Last Modified
─── ───── ─────────────
did:abt:notes-app 0 —list のデフォルト(非 TTY)ビューは既にこの同じ、人間可読で scope ごとのブロックです —— 本ページの中で、--view human を加えても何も変わらない唯一のサブコマンドです。--json は同じ 2 つのグループを groups 配列として持ち、それぞれに role、userDid、rootPath、apps、total を含みます。
arc space tree
1 つの app space のファイルツリーを表示します。
使用法
arc space tree <app-did> [options]--app-did <did>(必須、第 1 positional でもある):検査対象の app DID--scope <instance|user>:どの DID Space か(デフォルトinstance)--path <path>:app fragment 内のパス(デフォルト/)--depth <n>:ツリーの最大深さ(デフォルト99)--limit <n>:最大エントリ数、--allを指定しない場合(デフォルト100)--all:すべてのエントリを表示する、--limitを無視する--root-path <path>/--user-did <did>:listと同じ上書き項目
--app-did は positional で渡さなければなりません —— --app-did が上記のフラグ表や --help の Options: 一覧にも載っているにもかかわらず、positional を伴わない arc space tree --app-did <did> 単体は、引数が足りないとして拒否されます。tree を、space がまったく存在しない app DID に対して実行すると、これは本物の拒否です(exit 5、App space not found: <did>)—— その accept-path 側の対応物が、この下の arc space path です。これはデータが存在するとしたらどこかを計算するだけなので、同じ欠落した DID に対してもエラーになりません。
arc space path
app の DID Space フラグメントに対応する AFS パスを表示します。これを arc afs コマンドに直接渡したいときに便利です。
使用法
arc space path <app-did> [path] [options]--app-did <did>(必須、第 1 positional でもある):検査対象の app DID--scope <instance|user>:どの DID Space か(デフォルトinstance)--path <path>:app fragment 内のパス(デフォルト/)--root-path <path>/--user-did <did>:listと同じ上書き項目
tree とは異なり、path は app space が実際に存在することを要求しません —— それに関わらず計算済みの AFS パスを表示します、exit 0:
$ arc space path did:abt:no-such-app --root-path ~/spaces
/spaces/z1bp5ncJyUiKBv8BVCBH1RVnKks6u9VkW7G/blocklets/no-such-app/systemデータを移動する
arc space sync
2 つのサブツリー間でデータを移動します —— ローカルフォルダ、リモートホスト、あるいはそれぞれ 1 つずつ。--to を --from に向けて収束させます。
これは「データを A から B へ移動する」ための唯一のコマンドで、どちらの方向でも、任意の 2 つの端の間でも使えます。方向と両端は常に引数であり、コマンド名になることはありません —— push の代わりに pull したい場合は、--from と --to を入れ替えてください。
これは space をパスで指定するため、--server、--app-did、--scope がありません:layout=files の space はディスク上に実在するディレクトリを置くため、パスそのものがどの space・どの fragment を指しているかを既に示しています。(--scope は、space を DID で指定する list/tree/path/rm には引き続き適用されます。)グローバルな --instance / -i は、このコマンドがどのローカル ARC インスタンスと話すかを選ぶもので、依然として DID Space の id ではありません。
使用法
arc space sync --from <ref> --to <ref> [options]それぞれの <ref> は、ローカルフォルダか、リモート app の user fragment を表す https://<host>[/<sub>] のいずれかです。この 2 つの形式は scheme だけで区別されるため、タイプミスした URL が黙って相対ディレクトリ名として再解釈されることはありません。
--from <ref>(必須):source--to <ref>(必須):destination--mirror:destination にしかないファイルを削除する(デフォルト:additive、何も削除されない)--dry-run:何も書き込まずに差異を報告する--engine <auto|changelog|cursor|manifest>(デフォルトauto):engine を強制指定する。autoは両端が対応する中で最も強力なものを協議して決める。指名した engine が利用できない場合はエラーになり、静かにダウングレードすることは決してない--verify:sync の後、destination の各ファイルの CID を source と照合して再計算する。--dry-runと組み合わせると、destination が既に一致していることを断言し、一致していなければ非ゼロで終了する--full:記録されている cursor を無視してすべてを再読み込みする —— cursor は使わず、どちらの端のインデックスも読まない。両方のツリーを直接たどる。destination への最初の sync はどちらにせよ full になる。信用できなくなった destination を再構築する場合、または意図的に AFS の外側で書き込まれている claim 済みフォルダを sync する場合に使う(そのインデックスは遅れることが予想され、これを付けないと index-diverged エラーで失敗する —— 下の 3 番目の例の後の注釈を参照)--init:フォルダの destination をlayout=filesとして claim する(source が claim されている場合はデフォルトでこの動作になる)--external-writes <none|possible>(デフォルトpossible):claim された destination に対する query-freshness の宣言。destination が実際に claim されている場合にのみ参照される--token <token>:リモートエンドポイントのアクセストークン、ブラウザ認証の代わり--browser:認証フロー用のブラウザを開く(デフォルトtrue);無人実行では--tokenと一緒に--no-browserを渡す
以下のそれぞれの実行では、stderr に短い進行状況トレース(Scanning source N files, destination M (…ms) / Comparing (…ms) / Syncing X/Y (…ms) / Total: …ms、以下の stdout のダンプでは省略)も表示され、また各側がインデックスのスナップショットから応答したのか、それともスキャンにフォールバックしたのかを示す File list: の行も表示されます —— どちらも本ページの他の箇所には記載されておらず、前回の取得以降に新しく現れたものです。
デフォルトは additive です。最初の sync は、何を移動したかを報告し、協議で決まった engine の名前と、他の engine がなぜ拒否されたかを示します。--view human は各拒否理由の長い形式を表示し、デフォルト(非 TTY)ビューでは代わりに 1 行のサマリーを表示します —— 本ページ全体で --view human を使う理由については、上の 保存されているものを確認する の注釈を参照してください:
$ arc space sync --from src --to dst --view human
src → dst
Base path: /
Mode: additive
Engine: manifest — the manifest engine works between any two endpoints
not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it
not cursor: the cursor engine mirrors (it deletes destination-only paths); this run is additive, so use --mirror to allow deletions or let the manifest engine handle it
File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot)
Added: 2
Modified: 0
Deleted: 0
Unchanged: 0
Transferred: 2 files
Verified: no
Duration: 348msここでの src/dst は、一度も arc space init されたことのない、普通の 2 つのフォルダです —— これが File list: が両方について scan (Operation not supported: paginated snapshot) と表示する理由です:どちら側にもスナップショットを取れるインデックスがないため、manifest engine はツリーを直接たどるフォールバックをします。destination にしか存在しないファイルはそのまま残ります。destination を正確なコピーにしたい場合は --mirror を渡してください —— この 2 回目の実行では、事前に src から b.txt も削除しているため、Deleted: 1 は編み出した数字ではなく、実際の削除を反映しています:
$ arc space sync --from src --to dst --mirror --view human
src → dst
Base path: /
Mode: mirror (deletes destination-only files)
Engine: manifest — the manifest engine works between any two endpoints
not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it
not cursor: source is not a claimed DID Space, so it keeps no changelog ledger to take a cursor from
File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot)
Added: 0
Modified: 0
Deleted: 1
Unchanged: 1
Transferred: 0 files
Verified: no
Duration: 322mssource 自身が claim された layout=files space(arc space init)である場合、同じ拒否理由は違う書かれ方になります —— これは覚えておく価値のある文言です。なぜなら実際の解決策を名指ししているからです:
not cursor: source is layout=files with externalWrites="possible" — the changelog cannot see edits made outside AFS; run `arc space set <from> external-writes=none` (only if the folder really is exclusively AFS-managed) to enable cursor-incremental sync
File list: source snapshot, destination snapshot(実際の取得結果、source/destination とも claim 済み —— File list: は両側とも snapshot と表示し、フォールバックの理由はありません。両方に読み取れるインデックスがあるからです。)
--dry-run は示すだけ、--verify は断言する。両方を一緒に使うと、destination に触れずに確認できます —— 以下の実行では改ざんされたファイルを 1 つ見つけ、1 で終了しました:
$ arc space sync --from src --to dst --dry-run --verify --view human
src ⇢ (dry-run) dst
Base path: /
Mode: additive
Engine: manifest — the manifest engine works between any two endpoints
not changelog: the changelog engine is a device↔cloud engine — it needs exactly one local folder (the device) and one remote host (the cloud); neither folder↔folder nor remote↔remote fits it
not cursor: the cursor engine mirrors (it deletes destination-only paths); this run is additive, so use --mirror to allow deletions or let the manifest engine handle it
File list: source scan (Operation not supported: paginated snapshot), destination scan (Operation not supported: paginated snapshot)
Added: 0
Modified: 1
Deleted: 0
Unchanged: 0
Transferred: 0 files
Verified: no
Duration: 357ms--dry-run は両端が既に存在していることを必要とします。destination ディレクトリを作成するのは、実際の実行だけです。
前回の取得以降に新しくなった点:AFS の外で手動編集されたclaim済みのdestination に対する --dry-run --verify は、そのズレを Modified として報告するのではなく、明確に拒否するようになりました —— --full に関する --help 自身の説明文が、まさにこの失敗を名指ししています:
$ arc space sync --from src-claimed --to dst-claimed --dry-run --verify --view human
ERROR: Provider "did-space-files" cannot reach its "query-freshness" dependency at "/": index has diverged from disk in 1 directory — /: a.txt (size-mismatch) — run `arc space repair --folder dst-claimed` to repair. Or re-run with --full to read both trees directly and ignore the indexes (slower, but it is the right choice for a folder that is deliberately written outside AFS).(exit 5。)--full を渡す(または先に arc space repair --folder <dst> を実行する)のが、この拒否の accept-path 側の対応です —— 同じ改ざんされたファイル、同じコマンド、フラグを 1 つ追加しただけで、上の普通のフォルダの例とまったく同様に Modified: 1 を報告し、1 で終了します(--verify の不一致による終了コードで、拒否ではありません)。
編集
arc space rm
ローカルの app space 内のファイルまたはディレクトリを、再帰的に削除します。これは space の ledger を経由します —— 素の rm -rf は、arc space repair でしか消せない幻の行をインデックスに残します。
使用法
arc space rm <app-did> <path> [options]--app-did <did>(必須、第 1 positional でもある):対象の app DID--path <path>(必須、第 2 positional でもある):app fragment 内のパス--scope <instance|user>:どの DID Space か(デフォルトuser)--root-path <path>/--user-did <did>:listと同じ上書き項目
両方の positional が必須です —— arc space rm <app-did> だけ(path なし)は「non-option 引数が足りない」として拒否されます。これは、上の tree/path が --app-did の欠落で当たったのと同じ yargs レベルのガードです。
フォルダ形態の space
claim されたフォルダとは、.did-space/ インデックスを伴う、普通の手編集可能なファイルツリーによって支えられた DID Space のことで、layout=cas(コンテンツアドレス方式)の形態とは対照的です。この 5 つのコマンドは、フォルダを claim し、そのインデックスがディスクとまだ一致しているかを確認し、一致していなければ再構築し、CAS の space をフォルダ形態に変換します。
arc space init
フォルダを書き込み可能な DID Space として初期化します —— .did-space/ だけを作成します。
使用法
arc space init <dir> [options]dir(必須):DID Space として claim するフォルダ(--sourceが設定されている場合は ledger)--external-writes <none|possible>(デフォルトpossible):新しい space に対する query-freshness の宣言。possible—— 人が初期化したフォルダは常に手編集される可能性があるため、すべてのクエリがディスクを再スキャンする。none—— 何か他のもの(デーモン)がこのフォルダを排他的に管理する場合にのみ渡す;この場合、クエリはインデックスから直接答える。外部 ledger 形態(--source)はpossibleを要求する--source <path>:外部 ledger 形態のための読み取り専用の真実の層;ledger(.did-space/config+space.db)はdirに作成され、source 自体には決して書き込まれない
$ arc space init ~/notes
Initialized DID Space at ~/notes (layout=files, externalWrites=possible)init のデフォルトビューは、この同じ 1 行のテキストです;--json は { "dir", "layout", "externalWrites" } を返します。
すでにファイルが入っているフォルダを claim しても、それらのファイルはインデックスされません —— init は .did-space/ を作成するだけです。その後 arc space repair --folder <dir> を実行するか、先に arc space check --folder <dir> を実行してインデックスに何が欠けているかを確認してください。
arc space check
ローカルの DID Space を監査します:layout(migrated / needs migration / unreadable)と、index と disk の新鮮度です。読み取り専用です —— インデックスや config を書き込むことは決してありません。移行が必要なもの、読み取れないもの、あるいはズレているものがある場合は非ゼロで終了します。
使用法
arc space check [options]--folder <dir>:ちょうど 1 つの claim されたフォルダの新鮮度だけを確認し、layout のスイープを完全にスキップする--root <dir>(繰り返し可能):layout スイープの root ディレクトリ。デフォルト:このインスタンスの space root およびその兄弟である<home>/.afs/work—— host の work ledger はroot_pathの外側にあるそこに存在し、これを見落としたスイープは誤って「全て問題なし」と報告する--root-path <path>:スイープ用の root path の上書き
check のデフォルト(非 TTY)ビューは JSON です。以下のテキストではありません —— これは本ページの前回の取得以降に新しくなった点で、以前はこのテキストがデフォルトであるかのように示されていました。以下のすべての例は、読みやすい形式のために --view human を渡しています。これを外すと、代わりに { "folder", "layout", "externalWrites", "directoriesChecked", "fresh", "dirty" } と同じデータが得られます(デフォルトビュー経由でも明示的な --json 経由でも、ペイロードは同一です)。
ズレはディレクトリごとに報告され、解決策も明記されます:
$ arc space check --folder ~/notes --view human
Check freshness: ~/notes (layout=files, externalWrites=possible)
Directories checked: 2
Result: DRIFT DETECTED — 2 of 2 directories disagree with disk
/
! b.txt [missing-in-index]
! notes [missing-in-index]
/notes
! a.md [missing-in-index]
Run `arc space repair --folder ~/notes` to repair (review the entries above first — it rebuilds the WHOLE index from disk).問題のない space はそのとおりに報告し、0 で終了します:
$ arc space check --folder ~/notes --view human
Check freshness: ~/notes (layout=files, externalWrites=possible)
Directories checked: 2
Result: CLEAN — index agrees with diskarc space repair
実際のファイルツリーからインデックスを再構築することで、claim されたフォルダ space を修復します。claim されたフォルダの下でファイルを手編集した後、またはその中で素の rm -rf を行った後に使います。
使用法
arc space repair --folder <dir> [options]--folder <dir>(必須):修復する claim されたフォルダ(layout=filesでなければならない)--index(デフォルトtrue):ディスクから folder-backend のインデックスを再構築する —— このコマンドが今日行う唯一の修復
$ arc space repair --folder ~/notes
Repaired index for ~/notes (layout=files)
Added: 2
Modified: 0
Deleted: 0
Unchanged: 0
Duration: 43msrepair のデフォルトビューは、この同じテキストです;--json は { "folder", "layout", "added", "modified", "unchanged", "deleted", "elapsed" } を返します(Duration ではなく elapsed であることに注意してください —— 2 つのビューは同じ数値に対して異なるキー名を使っています)。
arc space set
既存の layout=files DID Space に宣言を設定します。
使用法
arc space set <folder> <assignment>--folder <dir>(必須、第 1 positional でもある):更新する claim されたフォルダ(既にlayout=filesでなければならない ——arc space initを参照)--assignment <key>=<value>(必須、第 2 positional でもある):設定する宣言。external-writes=none—— このフォルダは排他的な(例:デーモンによる)管理下にあり、クエリはディスクスキャンなしでインデックスから直接答える。external-writes=possible—— フォルダはまだ手編集される可能性があり、クエリは毎回答える前にディスクを再スキャンする。どちらの方向でも冪等かつ可逆;.did-space/configにすでにある他のキーはすべて変更されずに保持される
$ arc space set ~/notes external-writes=none
Set externalWrites=none for ~/notes (layout=files)arc space migrate
layout=cas の DID Space を、その場で layout=files に移行します(コピー → 検証 → アトミックな置き換え;古い CAS ディレクトリはロールバックのために保持されます)。
使用法
arc space migrate <dir> --to-layout files [options]dir(必須):移行する claim された DID Space フォルダ(layout=casでなければならない)--to-layout <files>(必須):目標の layout ——filesのみサポートされる--dry-run:何が起こるかを報告する(space 数、ファイル数、バイト数、期待される結果)—— ディスクへの変更はゼロ--external-writes <none|possible>(デフォルトnone):移行後のlayout=filesspace に対する query-freshness の宣言。デフォルトがnoneなのは、layout=casspace の真実の層(objects/<cid>+_metadata.db)は人が手編集するものではないため、「移行時点で外部の書き込み者はいない」ということが断言可能な事実だからです;この space が実際に普通の手編集可能なフォルダとして扱われてきた場合にのみpossibleを渡してください
migrate のデフォルト(非 TTY)ビューも、check と同様に JSON です;--view human は代わりに短い文章形式のサマリーを表示します。
既に layout=files であるフォルダを migrate してもエラーにはなりません —— これは本物の、冪等な accept path です、exit 0:
$ arc space migrate ~/notes --to-layout files --view human
Migrate ~/notes (layout=cas -> layout=files)
Already layout=files — nothing to migrate.
External writes: none.did-space/ がまったくないフォルダに対して arc space migrate を実行すると、これはエラーです —— 上の「すでに移行済み」とは異なるものです(exit 5):
$ arc space migrate ~/plain-dir --to-layout files
ERROR: arc space migrate: ~/plain-dir is not a claimed DID Space (no .did-space/). Run `arc space init ~/plain-dir` first.移行を取り消す必要がある場合のロールバック:
rm -rf "<dir>"
mv "<parent-of-dir>/.cas-backups/<dir-name>" "<dir>"移行前の layout=cas ディレクトリは <parent-of-dir>/.cas-backups/<dir-name> に保持され、自動的に削除されることは決してありません。これは意図的に、space 自身の parent よりも 1 階層下、それ自体は claim された space ではないコンテナの中に置かれています。そのため space の列挙 —— つまりデーモンの起動 —— は、このバックアップを二度と発見しません。
sync-bench(内部)
このビルドには 11 番目のサブコマンドが存在します:arc space sync-bench は、afs-rpc(afs-rpc-batch P6 driver)上で駆動される SyncEngine のスループットベンチマークです。これは --server <url> と --token <token> を必要とします —— ローカルフォルダではなく実際のリモートエンドポイントです —— そして --prefix(デフォルト e2e-batch/bench)の下で使い捨てのファイルを seed / ベンチマーク / クリーンアップします。他の 10 個とは異なり、space のデータモデルにおける読み取り/書き込み/検視の役割は持ちません;そのフラグ(--blocklet、--files、--size、--single-op、--header、--cleanup)については arc space sync-bench --help を参照してください。本ページではこれ以上詳しく説明しません。