Skip to main content

arc afs

arc afs is the command group for AFS file system operations: listing, reading, writing, deleting, and searching paths, running actions, and managing mounts.

arc afs is the command group for AFS file system operations. Every subcommand operates on an AFS path, a mounted location like /src or /data, not a raw filesystem path on your machine.

Captured against arc 2.0.0-beta.50 (commit a99fb2c37, main, 2026-09-11). Run arc --version before you copy dumps; the commit is what pins the command surface.

bash
arc afs <subcommand> [options]

Run arc afs --help to see the full subcommand list. Every subcommand also accepts the global --json, --view <default|llm|human|json>, --instance / -i, and --home <dir> flags described in Overview. --yaml was removed (never implemented); use --json or --view json.

An unrecognized flag is now rejected (Unknown argument: <name>, exit 5), not silently ignored — for example arc afs ls --bogus-flag foo fails instead of running with --bogus-flag dropped.

Which instance does this talk to

arc afs needs a live instance to run against. With no flag it attaches to the default background instance (started with a bare arc service start); if none is running, every arc afs subcommand exits non-zero instead of silently falling back to a throwaway ad-hoc AFS:

bash
$ arc afs ls /
ERROR: No AFS daemon is running for instance "default".
Start it with:  arc service start
Or use --standalone for ad-hoc mode (no runtime state)
  • --instance <name> / -i: global. Attach to a named instance instead of the default one (see arc service list). Omit for default
  • --home <dir>: global. Instance root. Used by arc service start (create), --standalone (ad-hoc), and arc did init. To pick which instance, use --instance. If you pass both and they name different instances, the command fails
  • --standalone: force ad-hoc mode — load AFS straight from the local .afs-config/config.toml in the current directory instead of connecting to any running daemon. No runtime state (mounts you add elsewhere, live subscriptions, etc. are invisible); prints a [standalone] not attached to any instance line to stderr as a reminder
bash
arc service start --instance docs-demo --home ~/docs-demo   # start a named instance once
arc afs ls / --instance docs-demo                 # every later afs call names it explicitly

Reading and listing

arc afs ls

List directory contents.

Usage

bash
arc afs ls [path] [options]
  • [path] (optional, default /): the AFS path to list
  • --depth <n>: maximum depth to list (default 1)
  • -l: long listing format, shows kind and size
  • -R: list recursively
  • --limit <n>: maximum number of entries to return
  • --max-children <n>: maximum children per directory
  • --pattern <glob>: filter entries by glob pattern

Aliased as arc afs list.

-R and an explicit --depth are mutually exclusive — -R always lists at depth 10, so combining it with --depth is ambiguous about which one wins:

bash
$ arc afs ls /demo -R --depth 2
ERROR: ls: --depth conflicts with -R (recursive always lists at depth 10) — choose one: drop --depth to use -R's depth of 10, or drop -R and pass --depth explicitly

A path that does not exist exits 1 (not 0 with an empty list, and not 5):

bash
$ arc afs ls /demo/does-not-exist
ERROR: No data found for path: /demo/does-not-exist

Example: recursive, long listing

bash
arc afs ls /demo -l -R
└── 📁 demo
    ├── 📄 notes.txt (fs:file)  15B
    └── 📁 reports (fs:directory)
        └── 📄 q1.txt (fs:file)  15B

arc afs read

Read file content.

Usage

bash
arc afs read [path] [options]
  • [path] (positional, or --path <path>, one of the two is required): path to read
  • --start-line <n>: start line, 1-indexed, inclusive
  • --end-line <n>: end line, 1-indexed, inclusive; -1 for end of file

Aliased as arc afs cat.

Example

bash
$ arc afs read /demo/notes.txt
Hello from AFS

A path that does not exist exits 1:

bash
$ arc afs read /demo/does-not-exist.txt
ERROR: No data found for path: /demo/does-not-exist.txt

arc afs stat

Get file or directory info.

Usage

bash
arc afs stat [path]
  • [path] (positional, or --path <path>, one of the two is required): path to inspect

Example

bash
$ arc afs stat /demo/notes.txt
PATH=/demo/notes.txt
KIND=fs:file
SIZE=15
MODIFIED=2026-08-01T04:00:51.508Z

A path that does not exist exits 1, same message and exit code as arc afs read:

bash
$ arc afs stat /demo/does-not-exist.txt
ERROR: No data found for path: /demo/does-not-exist.txt

Search for content within an AFS path.

Usage

bash
arc afs search [path] [query]
  • [path] (positional, or --path <path>, one of the two is required): path to search in
  • [query] (positional, or --query <text>, one of the two is required): search query

Aliased as arc afs grep. Not aliased as findfind was removed (it searches content, not names; to filter entries by name instead, use arc afs ls --pattern).

Example

bash
$ arc afs search /demo revenue
/demo/reports/q1.txt

