Seafile

Other

Search, download, and upload files in a single Seafile library using a repo token. Use when an agent needs library-scoped filename or path search, exact-path downloads, or uploads into a Seafile library via the repo-token API.

Install

openclaw skills install seafile

Seafile Skill

Overview

Use this skill to interact with one Seafile library through the repo-token API. It is designed for three tasks only:

  • Search for files or folders by filename or path fragment inside the token's library scope
  • Download a file by exact Seafile path
  • Upload a local file into an existing Seafile directory

This skill does not cover full-text content search, cross-library discovery, deletes, renames, moves, or share-link management.

For endpoint details, see references/seafile-api.md. For reusable shell patterns, see references/command-patterns.md.

Prerequisites

Required:

  • curl
  • jq
  • Network access to the Seafile server
  • SEAFILE_BASE_URL
  • SEAFILE_REPO_TOKEN with access to the target library

Optional with defaults:

  • SEAFILE_LIBRARY_ROOT, which defaults to /
  • SEAFILE_OUTPUT_DIR, which is only needed when saving downloaded files locally

Export the required variables before running commands. The optional variables below are shown with their recommended defaults:

export SEAFILE_BASE_URL="https://seafile.example.com"
export SEAFILE_REPO_TOKEN="<repo-token>"
export SEAFILE_LIBRARY_ROOT="/"        # optional
export SEAFILE_OUTPUT_DIR="$PWD/downloads"  # optional, used for downloads
mkdir -p "$SEAFILE_OUTPUT_DIR"

Defaults and expectations:

  • SEAFILE_BASE_URL should be the server origin without a trailing slash
  • SEAFILE_LIBRARY_ROOT defaults to / if you do not override it
  • SEAFILE_OUTPUT_DIR is only needed for downloads
  • All Seafile paths in this skill are absolute library paths such as /, /docs, or /docs/report.pdf

Authentication

The repo-token endpoints use the repo token in the Authorization header. Use this default form unless your deployment documents a different token scheme:

AUTH_HEADER="Authorization: Token $SEAFILE_REPO_TOKEN"
API_BASE="${SEAFILE_BASE_URL%/}/api/v2.1/via-repo-token"

Before doing search, download, or upload, verify the token and library scope:

curl --fail --silent --show-error \
  -H "$AUTH_HEADER" \
  "$API_BASE/repo-info/" | jq

If this fails with 401 or 403, stop and fix the token, permissions, or server URL before continuing.

Search Workflow

Use repo-token directory listing and filter locally with jq. This is filename and path search, not full-text search.

1. List items from a starting path

START_PATH="${SEAFILE_LIBRARY_ROOT:-/}"

curl --fail --silent --show-error \
  -G \
  -H "$AUTH_HEADER" \
  --data-urlencode "path=$START_PATH" \
  --data-urlencode "recursive=1" \
  "$API_BASE/dir/"

Useful query parameters:

  • path: directory to inspect, default /
  • recursive=1: walk the subtree recursively
  • type=f: files only
  • type=d: directories only

2. Filter by filename fragment

NEEDLE="report"
START_PATH="${SEAFILE_LIBRARY_ROOT:-/}"

