SuperAPI AI Directory

aside-agent

Office & productivity

View repository

Updated 10-17 08:06

About this skill

Aside Computer Skill

This skill lets the Agent on the computer use the phone's foreground terminal according to references/protocol.md . The protocol is governed by that document. Do not build a separate login or content protocol.

Library operations go only through arc afs. Without scripts/client.mjs, also do not write another client that POSTs to /rpc yourself. Pairing, claiming, and probing are not AFS methods; they still go through /agent/v1. Once mounted,arc 's HTTP provider forwards list、read、stat、search、explain、exec to the phone's POST /rpc。

The Skill is not a security boundary. Permission on the phone is the authorization. The computer cannot grant permission itself, nor confirm permanent deletion itself.

Supported scope

The computer side uses macOS's built-in dns-sd and curl, as well as arc. When arc is missing, install it first:curl -fsSL https://arc.afsd.io/install.sh | bash。

There is no interactive Codex, Claude, or Muse session. Muse is not a supported integration. Do not list tools you have not run as supported. Fill--tool with the real tool name of the current Agent.

Working directory

All arc afs commands run in ~/.aside-agent , with --standalone。arc afs mount writing only to the current directory's .afs-config/config.toml, not into the running daemon. Mounting inside the skill directory is the same: the command may report already mounted, while the running daemon still has no /aside. --standalone without arc afs ls hits the daemon and will not see this mount.

mkdir -p ~/.aside-agent
cd ~/.aside-agent

The credential file is ~/.aside-agent/credential, permissions 0600. This computer's fixed identifier is ~/.aside-agent/device-id. When this file is missing, create it once with the content mac- plus a random hexadecimal segment, and reuse it for every subsequent pairing. Making up another new identifier will cause the phone to record this computer as a separate connection. Do not write credentials, pairing codes, or device-id into chats, logs, command echoes, or this skill.

First connection

  1. Ask the user to open Aside's content terminal page on the phone. After opening it, they can leave the page. Switching to another app, locking the screen, or being away for a while will all preserve the authorization until the user disconnects this one themselves. Listening stops first when the screen is locked or after being away for a while, and reopens by itself when returning to the foreground if authorization still exists—no need to open this page again or use a new pairing code. Tapping "End Connection" or "End All Connections", as well as confirming disconnection of a particular one, immediately revokes that authorization. Switching libraries or accounts does not revoke authorization. When the library has not yet been switched to the current account, content reads and writes will fail with library-changing ; the credential is still valid, retry with the same one, do not re-pair. Once mounted, reads and writes land in the currently open library. On first open, the system may ask for local network permission, which must be allowed.
  2. The phone and computer are on the same LAN. This version is plaintext TCP, with no TLS. Discovery uses Bonjour _aside-agent._tcp. Being on the same network does not mean trust. Until revoked, pairing codes and credentials can be seen by observers on the same LAN.
  3. Browse first. With only one device, use its hostname and port directly—don't stop to ask which one to pick. With two or more, ask the user to choose by matching the four-character marker on their phone; don't pick the first one yourself, and don't read the whole service name aloud as a title. Don't scan the entire subnet, and don't try addresses one by one.
dns-sd -B _aside-agent._tcp local.
dns-sd -L "服务名" _aside-agent._tcp local.

base Use the hostname and port from the resolution result, in the form http://HOST:PORT. The port and four-character marker change every time listening is reopened; don't reuse the previous session's port. Once the user has chosen a device, match that device by hostname on the next browse and reuse the original credentials. Don't change this address to IPv4 or another host. If the list is empty, tell the user to bring Aside to the foreground. Authorization is still valid; no need to allow again. Only after the user taps end connection, or this one has already been disconnected, do they need to reopen the terminal page. The page does not provide an address. Don't scan the subnet, and don't ask the user for host:port。

  1. Discover first, then determine the version. The first connection may fail; retry once with the same base . Don't switch addresses.
curl -sS "$BASE/agent/v1/discovery"

protocol must be aside-agent,version must be 1, and requiresPairing and requiresPhoneAllow must both be true. Otherwise stop. Tell the user the versions don't match—don't switch to another path or invent another protocol.

  1. If credentials already exist, first run probeagainst the base from this browse. If it succeeds, continue with these credentials, skip to step 7, and don't pair again. Only pair when there are no credentials, or when probe returns unauthorized、revoked、denied .