arc afs explain

Explain AFS concepts or paths. With no argument it prints a general overview (mount / path / uri concepts); with a topic or an actual AFS path it explains that specifically.

Usage

bash
arc afs explain [topic]
  • [topic]: a concept name (mount, path, uri) or an AFS path, e.g. /src. Can also be passed as --topic <value> instead of positionally

Example

bash
$ arc afs explain
AFS Overview
============

AFS (Agentic File System) is a virtual filesystem that unifies different data sources into a single namespace.

Core Concepts:
- mount: Mount a data source to a virtual path
- path: Virtual path, e.g., /src, /data
- uri: Data source address, e.g., fs://, git://, sqlite://

Data Flow:
  User Path -> AFS -> /{mount} -> Provider -> Actual Data

Examples:
  $ arc afs mount add /src fs:///path/to/source
  $ arc afs ls /src
  $ arc afs read /src/file.txt

arc afs subscribe

Subscribe to AFS events under a path; prints one JSON event per line until you press Ctrl-C. Useful for watching a mount for changes made by another process (a build tool, another arc afs write, a running blocklet).

Usage

bash
arc afs subscribe [path] [options]
  • [path] (optional, default /): path prefix to watch, e.g. /demo or /dev/code-agents. Can also be passed as --path <value>
  • --type <pattern>: event type filter, e.g. afs:write, afs:* (default afs:write, wildcards allowed)

Example (run in one terminal, then arc afs write /demo/hello.txt ... in another)

bash
$ arc afs subscribe /demo
Subscribed to /demo (type=afs:write) — Ctrl-C to stop
{"type":"afs:write","path":"/demo/hello.txt","source":"fs","timestamp":1787870798884}

Writing and deleting

arc afs write

Write content to a file.

Usage

bash
arc afs write [path] [content] [options]
  • [path] (positional, or --path <path>, one of the two is required): path to write
  • --content <text>: content to write
  • --mode <mode>: one of replace (default), append, prepend, patch, create, update
  • --patch <json>: JSON array of patch operations, used with --mode patch
  • --meta <key=value>: set a metadata field, repeatable
  • --if-match <version>: optimistic-concurrency token from a prior stat/read/write. Rejects the write with AFS_CONFLICT if the current version differs; providers that don't support it ignore the flag (last-write-wins)

Example: write, then append

bash
$ arc afs write /demo/draft.txt --content 'first draft'
OK /demo/draft.txt

$ arc afs write /demo/draft.txt --content ' plus more' --mode append
OK /demo/draft.txt

$ arc afs read /demo/draft.txt
first draft plus more

arc afs delete

Delete a file or directory.

Usage

