面向 AI Agent 与人类的安全临时文件共享工具
英文标题:🔶 Secure temporary file sharing for AI agents and humans
aispace.sh 推出了一款面向 AI Agent 和人类协作的临时文件共享 CLI,支持过期链接、稳定 JSON 输出、流式上传及可选的本地 age X25519 加密。该开源客户端强调自动化能力,提供固定退出码、stdin 输入、无交互式提示和可预测的最终 URL 输出,适合 Agent、Shell 脚本与 CI 工作流。服务支持私有文件、账户内共享、可撤销的公开链接、下载次数上限,以及 Pro 账户的最长 30 天文件与链接期限。项目还提供兼容 Codex 的 skill、OpenAI/Anthropic 工具 schema 和 Python 参考处理程序,便于接入自定义 Agent 运行时。
32.2 KB
42.5 KB
中文
面向 AI Agent 与人类的安全临时文件共享。
一个可编写脚本调用的 CLI,提供会过期的链接、可预测的 JSON,以及可选的本地 age 加密。
aispace.sh 是一个对 Bot 友好的文件投递服务,适用于那些对聊天而言过大、结构化或仅需临时保存的输出。其开源客户端专为自动化而设计:一个二进制文件、稳定的退出码、流式上传,以及在可预测的最后一行输出分享 URL。
- **为 Agent 构建:**精确的 JSON 输出、文档化的错误信息、stdin 支持,以及自动化流程中没有交互式提示。
- **天生短生命周期:**支持文件过期、单独设置链接过期、撤销以及可选的单链接下载次数上限。
- **需要时保持私密:**支持经认证的账户交接和本地 age X25519 加密;解密身份密钥绝不会传送至 aispace。
托管服务独立运营。本仓库包含客户端、Agent skill 和集成示例——不包含服务器、计费系统、部署配置或客户数据。
安装最新版本:
curl -fsSL https://aispace.sh/install.sh | sh
使用在 aispace 控制台创建的密钥进行认证,然后存储文件:
aispace login --key ask_...
aispace upload report.pdf --json
在 Pro 账户中,可添加一个单独设置过期时间的公开交接链接:
aispace upload report.pdf --link --link-expires 1h --max-downloads 1
URL 会在最后一行单独输出,因此 Agent 或 Shell 脚本可以轻松捕获。添加 --json 可获得稳定、可供机器读取的响应。精简后的响应示例如下:
{"file":{"id":"...","name":"report.pdf"},"link":{"url":"https://aispace.sh/d/...","expires_at":1757003600}}
其他安装渠道:
npm install -g @aispace-sh/cli
brew install aispace-sh/tap/aispace
go install github.com/aispace-sh/aispace-client@latest
可通过 AISPACE_VERSION=v1.2.3 固定 Shell 安装器的版本。发布的二进制文件支持运行于 amd64 和 arm64 架构的 macOS、Linux 与 Windows。Shell 安装器支持 macOS 和 Linux;Windows 请使用 npm。
本仓库包含一个可复用、兼容 Codex 的 skill。克隆仓库,并将该 skill 链接到个人 Codex skills 目录:
git clone https://github.com/aispace-sh/aispace-client.git
mkdir -p ~/.codex/skills
ln -s "$PWD/aispace-client/skills/aispace" ~/.codex/skills/aispace
重启 Codex,然后在需要向你交付报告、归档文件、图像或其他生成产物时,要求它使用 aispace。该 skill 默认使用账户私有存储,除非你要求公开链接;它会优先采用较短的过期时间,并将加密身份密钥视作凭证。
对于自定义 Agent 运行时,docs/LLM_USAGE.md 提供系统提示词片段、兼容 OpenAI/Anthropic 的工具 schema,以及 Python 参考处理程序。可参阅 examples,获取可运行的 Shell、CI 与加密交接方案。
# Upload text from stdin and return an expiring public link (Pro).
echo "hello" | aispace upload - --name note.txt --link --link-expires 1h
# Keep a file available only to this key.
aispace upload secret.txt --private
# Share ciphertext; keep the generated age identity locally.
aispace upload secret.pdf --encrypt --identity-out secret.agekey --link
# Authenticated handoff to another key on the same account—no public URL.
aispace upload notes.md --shared --json
# Receive, manage, and revoke.
aispace ls --json
aispace download <file_id> --output ./file
aispace download <file_id> --output ./file --verify # check the recorded SHA-256
aispace link <file_id> --expires 30m --max-downloads 1
aispace revoke <link_id>
aispace rm <file_id>
完整命令参考见 docs/CLI.md;HTTP 协议约定见 docs/API.md。
upload 接受 --name、--expires、--content-type、--sha256、--link、--link-expires、--max-downloads、--private、--shared、--encrypt、--recipient 和 --identity-out 参数。上传会从磁盘流式读取。加密上传会在本地使用 age X25519,并将密文存储为 <name>.age;私密身份密钥绝不会发送到 API。
使用 --json 时,错误也会保持结构化并写入 stderr。upload --link --json 返回 {"file": File, "link": ShareLink};加密上传会额外加入一个 "encryption" 对象。
优先级:标志参数 > 环境变量 > 配置文件 > 默认值。
| 设置 | 标志参数 | 环境变量 | 文件键名 | 默认值 |
|---|---|---|---|---|
| API 密钥 | --key |
AISPACE_KEY |
key |
— |
| 服务器 | --url |
AISPACE_URL |
url |
https://aispace.sh |
当省略 decrypt --identity-file 时,AISPACE_AGE_IDENTITY 会提供解密身份密钥。该值被刻意禁止作为命令行参数传入。
配置文件:$XDG_CONFIG_HOME/aispace/config.json(默认值为 ~/.config/aispace/config.json),以 0600 权限模式写入。如果其他用户可读取此文件,程序会输出警告。AISPACE_CONFIG 可覆盖该路径。
时长参数(--expires、--link-expires)接受 Go 语法及 d 后缀:30m、24h、7d、1d12h,或纯数字形式的秒数。省略时将使用服务器默认值(文件为 7 天,链接为 1 小时)。
文件权限与链接
文件可见性控制经认证密钥的访问权限。公开链接是一项独立的能力:创建它需要 Pro 账户,并会让持有 URL 的任何人都可访问该单个文件。
| 文件模式 | 谁可以访问? | 文件生命周期 | 公开链接生命周期 | 下载上限 | 访问泄露时的暴露范围 |
|---|---|---|---|---|---|
private |
仅上传密钥 | 默认 7 天;Free 最长 7 天,Pro 最长 30 天 | 无 | 账户每月限额 | 该密钥所属的私有文件,直至删除或过期 |
account |
账户内每个活跃密钥 | 默认 7 天;Free 最长 7 天,Pro 最长 30 天 | 无 | 账户每月限额 | 账户共享文件,直至删除或过期 |
private + 公开链接 |
上传密钥和持有 URL 的任何人 | 因链接需要 Pro,最长 30 天 | 默认 1 小时;最长 30 天,且绝不超过文件过期时间 | 可选的单链接上限 | 仅该链接对应的文件,直至链接过期、被撤销、下载次数耗尽、文件删除或文件过期 |
account + 公开链接 |
账户密钥和持有 URL 的任何人 | 因链接需要 Pro,最长 30 天 | 默认 1 小时;最长 30 天,且绝不超过文件过期时间 | 可选的单链接上限 | URL 访问随链接结束;账户密钥仍可访问,直至文件删除或过期 |
| 客户端加密文件 | 可见性控制密文访问;仅 age 身份密钥持有者可解密 | 与所选文件模式相同的限制 | 创建链接时适用相同的 Pro 专属限制 | 可选的单链接上限 | 明文泄露须同时获得密文和 age 身份密钥 |
可用的时长语法包括 30s、15m、1h、36h 和 7d。
文件生命周期结束时,文件将不可用。链接可能因过期、被撤销或达到下载次数上限而更早失效。删除文件会立即终止经认证密钥的访问以及所有关联的公开链接。
| 代码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 通用错误(网络错误,以及未在下方列出的 4xx/5xx) |
| 2 | 使用错误 |
| 3 | 身份验证错误(401,或未配置密钥) |
| 4 | 配额 / 大小限制(402、413) |
| 5 | 速率受限(429)——幂等 GET 请求会等待 Retry-After(最长 30 秒)后重试一次 |
错误会以 error: <message> (<code>) 形式写入 stderr;使用 --json 时,则会在 stderr 输出 JSON 对象 {"error":{"code","message","status","details","exit_code"}}。
go test -race ./... && go vet ./... && test -z "$(gofmt -l .)"
go build -ldflags "-X main.version=0.0.0-dev" -o aispace .
(cd npm && npm test && npm pack --dry-run)
测试套件使用本地 HTTP fixture,无需 aispace 密钥。欢迎贡献——请从 CONTRIBUTING.md 开始,查看 ROADMAP.md,并审阅 CHANGELOG.md。针对性 Bug 报告和功能建议可使用仓库的结构化 Issue 表单提交。
版本通过手动运行 GitHub Actions 工作流进行发布。GoReleaser 会构建带校验和的 macOS、Linux 和 Windows 二进制文件,更新 Homebrew tap,并将 @aispace-sh/cli 发布到 npm。发布者配置和发布检查清单请见 RELEASE.md。
请通过 GitHub Security Advisories 私下报告漏洞。请勿创建包含凭证、私有链接或客户数据的公开 Issue。详见 docs/SECURITY.md。
English / 原文
Secure temporary file sharing for AI agents and humans.
A scriptable CLI with expiring links, predictable JSON, and optional local age encryption.
aispace.sh is a bot-friendly file drop for outputs that are too large, structured, or temporary for chat. The open-source client is deliberately easy to automate: one binary, stable exit codes, streaming uploads, and share URLs printed on a predictable final line.
- Built for agents: exact JSON output, documented errors, stdin support, and no interactive prompts in automated flows.
- Short-lived by design: file expiration, separately expiring links, revocation, and optional per-link download caps.
- Private when needed: authenticated account handoffs and local age X25519 encryption; the decryption identity never reaches aispace.
The hosted service is operated separately. This repository contains the client, agent skill, and integration examples—not the server, billing system, deployment configuration, or customer data.
Install the latest release:
curl -fsSL https://aispace.sh/install.sh | sh
Authenticate with a key created in the aispace dashboard, then store a file:
aispace login --key ask_...
aispace upload report.pdf --json
On a Pro account, add a separately expiring public handoff:
aispace upload report.pdf --link --link-expires 1h --max-downloads 1
The URL is printed last on its own line, making it easy for an agent or shell script to capture. Add --json for a stable machine-readable response. An abridged response looks like:
{"file":{"id":"...","name":"report.pdf"},"link":{"url":"https://aispace.sh/d/...","expires_at":1757003600}}
Other installation channels:
npm install -g @aispace-sh/cli
brew install aispace-sh/tap/aispace
go install github.com/aispace-sh/aispace-client@latest
Pin the shell installer with AISPACE_VERSION=v1.2.3. Release binaries support macOS, Linux, and Windows on amd64 and arm64. The shell installer supports macOS and Linux; use npm on Windows.
The repository includes a reusable Codex-compatible skill. Clone the repository and link the skill into your personal Codex skills directory:
git clone https://github.com/aispace-sh/aispace-client.git
mkdir -p ~/.codex/skills
ln -s "$PWD/aispace-client/skills/aispace" ~/.codex/skills/aispace
Restart Codex, then ask it to use aispace when it needs to hand you a report, archive, image, or other generated artifact. The skill defaults to account-private storage unless you request a public link, prefers short expirations, and treats encryption identities as credentials.
For custom agent runtimes, docs/LLM_USAGE.md includes a system-prompt snippet, OpenAI/Anthropic-compatible tool schemas, and a reference Python handler. See examples for runnable shell, CI, and encrypted-handoff recipes.
# Upload text from stdin and return an expiring public link (Pro).
echo "hello" | aispace upload - --name note.txt --link --link-expires 1h
# Keep a file available only to this key.
aispace upload secret.txt --private
# Share ciphertext; keep the generated age identity locally.
aispace upload secret.pdf --encrypt --identity-out secret.agekey --link
# Authenticated handoff to another key on the same account—no public URL.
aispace upload notes.md --shared --json
# Receive, manage, and revoke.
aispace ls --json
aispace download <file_id> --output ./file
aispace download <file_id> --output ./file --verify # check the recorded SHA-256
aispace link <file_id> --expires 30m --max-downloads 1
aispace revoke <link_id>
aispace rm <file_id>
The complete command reference is in docs/CLI.md; the HTTP contract is in docs/API.md.
upload accepts --name, --expires, --content-type, --sha256, --link, --link-expires, --max-downloads, --private, --shared, --encrypt, --recipient, and --identity-out. Uploads stream from disk. Encrypted uploads use age X25519 locally and store ciphertext as <name>.age; the secret identity is never sent to the API.
With --json, errors also remain structured and are written to stderr. upload --link --json returns {"file": File, "link": ShareLink}; encrypted uploads add an "encryption" object.
Precedence: flag > environment > config file > default.
| Setting | Flag | Env | File key | Default |
|---|---|---|---|---|
| API key | --key |
AISPACE_KEY |
key |
— |
| Server | --url |
AISPACE_URL |
url |
https://aispace.sh |
AISPACE_AGE_IDENTITY supplies a decryption identity when decrypt --identity-file is omitted. It is deliberately not accepted as a command-line value.
Config file: $XDG_CONFIG_HOME/aispace/config.json (default ~/.config/aispace/config.json), written with mode 0600. A warning is printed if the file is readable by others. AISPACE_CONFIG overrides the path.
Durations (--expires, --link-expires) accept Go syntax plus a d suffix: 30m, 24h, 7d, 1d12h, or a bare number of seconds. Omitting them uses the server defaults (7 days for files, 1 hour for links).
File permissions and links
File visibility controls authenticated key access. A public link is a separate capability: creating one requires a Pro account and makes that one file available to anyone holding the URL.
| File mode | Who can access it? | File lifetime | Public-link lifetime | Download cap | Exposure if access leaks |
|---|---|---|---|---|---|
private |
Uploading key only | 7 days by default; maximum 7 days on Free or 30 days on Pro | None | Account monthly limit | Private files belonging to that key, until deletion or expiry |
account |
Every active key on the account | 7 days by default; maximum 7 days on Free or 30 days on Pro | None | Account monthly limit | Account-shared files, until deletion or expiry |
private + public link |
Uploading key and anyone with the URL | Maximum 30 days because links require Pro | 1 hour by default; maximum 30 days and never beyond file expiry | Optional per-link cap | Only the linked file, until link expiry, revocation, exhaustion, file deletion, or file expiry |
account + public link |
Account keys and anyone with the URL | Maximum 30 days because links require Pro | 1 hour by default; maximum 30 days and never beyond file expiry | Optional per-link cap | URL access ends with the link; account keys retain access until file deletion or expiry |
| Client-encrypted file | Visibility controls ciphertext access; only age identity holders can decrypt it | Same limits as the selected file mode | Same Pro-only limits when a link is created | Optional per-link cap | Plaintext exposure requires both the ciphertext and the age identity |
Available duration syntax includes 30s, 15m, 1h, 36h, and 7d.
A file becomes unavailable when its file lifetime ends. A link can end sooner because it expired, was revoked, or reached its download cap. Deleting the file immediately ends authenticated key access and every associated public link.
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | generic error (network, 4xx/5xx not listed below) |
| 2 | usage error |
| 3 | authentication (401, or no key configured) |
| 4 | quota / size (402, 413) |
| 5 | rate limited (429) — idempotent GETs sleep Retry-After (max 30s) and retry once |
Errors go to stderr as error: <message> (<code>); with --json they are a JSON object {"error":{"code","message","status","details","exit_code"}} on stderr instead.
go test -race ./... && go vet ./... && test -z "$(gofmt -l .)"
go build -ldflags "-X main.version=0.0.0-dev" -o aispace .
(cd npm && npm test && npm pack --dry-run)
The test suite uses local HTTP fixtures and does not require an aispace key. Contributions are welcome—start with CONTRIBUTING.md, check the ROADMAP.md, and review the CHANGELOG.md. Focused bug reports and feature proposals can use the repository's structured issue forms.
Releases are cut through the manual GitHub Actions workflow. GoReleaser builds checksummed macOS, Linux, and Windows binaries, updates the Homebrew tap, and publishes @aispace-sh/cli to npm. See RELEASE.md for publisher configuration and the release checklist.
Please report vulnerabilities privately through GitHub Security Advisories. Do not open a public issue containing a credential, private link, or customer data. See docs/SECURITY.md.
