oss

GitHub

提供S3兼容对象存储的命令行操作能力,支持列表、读写、复制、移动、删除及生成预签名URL等文件管理功能。

internal/ai/skills/oss/SKILL.md opskat/opskat

触发场景

需要读取或写入云存储文件 管理OSS/S3桶内对象 生成临时访问链接

安装

npx skills add opskat/opskat --skill oss -g -y
更多选项

非标准路径

npx skills add https://github.com/opskat/opskat/tree/main/internal/ai/skills/oss -g -y

不安装直接使用

npx skills use opskat/opskat@oss

指定 Agent (Claude Code)

npx skills add opskat/opskat --skill oss -a claude-code -g -y

安装 repo 全部 skill

npx skills add opskat/opskat --all -g -y

预览 repo 内 skill

npx skills add opskat/opskat --list

SKILL.md

Frontmatter
{
    "name": "oss",
    "description": "List, read, upload, copy, move, delete and presign objects in S3-compatible object storage via exec, using a family + verb + target command syntax."
}

OSS assets

OSS assets connect to an S3-compatible object storage endpoint (AWS S3, MinIO, Aliyun OSS, …). The asset names the endpoint and credentials — the bucket is part of every command's target. An asset may also carry a default bucket (bucket in its config) for credentials scoped to one bucket; it never fills in a missing bucket in a target.

Command syntax

<family> <verb> [target] [--flags] — family is bucket or object, verb is the operation, and target is <bucket>/<key> (no leading slash).

Every example below is literally executable as written. Optional flags are not marked with brackets; each useful combination is spelled out on its own line.

bucket

  • bucket list

object

  • object list backups
  • object list backups/2026/
  • object list backups/2026/ --max-keys=100
  • object list backups/2026/ --max-keys=100 --after=2026/03/db.sql.gz
  • object stat backups/2026/db.sql.gz
  • object get backups/app.conf (returns the content inline, truncated to 64 KiB)
  • object get backups/app.conf --max-bytes=4096
  • object get backups/2026/db.sql.gz --file=/tmp/db.sql.gz (streams to a local file instead)
  • object put backups/2026/db.sql.gz --file=/tmp/db.sql.gz
  • object put backups/app.conf --file=/tmp/app.conf --content-type=text/plain
  • object copy backups/2026/db.sql.gz --to=archive/db-2026.sql.gz
  • object move backups/2026/db.sql.gz --to=archive/db-2026.sql.gz
  • object delete backups/2026/old.log
  • object presign backups/2026/db.sql.gz
  • object presign backups/2026/db.sql.gz --expiry=600
  • object presign uploads/inbox/report.pdf --method=put --expiry=600 (denied by the default policy, see Notes)

Flag reference

Every flag each verb accepts — anything else is rejected rather than ignored. Bold flags are required: omitting one does not default it, the command is rejected before it runs. Verbs not listed here take no flags at all.

  • object list: --max-keys, --after
  • object get: --file, --max-bytes
  • object put: --file, --content-type
  • object copy: --to
  • object move: --to
  • object presign: --expiry, --method

Flag values

Checked before any approval dialog, so a wrong value costs nothing:

  • --max-keys, --max-bytes and --expiry must be plain decimal integers: 1000, not 1,000, 1_000, 1e3 or 3.0.
  • --method is get or put, lower case exactly. Nothing else is accepted, and there is no case folding: GET is an error rather than a synonym. Omitting it means get, so a bare object presign requests object.presign.read.
  • --expiry defaults to 3600 seconds when omitted.
  • --file must be an absolute local path. The approved command string is all that identifies the file, and a relative path resolves against a working directory that is not part of it, so it would land somewhere unpredictable.
  • --file and --max-bytes cannot be given together: they select two different behaviors of object get (stream the whole object to disk, or return the first bytes inline), so one of them would have to be ignored.
  • --max-bytes defaults to 64 KiB and is capped at 1 MiB. A larger value is reduced to the cap rather than rejected, and truncated then reports that the object was longer.
  • --max-keys is capped at 1000. A larger value is rejected, not reduced: silently returning fewer keys than asked would break --after pagination against what the caller expected to page through.
  • --expiry is capped at 604800 seconds (7 days) and is also rejected rather than reduced: a longer-lived presigned URL is what S3-compatible backends refuse to sign in the first place, so a value over the cap would otherwise be approved and then fail.
  • --to is a second <bucket>/<key> and follows the same rules as the target, including the requirement that it name a single object.

Not checked on this side at all — the storage service is the only thing that will reject a wrong value, after approval and a round trip:

  • --content-type is passed through verbatim as the object's MIME type; omitting it lets the service decide.
  • --after is a continuation cursor, not a filter: pass back the nextContinuationToken from the previous object list result to read the next page.

Results

  • bucket list returns {"buckets":[…]}. On an asset with a default bucket it returns that one bucket without asking the storage service, since a bucket-scoped credential is not allowed to list the account's buckets.
  • object list returns the raw listing: prefixes (one level of "folders"), objects, plus isTruncated and nextContinuationToken for paging.
  • object stat returns the object's metadata.
  • object get without --file returns content together with encoding (utf-8, or base64 when the bytes are not valid UTF-8) and truncated. When truncated is true you read only the first bytes — re-run with --file rather than guessing at the rest.
  • object get --file returns the byte count, the object and the local file path; object put returns the byte count and the object (bucket/key), with no file. The content never passes through the conversation either way.
  • object copy, object move and object delete return {"status":"ok",…}.
  • object presign returns the signed url, its method and expiresIn seconds. The URL is fully usable. Under raw-by-default Audit the complete signed URL — signature parameters included — enters the Audit result unchanged, subject only to the existing result capture/truncation; nothing is redacted, so treat the URL as a capability that grants access until it expires.