curl -sS -X POST "$BASE/agent/v1/probe" \
  -H "Authorization: Bearer ${ASIDE_TOKEN}" \
  -H 'content-type: application/json' \
  -d '{}'

ASIDE_TOKEN Read from the credentials file; don't echo。account.name is the account currently open on the phone; use this name. The computer cannot choose a different account.

  1. Pair. Give the returned tool name, device name, and pairing code to the user immediately, and claim right away. The pairing code on the phone expires after about 60 seconds. Don't read source code or do anything else in this window. The pairing code is not a credential. Don't call allow on the computer. The online /agent/v1/allow will reject it.
curl -sS -X POST "$BASE/agent/v1/pair" \
  -H 'content-type: application/json' \
  -d '{"toolName":"当前工具名","deviceName":"这台电脑","deviceId":"DEVICE_ID"}'

Claiming before allow returns not-allowed; this does not mean the code is wrong. Retry about once per second, for up to about 50 seconds. If the window runs out and you get pairing-expired , pair again, give the user the new code, and don't reuse the old code.

curl -sS -X POST "$BASE/agent/v1/claim" \
  -H 'content-type: application/json' \
  -d '{"sessionId":"SESSION_ID","pairingCode":"PAIRING_CODE"}'

Write the credential from the response into ~/.aside-agent/credential and chmod 600. Don't print credentials.claim The success body has no expiresAt. Credentials have no clock-based expiry. They are only invalidated when the user disconnects this one, denies, or ends all connections.

If claiming fails to connect the first time, request again with the same base . If claimed, continue. If it still can't connect, stop and ask the user to bring Aside to the foreground. Don't pair again.

  1. Mount to /aside. This is the condition for a successful connection. In ~/.aside-agent , unmount first, then mount, to avoid old ports and old credentials remaining in the config. The URI contains only the host and port.allowPrivateNetwork must use --set. Writing it only in the query parameters will cause it to be dropped, and the LAN address will then trigger SSRF. Credentials do not go in the URI.
cd ~/.aside-agent
arc afs mount remove /aside
arc afs mount add /aside "$BASE" \
  --set allowPrivateNetwork=true \
  --set "token=${ASIDE_TOKEN}" \
  --sensitive-args token

Then confirm in the same directory that it is mounted:

cd ~/.aside-agent && arc afs ls /aside --standalone --json

If this step succeeds, the connection succeeded./aside is the library currently logged in on the phone; below is items、collections、tags. If mounting fails, don't try other addresses, don't scan the subnet, and don't write another HTTP client. If the private network is rejected, check whether --set allowPrivateNetwork=true was really passed to this mount add。

  1. Before writing a note with an embed, check capabilities. The action must appear in the returned actions , and the block kind must appear in note.blocks Inside. Without note , write only plain text.
cd ~/.aside-agent && arc afs exec /aside/.actions/aside \
  --args '{"action":"capabilities"}' \
  --standalone --json

Do not call /.actions/query. It always rejects, and the message is query is not served on this library。

Search

For item search, use the AFS tree's search. This is the library index wired up in #2369, the same one as the mobile search page. Keywords, Chinese, tags, collections, types, links, and dates are all in this one query string. Do not first ls and then do a local substring match, and do not POST /rpc。

cd ~/.aside-agent && arc afs search /aside/items "论文 tag:papers after:2026-01-01" --standalone --json

For the next page, use meta.cursorfrom the previous page's JSON. Keep the path and query unchanged.

cd ~/.aside-agent && arc afs search /aside/items "论文 tag:papers after:2026-01-01" \
  --cursor "CURSOR" --standalone --json

/aside and /aside/items both hit this index. Other paths are not this index. Use arc afs lsfor collections and tags; do not search for them with the prefix language.

Prefixes are case-insensitive. Words without a prefix are ANDed with each other. An empty query or pure whitespace is an empty page and will not return recent items. To browse the directory, use ls. A prefix alone with no keyword (for example, tag:papers、type:link) queries the index. Archived items are excluded by default.arc afs search must include --json. When --limit is not passed, this page has at most 500 items.--limit is a positive integer; this phone only uses 1 to 500, and anything larger is clamped to 500.meta.hasMore Only when true does it include --cursor, and the value is this page's meta.cursor. If there is no meta, or hasMore is not true, stop; do not make up a cursor.arc afs search --help When --cursor is not in /rpcyourself. When the response has exactly 500 items and no meta , this phone does not yet have search pagination; do not treat this page as everything. Collections and tags do not use this cursor.arc afs exec For list / search , use a different set of nextCursor: default 50, maximum 100.