bash
arc afs delete [path] [options]
  • [path] (positional, or --path <path>, one of the two is required): path to delete
  • -r, --recursive: delete a directory recursively (default false)
  • --dry-run: print what would be deleted without deleting it
  • --yes: skip the TTY confirmation prompt (the prompt only appears when stdin is a real TTY; a non-interactive arc afs delete — a script, CI, this doc's own examples — never blocks on it either way)

Aliased as arc afs rm.

Example: preview, then delete

bash
$ arc afs delete /demo/draft.txt --dry-run
Would delete /demo/draft.txt (dry-run)

$ arc afs stat /demo/draft.txt
PATH=/demo/draft.txt
KIND=fs:file
SIZE=21

$ arc afs delete /demo/draft.txt --yes
OK /demo/draft.txt

Executing actions

arc afs exec

Execute an action exposed by a provider at a given path, for example a provider-defined operation that isn't just a plain file read/write.

Usage

bash
arc afs exec <executable_path> [options]
  • executable_path (required): the action path to execute
  • --args <json>: JSON arguments, e.g. --args '{"key": "value"}'

Not every mount exposes actions. Against a plain fs:// mount attached to a running instance, calling an action path currently surfaces as a generic server error, not a specific one — the daemon's HTTP layer doesn't propagate the underlying AFS error text for this case:

bash
$ arc afs exec /demo/.actions/foo
ERROR: Internal server error

In --standalone mode (no daemon in the loop) the same call gets the specific message instead:

bash
$ arc afs exec /demo/.actions/foo --standalone
ERROR: No actions available for path: /.actions/foo

Mount management

arc afs mount is its own subcommand group for managing what's mounted where.

bash
arc afs mount <subcommand> [options]

arc afs mount add writes to the .afs-config/config.toml found by walking up from your current directory — not to any --instance/--home instance. --home is rejected outright (exit 5) because that flag would imply the change reaches an instance's daemon, and it never does. --instance / -i is the global instance selector: if that instance isn't running, the command fails before mount add runs. Drop --home and run from the right directory instead. To change what a running instance has mounted: cd into that instance's home directory (the one you passed to arc service start --home) before running arc afs mount add, then it takes effect for that instance immediately, no restart needed. (This is the mechanism behind the "mount add is not automatically an acceptance path" caveat on the AFS runtime boundaries page — running mount add from the wrong directory is what makes the mount show up in mount list but not in ls.)

bash
$ arc afs mount add /demo fs:///path/to/a/local/directory --instance docs-demo
ERROR: no instance named "docs-demo". `arc service list` shows 0

$ arc afs mount add /demo fs:///path/to/a/local/directory --home /Users/you
ERROR: --home is not supported by `arc afs mount add`. `arc afs mount` only reads and writes the `.afs-config/config.toml` found by walking up from the current directory; it never reaches an instance's daemon, so the selected instance would silently not see the change. Drop the flag to edit the cwd config, or mount into a running instance at runtime with `arc attach --to <daemon-url> --namespace <ns> --source <dir>`.
bash
cd ~/docs-demo                                    # the instance's --home directory
arc afs mount add /demo fs:///path/to/a/local/directory
arc afs ls /demo --instance docs-demo               # visible right away

arc afs mount add

Add a mount.

Usage

bash
arc afs mount add <path> <uri> [options]
  • path (required): mount path, e.g. /src
  • uri (required): provider URI, e.g. fs://./src
  • --namespace <name>: mount namespace
  • --description <text>: mount description
  • --sensitive-args <names>: field names to treat as sensitive credentials
  • -s, --set <key=value>: set a credential directly, repeatable, bypasses the interactive prompt
  • --terminal: collect credentials via terminal readline instead of a browser
  • -f, --force: force re-collecting credentials, ignoring cached values

Example

bash
$ arc afs mount add /demo fs:///path/to/a/local/directory
Mounted fs:///path/to/a/local/directory at /demo

arc afs mount list

List all mounts.

Usage

bash
arc afs mount list [options]

Aliased as arc afs mount ls. There is no --namespace filter — the cwd .afs-config/config.toml is one table with no per-namespace slice to filter by, so passing --namespace is rejected:

bash
$ arc afs mount list --namespace anything
ERROR: --namespace is not supported by `arc afs mount list`. `arc afs mount` reads and writes the cwd `.afs-config/config.toml` as one table; there is no per-namespace slice. Drop --namespace.

Example (one entry shown; your actual list will contain every mount you've added)

bash
$ arc afs mount list
/demo -> fs:///path/to/a/local/directory

arc afs mount remove

Unmount a path.

Usage

bash
arc afs mount remove <path> [options]
  • path (required, positional only): mount path to remove. --help also lists a --path option marked [required], but passing it as a flag instead of positionally does not satisfy the requirement — it still fails with Not enough non-option arguments: got 0, need at least 1. Always pass the path positionally
  • --namespace <name>: not supported — arc afs mount treats the cwd .afs-config/config.toml as one table with no per-namespace slice, so remove --namespace foo is rejected (ERROR: --namespace is not supported by 'arc afs mount remove'), same as on mount list

Aliased as arc afs mount rm.

Example

bash
$ arc afs mount remove /demo
Unmounted /demo

Passing the path as --path instead of positionally does not work, even though --help lists it as a required option:

bash
$ arc afs mount remove --path /demo
ERROR: Not enough non-option arguments: got 0, need at least 1

arc afs mount validate

Validate the current mount configuration.

Usage

bash
arc afs mount validate

Example

bash
$ arc afs mount validate
Configuration is valid

Notes on output

When an afs command talks to a running instance — the default — it writes nothing to stderr at all: the result on stdout is the whole output. Boot logging belongs to the daemon, not to your shell.

--standalone is the exception, because there the command boots AFS inside your own process and that boot log goes to your terminal. Three lines are invariant — the one naming the ad-hoc mode, one echoing which .afs-config/config.toml file(s) it read, and, whenever AFS_DID_SPACE_SCOPE_SECRET is unset, a warn record from node:boot reporting that DID Space scope de-identification is off and directory names are stored in plaintext:

text
[standalone] not attached to any instance — ad-hoc mode (no runtime state)
[standalone] config: /path/to/.afs-config/config.toml
{"ts":"…","level":"warn","service":"arc-node","ns":"node:boot","message":"[afs-loader] AFS_DID_SPACE_SCOPE_SECRET unset — DID Space scope de-identification is OFF (plaintext directories). Set the secret to enable; set AFS_DID_SPACE_REQUIRE_DEID=true to enforce."}

Set the secret and the third line is gone; set AFS_DID_SPACE_REQUIRE_DEID=true to make its absence an error instead. Anything further on stderr is node:boot reporting on your own machine — a mount it could not establish, or a [code-agents] recover ok: ... line from the scheduler's own boot, say — so the total line count differs between hosts. Recognise the three above rather than counting them. None of it is part of the command's result, and all of it is omitted from the examples above.