Approval and policy rules

Approval is granted per <action> <resource>, where resource is <bucket>/<key>:

command permission(s) requested
bucket list bucket.list *
object list B/P object.list B/P
object stat B/K, object get B/K object.read B/K
object get B/K --file=P object.read B/K and a local-write check on P (the same gate cp uses when writing to this machine)
object put B/K object.write B/K
object copy S --to=D object.read S and object.write D
object move S --to=D object.read S, object.write D and object.delete S
object delete B/K object.delete B/K
object presign B/K --method=get object.presign.read B/K
object presign B/K --method=put object.presign.write B/K

copy and move request every one of their resources: any one of them being denied rejects the whole command, and where an allow list exists all of them must match.

Rules are written the same way, with * wildcards that do not cross / inside a key:

rule meaning
* everything
object.read mybucket or object.read mybucket/ every object in the bucket, at any depth
object.read mybucket/logs/ everything under the logs/ prefix, at any depth
object.read mybucket/logs/*.gz only *.gz directly under logs/
object.* mybucket/ any object operation on that bucket
object.presign.* * any presigned URL on any bucket

Notes

  • Presigned PUT URLs are denied by the default policy and cannot be enabled by an allow rule: a signed upload URL moves write access outside this app entirely — anyone holding it can write that key until it expires, with no further policy, approval or audit. Use object put instead — no asset or group policy change can enable it, because the deny is a floor merged into every effective policy.
  • Object keys may contain spaces; quote the whole target when they do, e.g. object stat 'mybucket/My Report.pdf'. Leading or trailing whitespace is rejected — permission rules split <action> <resource> at the first whitespace, so a padded name could never be authorized.
  • Every object verb takes exactly one target and it must name a real key: object stat mybucket is rejected, because mybucket as a rule would authorize the whole bucket rather than one object. object list is the exception — listing is always by prefix, so a bare bucket name is normalized to mybucket/.
  • A trailing / names the zero-byte "folder marker" object, so object delete mybucket/logs/ deletes exactly that marker. Because the same string read as a rule means the whole prefix, such an approval is never turned into a standing grant: repeating it asks again. object list is the exception — a listing approval on mybucket/logs/ does become a standing grant, because there the command and the rule cover the same range.
  • Targets must not start with / or --, and the bucket is always part of the target: an asset's default bucket is not implied, so object list with no target is still an error.
  • object copy and object move are single-object and server-side; both endpoints must be on this same asset. Use the cp tool to move data between different assets or between object storage and a server, and to copy whole prefixes.
  • Unknown flags are rejected rather than ignored, so a typo such as --max_keys=100 fails instead of silently listing the default page size.
  • The command line is shell-tokenized but never shell-executed: $, |, > and & produce an error rather than expanding or redirecting.
  • The scope parameter is not used by OSS assets; the target names bucket and key.

Asset config (for put_asset)

field type required notes
endpoint string yes Host, or scheme://host[:port]
access_key_id string yes
secret_access_key string no Write-only. Encrypted in the asset; does not create a credential
credential_id number no Existing managed password credential ID; mutually exclusive with secret_access_key
provider string no UI provider preset label (e.g. "s3", "minio"); does not change connection behavior
region string no
bucket string no Default bucket, a bare bucket name (no /). When set, the asset is limited to this bucket in the desktop browser and in bucket list, and the connection test probes it instead of listing buckets. Set it for credentials scoped to one bucket (e.g. Cloudflare R2 object tokens); "" clears it
use_path_style bool no true to force path-style addressing (needed by most self-hosted S3-compatible services)
use_ssl bool no true to connect over HTTPS
connect_timeout number no Seconds; 0 uses the default

Plaintext is never returned, is encrypted in the asset, and never creates a managed credential.

Example:

put_asset(name="backups-bucket", type="oss", config={"endpoint":"s3.us-east-1.amazonaws.com","region":"us-east-1","access_key_id":"AKIAEXAMPLE","secret_access_key":"...","use_ssl":"true"})

版本历史

  • 2b9abfb 当前 2026-10-19 03:58

    新增默认桶配置支持,优化无ListBuckets权限时的体验;修复Cloudflare R2等服务的文件夹路径编码解码问题。

  • b159e91 2026-08-19 20:21
  • d6c7a6e 2026-08-16 07:29

    修正文档契约漂移:明确presign PUT受内置deny组限制,object list前缀审批机制,oss get --file需过本地写入门禁,presign默认method=get且expiry=3600,put返回无file字段等实现细节。

  • aeb4bc3 2026-07-24 16:28

同 Skill 集合

extensions/notebook/SKILL.md
internal/ai/skills/database/SKILL.md
internal/ai/skills/etcd/SKILL.md
internal/ai/skills/k8s/SKILL.md
internal/ai/skills/kafka/SKILL.md
internal/ai/skills/local/SKILL.md
internal/ai/skills/mongodb/SKILL.md
internal/ai/skills/rdp/SKILL.md
internal/ai/skills/redis/SKILL.md
internal/ai/skills/serial/SKILL.md
internal/ai/skills/ssh/SKILL.md
internal/ai/skills/vnc/SKILL.md
plugin/opsctl/skills/opsctl/SKILL.md

元信息

文件数
0
版本
bca05b6
Hash
d0e4b69c
收录时间
2026-07-24 16:28

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-11-04 12:57
浙ICP备14020137号-1