curl --fail --silent --show-error \
  -G \
  -H "$AUTH_HEADER" \
  --data-urlencode "path=$START_PATH" \
  --data-urlencode "recursive=1" \
  "$API_BASE/dir/" |
  jq -r --arg needle "$NEEDLE" '
    .dirent_list[]
    | select((.name // "") | ascii_downcase | contains($needle | ascii_downcase))
    | [.type, .parent_dir, .name]
    | @tsv
  '

3. Filter by full path fragment

PATH_FRAGMENT="2026/q2"
START_PATH="${SEAFILE_LIBRARY_ROOT:-/}"

curl --fail --silent --show-error \
  -G \
  -H "$AUTH_HEADER" \
  --data-urlencode "path=$START_PATH" \
  --data-urlencode "recursive=1" \
  "$API_BASE/dir/" |
  jq -r --arg needle "$PATH_FRAGMENT" '
    .dirent_list[]
    | (.parent_dir + "/" + .name | gsub("//+"; "/")) as $full_path
    | select($full_path | ascii_downcase | contains($needle | ascii_downcase))
    | [$full_path, .type]
    | @tsv
  '

When you need exact metadata for one known file path, consult the repo-token file-info section in references/seafile-api.md and confirm the route shape against the target deployment if needed.

Download Workflow

Downloads are exact-path only. SEAFILE_OUTPUT_DIR is optional overall and only matters if you want this skill to save the downloaded file to a local directory.

1. Request a one-time download link

REMOTE_FILE="/docs/report.pdf"

DOWNLOAD_LINK=$(curl --fail --silent --show-error \
  -G \
  -H "$AUTH_HEADER" \
  --data-urlencode "path=$REMOTE_FILE" \
  "$API_BASE/download-link/" |
  jq -r '.')

2. Download the file to a local path

LOCAL_FILE="$SEAFILE_OUTPUT_DIR/$(basename "$REMOTE_FILE")"

curl --fail --silent --show-error --location \
  "$DOWNLOAD_LINK" \
  -o "$LOCAL_FILE"

Notes:

  • download-link/ returns a URL string, not a JSON object
  • Use --location because the returned URL may redirect
  • Keep the remote path exact, including spaces, case, and file extension

Upload Workflow

Uploads send a local file into an existing Seafile directory.

1. Request an upload link

UPLOAD_LINK=$(curl --fail --silent --show-error \
  -H "$AUTH_HEADER" \
  "$API_BASE/upload-link/" |
  jq -r '.')

2. Upload one local file

LOCAL_FILE="./artifact.zip"
TARGET_DIR="/incoming"

curl --fail --silent --show-error \
  -F "file=@${LOCAL_FILE}" \
  -F "parent_dir=${TARGET_DIR}" \
  -F "replace=0" \
  "${UPLOAD_LINK}?ret-json=1" |
  jq

Upload behavior:

  • parent_dir must be an absolute library path like /incoming
  • replace=1 overwrites an existing file with the same name
  • replace=0 preserves the existing file and lets Seafile rename the new upload if needed
  • ?ret-json=1 returns structured JSON and should be used by default

If you need Seafile to create nested folders beneath an existing parent, add -F "relative_path=subdir1/subdir2/" to the upload request.

Error Handling

Check failures in this order:

  • 401 or 403 The token is missing, expired, malformed, or does not allow the requested action.
  • 404 The base URL or endpoint is wrong, or the server is not exposing that API path.
  • 440 or similar upload validation errors The filename is invalid for the target server.
  • 442 or 443 The file is too large or the library is out of quota.
  • Directory listing or download returns no match Re-check the starting directory, exact remote path, and case sensitivity.
  • Upload succeeds but lands in the wrong place Re-check parent_dir and any relative_path value.

When a request is failing and the server output is unclear, remove --silent temporarily and inspect headers with curl -i.

Examples

Find files matching a name fragment

NEEDLE="invoice"
START_PATH="/finance"

curl --fail --silent --show-error \
  -G \
  -H "Authorization: Token $SEAFILE_REPO_TOKEN" \
  --data-urlencode "path=$START_PATH" \
  --data-urlencode "recursive=1" \
  --data-urlencode "type=f" \
  "${SEAFILE_BASE_URL%/}/api/v2.1/via-repo-token/dir/" |
  jq -r --arg needle "$NEEDLE" '
    .dirent_list[]
    | select((.name // "") | ascii_downcase | contains($needle | ascii_downcase))
    | (.parent_dir + "/" + .name | gsub("//+"; "/"))
  '

Download one file by exact path

REMOTE_FILE="/finance/invoices/april-2026.pdf"
DOWNLOAD_LINK=$(curl --fail --silent --show-error \
  -G \
  -H "Authorization: Token $SEAFILE_REPO_TOKEN" \
  --data-urlencode "path=$REMOTE_FILE" \
  "${SEAFILE_BASE_URL%/}/api/v2.1/via-repo-token/download-link/" |
  jq -r '.')

curl --fail --silent --show-error --location \
  "$DOWNLOAD_LINK" \
  -o "$SEAFILE_OUTPUT_DIR/april-2026.pdf"

Upload one local file into a target folder

TARGET_DIR="/incoming/reports"
LOCAL_FILE="./build/report.csv"
UPLOAD_LINK=$(curl --fail --silent --show-error \
  -H "Authorization: Token $SEAFILE_REPO_TOKEN" \
  "${SEAFILE_BASE_URL%/}/api/v2.1/via-repo-token/upload-link/" |
  jq -r '.')

curl --fail --silent --show-error \
  -F "file=@${LOCAL_FILE}" \
  -F "parent_dir=${TARGET_DIR}" \
  -F "replace=1" \
  "${UPLOAD_LINK}?ret-json=1" |
  jq