Olares Files (olares-cli files) — manage files on an Olares system from the command line, scoped to the active Olares ID. Covers list (ls), upload, download,...
---
name: olares-files
version: 4.0.1
description: "Olares Files (olares-cli files) — manage files on an Olares system from the command line, scoped to the active Olares ID. Covers list (ls), upload, download, cat, edit (open in $EDITOR), mkdir, rm, cp, mv, rename, chown (POSIX owner uid get/set), folder share (internal cross-Olares-ID, public link with password + expiration, SMB Samba), mount / unmount / favorite external SMB servers, and Sync (Seafile) repo CRUD — all against the per-Olares-ID files-backend on Olares (drive/Home, drive/Data, sync, cache, external, awss3, dropbox, google, tencent, share). Use when the user mentions Olares, Olares ID, Olares Files, olares-cli files, LarePass Files on Olares, drive, Home, Data, sync, cache, uploading / downloading / listing / editing remote files on Olares, in-place rename, POSIX file ownership, sharing a folder with another Olares user (by Olares ID), public link with password / expiration, SMB / Samba network shares, the LarePass 'Connect to Server' dialog, or Sync (Seafile) libraries."
metadata:
requires:
bins: ["olares-cli"]
cliHelp: "olares-cli files --help"
---
# files (per-user files-backend)
**CRITICAL — before running any verb here, MUST use the Read tool to read [`../olares-shared/SKILL.md`](../olares-shared/SKILL.md) for profile selection, login, and 401/403 recovery rules.**
> **Source of truth for flags & wire shapes is always `olares-cli files <verb> --help`.** This file only carries what `--help` cannot give: the cross-cutting frontend-path concept, the trailing-slash convention, the five client-side hard constraints, and the verb index.
## Core concept: the 3-segment frontend path
Every resource on the per-user files-backend is addressed by:
```
<fileType>/<extend>[/<subPath>]
```
| Segment | Meaning |
|---------|---------|
| `fileType` | Storage class (lowercase, case-sensitive): `drive`, `cache`, `sync`, `external`, `awss3`, `dropbox`, `google`, `tencent`, `share`, `internal` |
| `extend` | Volume / repo / account inside that class. **Case-sensitive.** Drive: only `Home` or `Data`. Cache / external: node name. Sync: seafile repo id. Cloud (`awss3`/`dropbox`/`google`/`tencent`): account key |
| `subPath` | Path inside `extend` (root if omitted). Leading `/` is implicit |
Examples: `drive/Home/`, `drive/Home/Documents/report.pdf`, `sync/<repo_id>/notes/`, `awss3/<account>/<bucket>/key.txt`.
> Drive's `extend` MUST be `Home` or `Data` exactly — `home` is rejected with `invalid drive type`.
### Per-verb namespace support
| Verb | Supported namespaces |
|------|----------------------|
| `ls` / `cat` / `download` / `rm` / `rename` | all of `drive`, `cache`, `sync`, `external`, `awss3`, `google`, `dropbox`, `tencent` |
| `edit` | `drive`, `sync`, `cache`, `external` only (cloud / tencent / share / internal refused) |
| `mkdir` | all of `drive`, `cache`, `sync`, `external`, `awss3`, `google`, `dropbox`, `tencent` |
| `cp` / `mv` | same as `mkdir` (PATCH `/api/paste/<node>/`) |
| `upload` | `drive/Home`, `drive/Data`, `sync/<repo_id>`, `cache/<node>`, `external/<node>/<volume>`, `awss3`, `google`, `dropbox` — **`tencent` rejected** (different upload protocol) |
| `chown` | `drive/Home`, `drive/Data`, `cache/<node>` only (cloud, sync, external all refused) |
| `share internal` | `drive`, `sync`, `external`, `cache` (cloud refused) |
| `share smb` | `drive`, `external`, `cache` (sync + cloud refused) |
| `share public` | `drive` only |
| `smb mount` / `unmount` / `history` | keyed by `<node>` + `<smb-url>`, not frontend paths |
| `repos` | operates on the Sync (Seafile) library catalog, not frontend paths |
## Trailing-slash convention (critical)
Whether a path ends with `/` is meaningful:
| Form | Meaning |
|------|---------|
| `drive/Home/Foo/` | Directory intent |
| `drive/Home/Foo` | File intent |
It shows up here:
- `files rm drive/Home/Foo/` requires `-r` — the trailing `/` declares "this is a directory".
- `files upload <local> drive/Home/Documents/` → upload INTO Documents; `files upload <local> drive/Home/Documents/2026-Q1.pdf` → upload AS that exact path.
- `files cp <src> <dst>/` and `files mv <src> <dst>/` — `<dst>` MUST end with `/` (drop-into-directory mode). Renaming via `cp`/`mv` is not supported; use `files rename` for in-place basename changes.
- `files cp -r drive/Home/old/` (trailing `/` on a source) requires `-r`.
- `files ls drive/Home/` lists the volume root; both `drive/Home` and `drive/Home/` are accepted but the slash is recommended.
## Client-side hard constraints (5 quirks — never work around)
These five rules are enforced client-side and reflect real backend / GUI invariants. Teach yourself AND the user to respect them — do not suggest curl / API workarounds.
### 1. POST `/api/resources/<dir>/` auto-renames on collision
Hitting the directory-create endpoint against an existing directory does NOT return 409 — it silently creates `<dir> (1)` instead. Therefore: `files upload` does NOT pre-create the destination directory; use `files mkdir [-p]` first if the parent doesn't exist yet.
### 2. GET `/api/resources/<file>` (no trailing slash) returns HTTP 500
The backend's single-file `List` handler tries to slurp file bytes into a JSON envelope and chokes on most files. Workaround baked into the CLI: `Stat` always lists the PARENT directory and finds the leaf in the items array. If the user reports `HTTP 500` on a direct file resource path, the answer is "use `files cat` / `files download`", never "retry the raw URL".
### 3. `external/<node>/` is a virtual volume-listing layer (read-only)
This level has no backing filesystem — it just enumerates attached volumes (`hdd1`, `usb1`, `smb-...`). Writes against it either fail server-side or trip quirk #1.
CLI client-side guards: `mkdir`, `cp` destination, `mv` destination, `upload`, AND `share` (all flavors) reject `external/<node>/` (and one level deeper for `mkdir`). Errors point at the corrected shape `external/<node>/<volume>/<sub>/`. Pure reads (`ls`, `cat`, `rm`, `rename`) DO work — that's how the user discovers what volumes are attached. Mount new volumes via LarePass, not via files-backend mkdir.
### 4. `drive/Home/{Pictures, Music, Movies, Downloads, Documents, Code, Cache, Data, Home, Ollama, Huggingface}` are system-managed
These eleven names under `drive/Home/` are LarePass bootstrap directories that user apps look up by exact name (e.g. the model-runtime app's `Ollama` cache, the LarePass UI's "Pictures" sidebar tile). The LarePass GUI greys out cut / copy / paste / delete / rename for them, and so does the CLI:
- `rename`, `rm`, and `mv source` REFUSE these names at the **first level under `drive/Home/` only**.
- `cp` (copy) is intentionally NOT gated — duplicating bytes (e.g. `cp -r drive/Home/Pictures/ drive/Home/Pictures-Backup/`) preserves the original and is fine.
- Content nested inside (`drive/Home/Pictures/Trip2024/`) is fully editable.
- Other namespaces (`drive/Data/Pictures`, `sync/<repo>/Pictures`, `external/...`) are unaffected.
Note LarePass casing: `Huggingface` is one word (not `HuggingFace`). Names are case-sensitive.
### 5. `cache/<node>/` is a node-picker for share-create only
`cache/<node>/` IS a real per-node directory on the wire, so `ls` / `cp` / `mkdir` / `upload` / `rm` / `rename` work fine. BUT the share-create flavors (`share internal` / `share public` / `share smb`) reject the bare node root because a share record on the node-picker layer points at no concrete dataset. Use `cache/<node>/<sub>/` for shares; `files ls cache/<node>/` for discovery.
## Authentication transport
Every files API call carries `X-Authorization: <access_token>` (NOT `Authorization: Bearer ...`). The transport auto-refreshes expired tokens transparently — reactive on 401/403 for replayable requests (every verb except `upload`), pro-active JWT-exp pre-flight for streaming `upload` chunks (because once an `*os.File` chunk is consumed it can't be replayed). Concurrent goroutines and processes serialize on a single `/api/refresh`.
**On `*ErrTokenInvalidated` / `*ErrNotLoggedIn`, do not retry — only `profile login` / `profile import` will help.** See [`../olares-shared/SKILL.md`](../olares-shared/SKILL.md) for the full recovery table.
## Verb index
For flags, examples, and wire shapes, **always start with `olares-cli files <verb> --help`**. The references below add only what `--help` cannot give — agent-facing safety constraints, multi-step orchestrations, and common-error → fix maps.
| Verb | `--help` first, then... | Notes |
|---|---|---|
| `ls` | [references/olares-files-ls.md](references/olares-files-ls.md) | Drive vs. cloud envelope shapes; `--json` semantics |
| `cat` | `olares-cli files cat --help` | Trivial GET to stdout; binary-safe |
| `download` | [references/olares-files-download.md](references/olares-files-download.md) | `--resume` / `--overwrite` semantics; directory parallel fetch |
| `upload` | [references/olares-files-upload.md](references/olares-files-upload.md) | Two-stage cloud upload (stage 1 chunks → stage 2 server-side transfer task); `--parallel` semantics; tencent rejection |
| `edit` | [references/olares-files-edit.md](references/olares-files-edit.md) | Editor cascade; three-tier size cap; text-only guard; concurrent-delete detection; cloud writeback gap |
| `mkdir` | [references/olares-files-mkdir.md](references/olares-files-mkdir.md) | `-p` skips existing prefixes; auto-rename quirk on the leaf; `external/<node>/<X>/` depth-1 guard |
| `rm` | [references/olares-files-rm.md](references/olares-files-rm.md) | Preflight existence check before prompt; trailing-slash signals dir; protected-names list |
| `rename` | [references/olares-files-rename.md](references/olares-files-rename.md) | In-place only (synchronous PATCH); protected-names list; bare basename only |
| `cp` / `mv` | [references/olares-files-cp-mv.md](references/olares-files-cp-mv.md) | Drop-into-dir semantics; `mv` source rejects protected names; preflight Stat of every src + dst dir |
| `chown` | [references/olares-files-chown.md](references/olares-files-chown.md) | UID 0 / 1000 conventions; namespace allow-list; volume-root refusal |
| `share` | [references/olares-files-share.md](references/olares-files-share.md) | Three flavors (internal / public / smb); directory-only; per-flavor namespace allow-list; update verbs (`set-members` / `set-password` / `set-smb`) |
| `smb` | [references/olares-files-smb.md](references/olares-files-smb.md) | Mount → `external/<node>/<entry>/`; host-only address triggers share discovery; favorites history |
| `repos` | `olares-cli files repos --help` | List / create / rename / rm Seafile libraries; repo_id is the `<extend>` segment |
## Common errors (cross-verb)
| Error fragment | Meaning | Fix |
|---|---|---|
| `is the volume listing layer (read-only); point at a real volume, e.g. external/<node>/<volume>/<sub>/` | Quirk #3 — bare `external/<node>/` write attempt | Add the `<volume>` segment |
| `refusing to mkdir external/<node>/<X>/: depth-1 entries under external/<node>/ are mounted volumes` | Quirk #3 depth-1 — would create a phantom volume | Mount the volume via LarePass; target an existing one |
| `refusing to {rename\|delete\|mv source} drive/Home/<name>: this is a system-managed Home folder` | Quirk #4 — protected name | Pick a different name, or operate on a nested path |
| `refusing to share cache/<node>/: this is the node-picker layer (no concrete dataset to share)` | Quirk #5 — bare cache node-root share | Use `cache/<node>/<sub>/` |
| `file disappeared between stat and fetch` | Concurrent-delete race on `edit` | Re-pull the parent directory and decide |
| `tencent upload is not supported` (or similar) | Tencent's octet protocol is not implemented | Use the LarePass web app for tencent uploads |
| `<src> does not exist on the server` (from `cp`/`mv`/`rm`) | Preflight Stat failed | `files ls` the parent and confirm the path |
| `HTTP 500` from `/api/resources/<file>` | Quirk #2 — backend tried to embed file bytes | Use `files cat` / `files download` instead |
For auth-related errors (`server rejected the access token`, `refresh token for X became invalid`, …) see [`../olares-shared/SKILL.md`](../olares-shared/SKILL.md).
## Safety contract
- **Write & delete verbs** (`rm`, `rename`, `cp`, `mv`, `chown --uid`, `share rm`, `repos rm`, `smb unmount`) — confirm intent with the user FIRST. Several verbs preflight against the server before any state change; do not bypass that by retry-on-404.
- **`rm -f` skips the y/N prompt but NOT the preflight existence check** — a missing path still aborts.
- **Never echo `access_token` / `refresh_token` to the terminal.** Use `--password-stdin` (where supported) for SMB passwords too.
- **Confirm destination paths** before any `upload --overwrite`, `cp` to an existing file, or any operation that could clobber bytes.
don't have the plugin yet? install it then click "run inline in claude" again.
use olares-files to manage remote files on an Olares system via the command line. covers every major operation: listing, uploading, downloading, editing, creating/deleting directories, copying, moving, renaming, changing ownership, sharing folders (internal, public with password/expiry, or SMB), mounting external SMB servers, and managing Sync (Seafile) libraries. scope is always the active Olares ID's per-user files-backend. use this skill when the user mentions Olares, an Olares ID, drive volumes (Home/Data), sync repos, cache, external storage, cloud integrations (S3/Dropbox/Google/Tencent), uploading/downloading/listing/editing remote files, POSIX ownership, cross-user folder sharing, public links, SMB shares, or Sync libraries.
olares-cli must be in $PATH. install via your Olares bootstrap process.olares-cli profile list to check; run olares-cli profile login <olares-id> if needed. see the shared auth rules in ../olares-shared/SKILL.md.ErrTokenInvalidated or ErrNotLoggedIn, you must run olares-cli profile login or olares-cli profile import again.smb mount, you may need SMB username/password. use --password-stdin to avoid echoing to the terminal.awss3, google, dropbox, tencent operations, the keys must be registered in the Olares files-backend first (via LarePass web UI). the CLI references them by account key (the <extend> segment).files edit, the CLI cascades through $VISUAL → $EDITOR → nano → vi. set $EDITOR if you have a preference.input: none
action: check active olares profile and login status.
olares-cli profile list
if no profile is active or you see auth errors, log in:
olares-cli profile login <olares-id>
output: active profile displayed; access token acquired and stored securely.
input: target resource on the files-backend
action: construct the path as <fileType>/<extend>[/<subPath>].
| segment | meaning | examples |
|---|---|---|
fileType |
storage class (lowercase, case-sensitive) | drive, cache, sync, external, awss3, dropbox, google, tencent, share, internal |
extend |
volume/repo/account inside that class (case-sensitive) | Home, Data (drive only); <repo_id> (sync); <node_name> (cache/external); <account_key> (cloud) |
subPath |
path inside extend (root if omitted, leading / implicit) |
Documents/report.pdf, notes/, empty string for root |
examples:
drive/Home/Documents/report.pdf (file in home drive)drive/Data/ (data volume root)sync/<repo_id>/notes/ (directory in a Sync repo)external/node1/hdd1/videos/ (external volume on a node)awss3/<account>/mybucket/key.txt (cloud object)output: validated 3-segment path ready for verb application.
input: the verb you want to run (e.g., upload, edit, share)
action: cross-reference the verb against its supported namespaces.
| verb | supported namespaces |
|---|---|
ls, cat, download, rm, rename |
drive, cache, sync, external, awss3, google, dropbox, tencent |
edit |
drive, sync, cache, external only (cloud and tencent refused) |
mkdir |
drive, cache, sync, external, awss3, google, dropbox, tencent |
cp, mv |
same as mkdir |
upload |
drive/Home, drive/Data, sync/<repo_id>, cache/<node>, external/<node>/<volume>, awss3, google, dropbox (tencent rejected) |
chown |
drive/Home, drive/Data, cache/<node> only |
share internal |
drive, sync, external, cache (cloud refused) |
share smb |
drive, external, cache (sync and cloud refused) |
share public |
drive only |
smb mount/unmount/history |
keyed by <node> and <smb-url>, not frontend paths |
repos |
Sync library catalog (not frontend paths) |
output: confirmed that your verb supports your target namespace.
input: path string
action: decide whether a trailing / is needed.
| form | meaning | when to use |
|---|---|---|
drive/Home/Foo/ |
directory intent | rm -r, mkdir, upload INTO, cp/mv INTO directory, ls |
drive/Home/Foo |
file intent | cat, download, upload AS, rename, rm (file) |
rules:
files rm drive/Home/Foo/ requires -r (trailing / declares this is a directory).files upload <local> drive/Home/Documents/ → upload INTO Documents; files upload <local> drive/Home/Documents/report.pdf → upload AS that exact file.files cp <src> <dst>/ and files mv <src> <dst>/ , <dst> MUST end with / (drop-into-directory mode). in-place rename uses files rename instead.files cp -r drive/Home/old/ (trailing / on source) requires -r.files ls drive/Home/ lists volume root; both drive/Home and drive/Home/ accepted, but slash recommended.output: path with correct trailing slash for intended operation.
input: any verb that modifies state (rm, rename, cp, mv, chown, share rm, repos rm, smb unmount)
action: ask the user to confirm the operation before executing. several verbs preflight against the server before any change; respect that check.
example:
user: delete my old backup
you: about to rm -r drive/Data/backup-2023/. confirm? [y/N]
user: y
output: user confirms intent; proceed with the verb.
input: validated path, confirmed verb, user intent
action: execute olares-cli files <verb> <args>. always start with --help if uncertain about flags.
common verbs (see references for full details):
olares-cli files ls drive/Home/Documents/
olares-cli files ls --json sync/<repo_id>/ # json envelope
olares-cli files upload /local/report.pdf drive/Home/Documents/
olares-cli files upload /local/report.pdf drive/Home/Documents/report.pdf # explicit name
olares-cli files upload --parallel 4 /local/bigfile.zip drive/Data/
note: tencent upload is not supported; use LarePass web for tencent.
olares-cli files download drive/Home/report.pdf /local/report.pdf
olares-cli files download --overwrite drive/Home/report.pdf /local/report.pdf
olares-cli files download --resume drive/Home/bigfile.zip /local/bigfile.zip
olares-cli files edit drive/Home/notes.txt
opens file in $EDITOR (or cascade: $VISUAL → nano → vi). write-back is automatic on save. 3-tier size cap: 256 KB default, 1 MB with --large, 10 MB with --huge. text-only guard enforced.
olares-cli files mkdir drive/Home/NewFolder/
olares-cli files mkdir -p drive/Home/a/b/c/ # create parents if missing
note: -p skips existing prefixes; auto-rename quirk applies to the leaf (if exists, creates NewFolder (1)).
olares-cli files rm drive/Home/report.pdf # file
olares-cli files rm -r drive/Home/OldFolder/ # directory (requires /)
olares-cli files rm -f drive/Home/report.pdf # skip prompt (still preflights existence)
protected names at drive/Home/<name> refuse deletion: Pictures, Music, Movies, Downloads, Documents, Code, Cache, Data, Home, Ollama, Huggingface.
olares-cli files rename drive/Home/old_name.txt new_name.txt
in-place only (synchronous PATCH). refuses protected names. bare basename only (no path separators in new name).
olares-cli files cp drive/Home/source.txt drive/Home/Backup/ # drop into directory
olares-cli files cp -r drive/Home/OldFolder/ drive/Home/NewFolder/ # recursive copy
olares-cli files mv drive/Home/file.txt drive/Data/ # move into directory
mv source refuses protected names. destination MUST end with / (drop-into-dir mode). renaming uses files rename.
olares-cli files chown --uid 1000 drive/Home/report.pdf # set to user 1000
olares-cli files chown --uid 0 drive/Data/ # set to root
allowed namespaces: drive/Home, drive/Data, cache/<node>. UID conventions: 0 (root), 1000 (default user).
olares-cli files share internal add --member <other-olares-id> drive/Home/SharedFolder/
olares-cli files share internal set-members --add <id1> --add <id2> drive/Home/SharedFolder/
olares-cli files share internal rm drive/Home/SharedFolder/ # remove share
allowed namespaces: drive, sync, external, cache. directory-only.
olares-cli files share public add --password secret123 drive/Home/PublicData/
olares-cli files share public set-password --password newsecret drive/Home/PublicData/
olares-cli files share public set-expiration --expires 2026-12-31 drive/Home/PublicData/
olares-cli files share public rm drive/Home/PublicData/
allowed namespace: drive only. directory-only.
olares-cli files share smb add drive/Home/SmbShare/
olares-cli files share smb set-password --password smb123 drive/Home/SmbShare/
olares-cli files share smb rm drive/Home/SmbShare/
allowed namespaces: drive, external, cache. directory-only. note: cache/<node>/ (bare node-picker) refuses share creation; use cache/<node>/<sub>/.
olares-cli files smb mount --url smb://192.168.1.100/share --user admin drive/node1
olares-cli files smb mount --url smb://server.local/data --password-stdin drive/node1
olares-cli files smb unmount drive/node1 smb://192.168.1.100/share
olares-cli files smb history drive/node1 # list previously mounted shares
mounted volume appears at external/<node>/<entry>/. host-only addresses trigger share discovery.
olares-cli files repos list # all repos for active user
olares-cli files repos create --name MyLib # new repo
olares-cli files repos rename <repo_id> --name NewName
olares-cli files repos rm <repo_id>
repo_id becomes the <extend> segment for sync operations (e.g., sync/<repo_id>/notes/).
output: verb execution completes; state change (if any) applied to files-backend.
input: stdout/stderr from olares-cli
action: parse response and apply fixes.
common error → fix map:
| error | meaning | fix |
|---|---|---|
is the volume listing layer (read-only); point at a real volume, e.g. external/<node>/<volume>/<sub>/ |
bare external/<node>/ write attempt |
add <volume> segment |
refusing to mkdir external/<node>/<X>/: depth-1 entries under external/<node>/ are mounted volumes |
would create phantom volume | mount via LarePass; target existing volume |
refusing to {rename|delete|mv source} drive/Home/<name>: this is a system-managed Home folder |
protected name | pick different name or edit nested path |
refusing to share cache/<node>/: this is the node-picker layer (no concrete dataset to share) |
bare cache node-root | use cache/<node>/<sub>/ |
file disappeared between stat and fetch |
concurrent-delete race on edit | re-pull parent and decide |
tencent upload is not supported |
tencent protocol not implemented | use LarePass web UI |
<src> does not exist on the server |
preflight stat failed | files ls parent; confirm path |
HTTP 500 from /api/resources/<file> |
backend tried to embed file bytes | use files cat or files download |
server rejected the access token |
expired or invalid token | run olares-cli profile login again |
output: error resolved or user informed of the constraint.
input: operation result (success or expected error)
action: confirm the file state matches user expectation. for destructive ops, re-list the directory or re-stat the file.
example:
olares-cli files rm drive/Home/old_backup/
# user confirms delete
olares-cli files ls drive/Home/ # verify old_backup is gone
output: user confirms operation succeeded.
if the user asks to edit a cloud file (e.g., awss3, google, tencent), the verb will refuse. offer an alternative:
the backend's POST auto-renames on collision (quirk #1) but does NOT pre-create parents. decision:
files mkdir -p drive/Home/a/b/c/ first, then upload.--parent-create flag if available in your olares-cli version (check --help).quirk #2: the backend's single-file List handler fails on binary or large files. decision:
files cat to stdout (for inspection).files download to disk (for retrieval).quirk #4: these eleven names under drive/Home/ are protected: Pictures, Music, Movies, Downloads, Documents, Code, Cache, Data, Home, Ollama, Huggingface. decision:
drive/Home/Pictures/Trip2024/).cp -r drive/Home/Pictures/ drive/Home/Pictures-Backup/) if the user wants to preserve it.quirk #5: cache/<node>/ is a node-picker layer, not a concrete dataset. decision:
cache/<node>/<sub>/ for any share operation.ls and other reads against cache/<node>/ are allowed (for discovery).if ErrTokenInvalidated or