---
name: okfile
description: Deliver Agent artifacts, upload files, exchange private queue items, and publish static sites through an OkFile-compatible server.
---

# OkFile

## 30-Second Start (CLI)

CLI 2.17.0 starts DeepSeek chat when run as `okfile` with no command; `okfile chat` also defaults to AI mode. With no explicit server, environment, or saved configuration, it uses https://okfile.pckee.com, whose Go service supports email-code login and DeepSeek. Explicit server choices are preserved. In chat, a bare local file path means upload, `login EMAIL` / `登录 邮箱` use the same account flow, and `upgrade` / `升级` checks the selected server's wheel without downgrading. After a login-required oversized upload, successful login resumes the pending file. Older magic-link SaaS servers show browser/API-key instructions instead of a raw 404.

    export OKFILE_SERVER="https://hk.okfile.com"
    python -m pip install --upgrade "$OKFILE_SERVER/downloads/okfile-2.17.0-py3-none-any.whl"
    okfile config --server https://hk.okfile.com
    okfile upload ./file.png
    okfile publish ./my-site/

Use this skill when a user asks to publish a local file, return a shareable link, or publish a static site folder.

Set OKFILE_SERVER to the selected server, for example:

    export OKFILE_SERVER="http://your-internal-server:8080"
    export OKFILE_API_KEY="okf_..."

The API key is optional. The same client can target the hosted service by setting OKFILE_SERVER to https://www.okfile.com.

## Agent automation (CLI 2.17.0)

Prefer the CLI when it runs in the environment containing the file. Pass the selected server explicitly or use OKFILE_SERVER; changing global configuration is unnecessary for a single task. A remote MCP cannot read a local path without a client that can access that file.

    okfile upload ./report.pdf --server "$OKFILE_SERVER" --json --idempotency-key TASK_UUID
    okfile download DOWNLOAD_URL --server "$OKFILE_SERVER" -o ./report.pdf --json

Generate a random task key once and persist it in the Agent's task record before the first upload. Reuse it only for retries of the same file and options. The key must be 16–128 printable ASCII characters without spaces. First discover uploadIdempotency.supported; unsupported servers fail explicitly. Ordinary uploads without a key remain independent deliveries.

With a task key, the CLI uses prepare even for small files and computes a complete source SHA-256 before uploading. Completed retries return the original ID with idempotentReplay=true. Changed content (even with the same name and size) or options return IDEMPOTENCY_CONFLICT; expired/cancelled tasks return IDEMPOTENCY_EXPIRED. Do not automatically choose a new key after these errors. For encrypted delivery, encrypt once and upload the resulting ciphertext with a task key; inline encryption with task keys is rejected because fresh ciphertext is randomized.