Syntax Meaning
论文 检索 Keywords AND. Chinese does not need to be segmented manually
tag:papers Filter by the current tag name. Multiple tag: AND
collection:阅读 Filter by the current collection name. Multiple collection: AND
type:link Types. Multiple type: are ORed. Aliases are link, note, text, image / photo, file, contact, event / calendar, place
link:example.com or site:example.com matches on URL / host
after:2026-01-01 before:2026-02-01 By createdAt。after includes the day,before excludes the day
status:archived Include archived items too

Repos on the home page are not type:repo or type:repos. These two queries are empty pages, and there is no repo in the aliases. The type in lists and search is an item type like link or note. Repos are in the item JSON's content.type, with the value repo; the list type of these items is still link. Keyword hits without a prefix are not this category.ls Neither content.type. Read /aside/items/<slug>.json to see it.

Hits are AFS items, with id and path, no body, and no guaranteed title. The path is under /aside/items/ . To get the title and body, read this path. Ordering is index order: exact URL, exact title, title prefix, then bm25, then createdAt descending.

Reading and writing

Every library command starts from ~/.aside-agent and includes --standalone --json。~/.aside-agent is not the parent of the project directory; running --standalone in another directory cannot see this mount. Do not arc afs write, and do not arc afs delete. These two will be rejected and the library will not be changed. Only use for changing the library: arc afs exec /aside/.actions/aside。--args is a JSON object.

Read:

cd ~/.aside-agent && arc afs ls /aside/items --standalone --json
cd ~/.aside-agent && arc afs read /aside/items/ITEM.json --standalone --json
cd ~/.aside-agent && arc afs stat /aside/items/ITEM.json --standalone --json

Do not load the full-page JSON into memory with Node's spawnSync or execFileSync . Even if maxBuffer is set to 64MB, stdout will still be truncated at 8192 bytes. Write the output to a file first, then parse that file.

resourceVersion is the SHA-256 of the bytes of that JSON file, using stat 's sha256, or the resourceVersionin the file. updatedAt。

Use exec for attachment bytes; do not guess a local path:

cd ~/.aside-agent && arc afs exec /aside/.actions/aside \
  --args '{"action":"readAttachment","id":"ITEM_ID","attachment":"ATTACHMENT_ID"}' \
  --standalone --json

For writes, use a new operationIdfor each new change. The same retry must use the same id, and the body must be exactly the same. Changing the body will be treated as a conflict and will not be written as a second object. After writing, read the same entry again; only whenresourceVersion and noteBlocks match what the write returned is the write successful.

Plain-text Quick Note:

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "createNote",
  "operationId": "OP_ID",
  "title": "标题",
  "text": "正文"
}'

When there are embeds, blocks takes precedence, and you may omit text. For links, only provide http or https url. For places, use latitude and longitude,kind to write location or place. Images, audio, files, and videos must have a filenamewithout a path, and the bytes go in contentBase64. You may include mimeType. Audio and video may include duration. At most 9 images, each no more than 20MB. Audio and files no more than 20MB each. Images, audio, and files together no more than 60MB. At most 1 video, no more than 200MB, and no longer than 15 seconds. Weather is not accepted.--args uses the command line; do not switch to writing your own HTTP for attachments that do not fit. Tell the user that this attachment is too large.

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "createNote",
  "operationId": "OP_ID",
  "title": "标题",
  "blocks": [
    {"kind": "text", "text": "正文"},
    {"kind": "link", "url": "https://example.com/notes", "title": "页面"}
  ]
}'

The returned noteKind is quickNote。noteBlocks without bytes. To get bytes, use readAttachment,attachment with the block's resourceId。

To edit an existing note, include the resourceVersionyou just read. To keep embeds,blocks must be the complete list. Images, audio, files, and videos already on the phone can be written with only resourceId. Passing only text will reduce this note to a piece of text.

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "updateNote",
  "operationId": "OP_ID",
  "id": "ITEM_ID",
  "resourceVersion": "RESOURCE_VERSION",
  "blocks": [{"kind": "text", "text": "正文"}]
}'

Tags, collections, and members are also the same exec.member is a boolean. Updates, member changes, and tagging entries must include the resourceVersionyou just read. When a conflict is returned, re-read the current version and write again with a new operation id.

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "ensureTag",
  "operationId": "OP_ID",
  "name": "标签"
}'

updateTag、createCollection、updateCollection、setMembership、setItemTag 's fields are in the protocol's content action table.setItemTag Use itemId and name。member . When true, a tag with the same name is created first if it does not exist and then attached. When false, it is only removed from this item; the tag itself remains.

Batches contain only non-delete write operations. If some items fail, the successful ones remain. Do not execute the whole batch again. Read back first, and retry only the failed steps with new operation ids.

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "batch",
  "operationId": "OP_ID",
  "operations": []
}'

Permanent deletion only registers a phone confirmation; it does not delete content:

cd ~/.aside-agent && arc afs exec /aside/.actions/aside --standalone --json --args '{
  "action": "delete",
  "operationId": "OP_ID",
  "objectIds": ["ITEM_ID"],
  "count": 1
}'

In the response, when pending is true and confirm is phone , tell the user: these objects and their counts must be confirmed on the phone, valid for about 60 seconds. Cancellation, timeout, or session revocation will not delete anything. Do not exec confirm or confirmDelete. That will not delete anything.

After the user disconnects this entry, rejects it, or taps end connection, if it was previously mounted, unmount it again. Do not unmount and re-pair because of a lock screen or being away for a long time.

cd ~/.aside-agent && arc afs mount remove /aside

Two different Agents mean two pairings, two sessions, two sets of credentials. Do not share one credential file. When pairing again with the same computer and same tool, the phone collapses the previous session. Do not pair again just because the user left the terminal page.

The AI tool you use may send what it reads to its own cloud service. Tell the user this before you start reading.

Recovery

  • Screen locked or away for a long time: listening stops first, authorization remains. HTTP requests without a timeout will hang forever. If you cannot connect, stop; do not spin. Tell the user to bring Aside to the foreground, then browse again. If credentials already exist, for this base first probe. On success, use the new port to mount addagain; do not pair again.
  • The user tapped end connection, or disconnected this one on the phone: this set is void. Ask the user to reopen the terminal page. Browse again. If there is only one, use it directly; if there are several, ask the user to choose. Then pair again and allow again.
  • The user only left the terminal page, or briefly switched to another app: the connection is still there. When one library command fails while probe still succeeds, retry that one with the same base. Do not pair again. If you cannot connect, browse again. If browsing still finds this phone, use the original credentials.
  • Switching library or account: authorization remains; do not pair again. While the library is still switching, it will fail with library-changing . Retry with the same credentials. After alignment, reads and writes land in the currently open library.
  • Same LAN: after the phone restarts listening, both the four-digit marker and the port change. For the one already chosen, identify it by hostname and reuse the original credentials to probe. Only when the user has not yet chosen and there are several on the network should you select by matching the marker on the phone.
  • The user rejects on the phone: you get denied. Stop and ask the user whether to pair again. Do not keep claiming.
  • Pairing timed out or the code was already used: you get pairing-expired or pairing-used. Pair again and have the user check the new code.
  • Credentials revoked:revoked. This set can no longer be used. Pair again if needed.
  • Missing or wrong credentials:unauthorized. Do not print those credentials. Go through pairing again.
  • Cannot connect or browsing is empty: tell the user to bring Aside to the foreground. Do not pair again, do not scan the subnet.
  • Version mismatch: stop. Do not downgrade, and do not construct content paths yourself.
  • Disconnected halfway through a write: read back first. If the object is already there, do not create it again. If it was not written, retry with the same operation id and the same body.
  • Delete confirmation timed out or the user canceled: the content is still there. Do not add another confirmation on the computer.

Do not

  • Do not probe the subnet. Only browse _aside-agent._tcp。
  • Do not write an HTTP client to call /rpc or /agent/v1/content. For library operations use arc afs。
  • Do not put credentials into the mount URI, and do not omit --set allowPrivateNetwork=true。
  • Do not mount ~/.aside-agent in directories other than /asideon library commands. --standalone。
  • Do not read source code inside the pairing window. Give the pairing code to the user first, and claim it immediately.
  • Do not put credentials, pairing codes, or demo codes in skills, logs, or examples.
  • Do not request /user、/dev、/kv、/afs. To read the library, use only the mount point /aside。
  • Do not arc afs write、arc afs delete, and do not exec either /.actions/query、confirm、confirmDelete。
  • Do not write Muse or any other tool that has not been run as already supported.

Protocol

The actions, errors, and query aliases accepted by the phone are in references/protocol.md. What a given phone accepts is determined by this capabilities . The suite that listens against the real foreground is in the Aside repository design/aside-agent-mode/skill/。