Success and failure use one JSON object on stdout when --json is set; progress goes to stderr. Check both the exit code and success. Errors include code, message, retryable, retryAfterSeconds, requestId, hint, status and action. Download success includes path, size, sha256 (the local output's digest), and elapsedSeconds. Authentication errors stop immediately.

For Agent-to-Agent work, use queue create, upload --queue, queue claim --download --json, then queue ack --json only after the processing result is durably saved. Renew a long-running lease; a crashed worker's lease can expire and be reclaimed. Claiming/downloading does not acknowledge processing. Queue creation returns scoped secrets once: keep them out of shared logs and give each worker only the needed role. Use environment credentials rather than command-line secrets. See GET $OKFILE_SERVER/api/upload/queue-docs for details.

## File upload

1. Call GET $OKFILE_SERVER/api/upload/config.
2. For a file at or below quickUploadMaxSize, send multipart form field file to POST /api/upload/quick.
3. For a larger file, send filename, size, contentType, and optional preferredPartSize to POST /api/upload/prepare.
4. When mode is single, PUT the exact bytes to uploadUrl and call POST /api/upload/complete with id and the optional response ETag.
5. When mode is multipart, upload every entry in parts using its uploadUrl. Send the returned partNumber/ETag pairs to POST /api/upload/complete. If complete returns missingParts, upload only those parts and retry complete.
6. Return url for inline viewing and downloadUrl when download behavior is requested.

Send X-API-Key when OKFILE_API_KEY is set. Optional upload fields are expiresAt (RFC 3339), maxDownloads (positive integer), burnAfterRead (boolean), and storage (one of upload/config storage.profiles[].id). Omit storage to use the server default. For quick upload, send storage as a multipart form field; for prepare, send it as a JSON field.

### Resume, cancel and checksums

CLI 2.15.0 persists transfer state automatically, uses parallel direct downloads, and detects password-encrypted files. In an interactive rerun, a matching unfinished task prompts for resume; scripts default to resume. Use `okfile upload PATH --resume`, `--restart`, `--mode sequential`, `--checksum sha256`, and `okfile cancel PATH`. Ctrl+C pauses and keeps state. The new server uses persistent prepare tasks for small files too. See the CLI recovery guide in the project documentation.

Read GET /api/upload/docs for the complete OkFile extension contract. Save prepare's id, uploadToken and uploadExpiresAt. GET /api/upload/status/{id} returns missingParts and parts[] (number, expectedSize, size, ETag, checksum and uploadUrl); uploadedParts remains a count. Resume only missing parts. bytesReceived is a sum, not a continuous byte offset.

Cancel unfinished uploads with DELETE /api/upload/session/{id} and Upload-Token, or the owning X-API-Key. A completed file cannot be cancelled. Expired/cancelled sessions return 410 and must be recreated. Upload session expiry is separate from the completed file's expiresAt.

PUT and PATCH accept Upload-Checksum: sha256 BASE64_DIGEST (sha1 is also supported). The digest covers the original bytes of this request; for quick upload it covers the file field only. A mismatch returns 422 CHECKSUM_MISMATCH without replacing a valid part or advancing the sequential offset. Store checksums separately from provider ETags.

### Sequential byte uploads

When config.sequential.supported is true, prepare with mode=sequential and size. HEAD uploadUrl returns Upload-Offset. PATCH uploadUrl using Content-Type: application/partial-upload and Upload-Offset at that confirmed position. Respect maxAppendSize. Query HEAD after an interruption or 409, then resume from the server offset. Unchecked interrupted requests may save their received prefix; checked requests commit only after full checksum verification.

Complete using POST /api/upload/complete, or Upload-Complete: ?1 in the final PATCH. If the final response is lost, query status and replay complete. Unknown-size streams use size=0 and deferLength=true; declare Upload-Length once known or finish using Upload-Complete: ?1. These are OkFile extensions, not a claim of full tus/IETF compatibility.

Quick example:

    curl -X POST "$OKFILE_SERVER/api/upload/quick" \
      -H "X-API-Key: $OKFILE_API_KEY" \
      -F "file=@report.pdf"

## Static Site Hosting

1. Enumerate every file below the folder with its relative path, byte size, and content type.
2. Call POST /api/site/prepare with siteName, optional entryPath, and files.
3. Upload every file through the normal file API.
4. Call POST /api/site/complete with siteId, siteToken, and relativePath/fileId entries.
5. Return the resulting siteUrl.

Do not synthesize an index file. If the folder has no root index.html, omit entryPath; the server returns a directory listing.

## Limits and behavior

- Always discover limits from /api/upload/config.
- Uploads larger than multipartThreshold use resumable multipart uploads when multipart.supported is true.
- Anonymous files expire after the server-configured period and have a download cap.
- API-key uploads persist unless expiresAt is supplied.
- /d/{id} counts against maxDownloads; /i/{id} is the inline/raw URL.
- Hosted video transcoding is advertised as unsupported by the Go server. Upload video as a normal file.

## Errors

API errors are JSON objects with `success=false`. Read `code` for stable program logic, display `message` (or legacy `error`) to the user, and retain `requestId` for server log lookup.

Only retry when `retryable=true`, a network request fails, or an intermediary returns HTTP 429/502/503/504. Honor `retryAfterSeconds` or the `Retry-After` header. Do not retry request, authentication, permission, missing-resource, or payload-limit failures without changing the request.

An error can also include `action`, `hint`, `docs`, and operation-specific recovery fields. For `MULTIPART_INCOMPLETE`, upload only `missingParts`, retain successful part ETags, and retry complete. The server echoes a valid inbound `X-Request-ID` or generates one in both the response header and body.

Example:

    {
      "success": false,
      "error": "Storage is temporarily unavailable",
      "message": "Storage is temporarily unavailable",
      "code": "STORAGE_UNAVAILABLE",
      "retryable": true,
      "retryAfterSeconds": 5,
      "action": "retry",
      "hint": "Retry later and provide requestId to the administrator if it persists.",
      "requestId": "req_8x2k19",
      "timestamp": "2026-10-12T06:00:00Z",
      "docs": "/SKILL.md#errors"
    }

文件密码：CLI `okfile upload FILE --password`（隐藏输入）或 `--password-env NAME`。prepare JSON / quick 表单使用 `password` 字段；先检查 `passwordProtection.supported`，并确认 `passwordProtected=true`。分享 URL 不带密码，收件人在浏览器输入后下载；下载、预览、raw 与 Range 都受保护。详情见 `docs/PASSWORD_PROTECTION.md`。

命令指南与测试场景：https://hk.okfile.com/guide 。CLI 2.17.0 会在上传和下载进度中显示实际并行数量，提供中英文 UTF-8 提示，并支持加密密码只输入一次、并行直连下载、自动识别密码加密文件、queue create/files/claim/ack/renew/release/key、upload --queue 与 download --queue。队列文件使用 X-API-Key，work 下载另外发送 Queue-Receipt；不要把凭据放进 URL。

For upload or download completion email, add --notify-email EMAIL; requires configured server email and a valid API key or queue credential. Only notify after successful local decryption.
