@shendu-sdt/oss-asset-upload
v0.1.9
Published
CLI for compressing image assets with Tinify and uploading them to Aliyun OSS.
Keywords
Readme
OSS Asset Uploader
命令别名:sd-oss(推荐)/ oss-asset-upload(兼容)
AI 可调用的本地文件上传工具:把本地图片、PDF、Word、Excel、GIF 等素材重命名、可选 Tinify 压缩、上传到阿里云 OSS,并输出可用 URL。图片来源不限,可以是设计工具复制的图片、截图、下载文件或本地素材。
内置 Web 浏览器界面,一条命令即可在浏览器中可视化浏览、搜索、预览 OSS 文件。
必要字段值参照
配置时可以按下面的示例理解各字段,也可以把截图里的真实值做脱敏后替换进去:
| 配置位置 | 字段 | 示例值 | 说明 |
| --- | --- | --- | --- |
| ossutil config | endpoint | https://oss-cn-beijing.aliyuncs.com | OSS 服务地址,可以和 sd-oss setup 的 endpoint 填同一个值。 |
| ossutil config | accessKeyID | LTAI5tF3****Demo | OSS 授权用的 AccessKeyId,只属于 ossutil。 |
| ossutil config | accessKeySecret | 8mQd****9xKp****vT2n | OSS 授权用的 AccessKeySecret,只属于 ossutil,不要写进 sd-oss 配置文件。 |
| ossutil config | stsToken | 留空 | STS 临时凭证才需要填写;使用长期 AccessKey 时直接回车留空,不要随便填示例值。 |
| sd-oss setup/init | bucket | demo-market-assets | OSS bucket 名,例如 oss://demo-market-assets/static/demo-mobile/ 里的 demo-market-assets。 |
| sd-oss setup/init | region | oss-cn-beijing | OSS 地域编码,用于推导默认 endpoint 和访问 URL。 |
| sd-oss setup/init | endpoint | https://oss-cn-beijing.aliyuncs.com | 本工具记录的默认 endpoint,可与 ossutil config 的 endpoint 一致。 |
| sd-oss init | baseDir | static/demo-mobile | 项目允许上传的 OSS 根路径。推荐填 bucket 后面的路径;如果误填 /static/demo-mobile/ 或 oss://demo-market-assets/static/demo-mobile/,工具会自动解析成 static/demo-mobile。 |
懒人 AI 用法
如果你希望 Claude、Codex、Qoder 等 AI Agent 以后直接会用这个工具,先在业务项目根目录把 AI 模板装好:
npm install -g @shendu-sdt/oss-asset-upload
sd-oss install-ai all然后把下面这段话直接复制给 AI:
请在当前项目使用 sd-oss 处理文件上传。
先执行 ossutil version,确认主版本为 2。如果本机没有 ossutil v2,或仍是 ossutil v1,先指导我按阿里云官方文档安装 ossutil v2:https://help.aliyun.com/zh/oss/developer-reference/ossutil-overview/;如果 ossutil 没在 PATH,让我提供路径并在命令里加 --ossutil <path>。
如果本机还没配置 OSS 授权,先指导我执行 ossutil config;sd-oss 不读取 OSS Browser 登录态,也不保存 AccessKey。
如果项目缺少 .oss-assets.json,先问我要当前项目允许上传的 OSS baseDir,然后执行 sd-oss init --base-dir <baseDir>。
我可以把 OSS 浏览器登录页、OSS 目录页、Tinify API 页截图发给你;请从截图里辅助识别 bucket、region、endpoint、baseDir 和 Tinify API key。截图里如果有 AccessKeySecret 或 Tinify API key,只能在本地可信 AI 会话中使用,不要发到公共对话。
如果需要压缩,先确认 Tinify 是否已配置;缺少 Tinify 时执行 sd-oss tinify 或提醒我先配置。
上传时只能使用项目 .oss-assets.json 允许的 baseDir/baseDirs,不要复制临时配置、不要修改 baseDir 来绕过限制。
baseDir 必须是已经存在的 OSS 前缀;baseDir 下面的 --dir 子目录可以是新的。
不要用 sd-oss 删除文件;这个 CLI 不提供删除能力,需要删除时让我手动去 OSS 控制台或官方工具处理。
日常上传命令使用:sd-oss upload <文件路径> --dir <目录> --name <文件名>。上传文件名会自动追加 16 位 hash,禁止覆盖已有 OSS 对象;只有需要压缩图片时才加 --compress tinify。
需要浏览 OSS 目录时,执行 sd-oss browse,零参数即可启动 Web 界面可视化浏览、搜索、预览 OSS 文件,默认 30 分钟无请求自动关闭。
完成后把命令输出里的 URL 返回给我。截图辅助配置时可以这样给 AI:
ossutil v2 是阿里云官方命令行工具,需要单独安装并配置授权。OSS Browser 登录态不能直接给
sd-oss使用;如果 AI 发现ossutil v2不可用,应先让我安装或提供--ossutil <path>。OSS 浏览器登录页:用于辅助识别
endpoint、region、预设 OSS 路径等。不要把 AccessKeySecret 明文贴到公共对话里。
- OSS 浏览器目录页:地址栏里
oss://<bucket>/<path>/的<path>就是候选baseDir。推荐只填 bucket 后面的路径;如果直接填完整oss://<bucket>/<path>/,工具会自动解析成<path>。
- Tinify API 页:用于确认 API key 和本月压缩额度。配置命令是
sd-oss tinify。Tinify API key 也是凭证,不要发到公共对话或不可信 AI。
快速开始
1. 安装 CLI
npm install -g @shendu-sdt/oss-asset-upload验证命令是否可用:
sd-oss --version2. 安装阿里云官方 ossutil v2
sd-oss 调用本机 ossutil v2 访问 OSS。目录查看、初始化时的远端目录检查和真实上传都要求 ossutil v2;ossutil v1 不受支持。只有不访问 OSS 的纯本地 dry-run 可以不安装 ossutil。
阿里云官方介绍:命令行工具 ossutil 2.0 https://help.aliyun.com/zh/oss/developer-reference/ossutil-overview/
Linux/macOS 可以使用阿里云官方安装脚本:
sudo -v
curl https://gosspublic.alicdn.com/ossutil/install.sh | sudo bashWindows 推荐下载官方 Windows 64bit 包,解压到固定目录,例如:
C:\Tools\ossutil\安装后执行以下命令验证版本:
ossutil version输出的主版本必须为 2,例如:
2.3.0仅执行 ossutil 并看到帮助信息,不能证明当前使用的是 v2。
Windows 用户需要先把安装目录加入系统 PATH,重新打开 PowerShell 或 CMD,再执行:
ossutil version如果不想配置 PATH,也可以在使用本工具时临时指定:
sd-oss dirs --ossutil /path/to/ossutilWindows 示例:
sd-oss dirs --ossutil C:\Tools\ossutil\ossutil.bat阿里云官方文档:https://help.aliyun.com/zh/oss/developer-reference/install-ossutil
3. 配置 OSS 授权
每台电脑首次使用上传或目录查看前,需要配置一次 ossutil:
ossutil config按提示填写:
endpoint: https://oss-cn-beijing.aliyuncs.com
accessKeyID: LTAI5tF3****Demo
accessKeySecret: 8mQd****9xKp****vT2n
stsToken: 直接回车留空;只有 STS 临时凭证才填写ossutil 的配置文件保存在用户本机。它和 OSS Browser 的登录信息互不相通,本工具也不会读取 OSS Browser 的 AK。
验证授权:
ossutil ls oss://demo-market-assets/static/demo-mobile/4. 配置 CLI 全局默认值
每台电脑执行一次:
sd-oss setup它会记录默认:
OSS bucket
OSS region
endpoint按提示填写你自己的 OSS 信息,例如:
bucket: demo-market-assets
region: oss-cn-beijing
endpoint: https://oss-cn-beijing.aliyuncs.com如果需要 Tinify 压缩,上传前必须配置 Tinify API key:
sd-oss tinify未配置 Tinify API key 时,图片默认不压缩,直接上传原图;显式传 --compress tinify 会报错并提示先配置。
5. 初始化业务项目
进入业务项目根目录:
cd /path/to/your-project交互初始化:
sd-oss init或直接指定当前项目允许上传的 OSS 前缀:
sd-oss init --base-dir path/to/project-prefix初始化会生成项目配置:
.oss-assets.json这个文件用于限制项目只能上传到指定 OSS 前缀。初始化默认会用 ossutil ls 检查 baseDir 已经存在,不存在会拒绝生成配置。
6. 查看可上传目录
sd-oss dirs输出的是当前项目 baseDir 下已经存在的第一层目录,用于挑选常用目录。上传时也可以指定新的 --dir 子目录,只要它仍在当前项目 baseDir 下面。
7. 上传图片
先预览,不写 OSS:
sd-oss --asset ./banner.png --dir home --name home-banner确认 OSS key 和 URL 后真实上传:
sd-oss upload ./banner.png --dir home --name home-banner常用查看命令:
sd-oss config all
sd-oss config global
sd-oss config current
sd-oss version旧参数仍然兼容,例如 sd-oss --asset ./banner.png --dir home --name home-banner --upload。
8. 浏览 OSS 文件
启动内置 Web 浏览器,可视化浏览、搜索、预览 OSS 目录:
sd-oss browse零参数启动时自动选取配置中最宽的目录。其他选项:
sd-oss browse --base-dir <OSS前缀> # 指定起始目录
sd-oss browse --port 8080 # 指定端口
sd-oss browse --idle-timeout 10 # 10 分钟无请求自动关闭(默认 30 分钟)
sd-oss browse --idle-timeout 0 # 禁用自动关闭
sd-oss browse --no-open # 不自动打开浏览器服务启动后在浏览器中打开输出地址即可。默认 30 分钟无请求自动退出,避免进程泄漏。
功能包括:
- 目录导航(前进/后退/回到根目录)
- 文件名搜索(当前目录内客户端过滤)
- 点击文件查看详情(大小、修改时间、Content-Type、公网 URL)
- 图片文件缩略图预览
- 复制上传路径提示词
配置模型
工具使用两层配置:
- 全局配置:记录默认
bucket、region、endpoint,可选记录 Tinify API key。 - 项目配置:每个项目根目录维护
.oss-assets.json,记录允许上传的 OSS 前缀和 URL 规则。
查看配置:
# 查看全局配置
sd-oss config global
# 查看当前项目配置
sd-oss config current
# 同时查看全局和当前项目配置
sd-oss config all
# 查看版本号
sd-oss version
sd-oss --version配置输出会包含配置文件路径,并会遮罩 tinifyApiKey 等敏感值。
修改配置:
# 全局配置
sd-oss config set global bucket your-oss-bucket
sd-oss config set global region your-oss-region
sd-oss config set global endpoint https://oss.example.com
sd-oss config set global base-dir path/to/prefix
sd-oss config set global tinify-api-key YOUR_TINIFY_API_KEY
# 当前项目配置
sd-oss config set current base-dir path/to/project-prefix
sd-oss config set current public-base-url https://cdn.example.com/path/to/project-prefix
sd-oss config set current default-module oss-assets
sd-oss config set current allow-overwrite true
sd-oss config set current allowed-extensions png,jpg,jpeg,pdf,docx
sd-oss config set current cache-control-hashed "public, max-age=31536000, immutable"
sd-oss config set current cache-control-plain "public, max-age=3600"
sd-oss config set current allow-chinese-key false项目配置支持修改的字段:project、bucket、region、endpoint、base-dir、public-base-url、default-module、env、allow-overwrite、allow-prod-overwrite、allowed-extensions、cache-control-hashed、cache-control-plain、allow-chinese-key。兼容 camelCase 写法,但日常建议使用 kebab-case。append-hash 和 hash-length 是安全固化字段,不能再通过 config set 修改。
allowed-extensions 使用逗号分隔。工具会去除扩展名前面的 .、转成小写并去重;扩展名只能包含英文字母和数字。文件名始终追加 16 位内容 hash 后缀。
删除显式高级配置、恢复运行时默认值:
# 单个字段
sd-oss config reset current allowed-extensions
sd-oss config reset current cache-control-hashed
sd-oss config reset current append-hash
sd-oss config reset current hash-length
# 整组配置
sd-oss config reset current cache-control
sd-oss config reset current naming可重置的叶子字段包括:allowed-extensions、cache-control-hashed、cache-control-plain、append-hash、hash-length、allow-chinese-key。append-hash 和 hash-length 的 reset 仅用于清理旧配置;运行时仍强制启用 16 位内容 hash。如果重置后嵌套对象为空,工具会同时删除该空对象。config current 仍会显示运行时补全后的有效默认值。
修改 base-dir 时,工具会把 public-base-url 末尾的旧 baseDir 同步替换为新值。如果当前 public-base-url 不是以旧 baseDir 结尾,工具会拒绝修改,避免后续上传输出错误 URL。
系统兼容
运行环境需要 Node.js 18+。目录查看、初始化时的远端目录检查和真实上传强制要求阿里云 ossutil v2;ossutil v1 不受支持。纯本地 dry-run 不访问 OSS,可以不安装 ossutil。
macOS、Linux、Windows 都可以使用。推荐把 ossutil 加入 PATH;如果没有加入 PATH,可以通过环境变量指定:
OSSUTIL_PATH=/path/to/ossutil sd-oss --list-dirsWindows PowerShell 示例:
$env:OSSUTIL_PATH="C:\Tools\ossutil.exe"
sd-oss --list-dirs从 ossutil v1 升级
升级 ossutil 后先执行:
ossutil version确认输出为 2.x。如果设置过 OSSUTIL_PATH,还需要确认它没有继续指向旧版可执行文件。
旧项目无需重新执行 sd-oss init。旧配置中的 appendHash 和 hashLength 不再控制上传行为,运行时固定使用 16 位内容 hash。CLI 会忽略旧值并给出提示;需要清理时执行:
sd-oss config reset current append-hash
sd-oss config reset current hash-length项目 .oss-assets.json 示例:
{
"project": "your-project-name",
"bucket": "your-oss-bucket",
"region": "your-oss-region",
"baseDir": "path/to/project-prefix",
"publicBaseUrl": "https://cdn.example.com/path/to/project-prefix",
"defaultModule": "oss-assets",
"allowedExtensions": ["png", "jpg", "jpeg", "webp", "svg", "gif", "html", "pdf", "doc", "docx", "xls", "xlsx"],
"baseDirs": [
{
"baseDir": "path/to/another-project-prefix",
"publicBaseUrl": "https://cdn.example.com/path/to/another-project-prefix",
"defaultModule": "oss-assets"
}
]
}baseDir 是项目默认 OSS 前缀。baseDirs 是可选白名单,用于允许临时切换到同项目配置中已经声明的其他 OSS 前缀。
全局 Setup
先在任意目录执行一次:
sd-oss setup它会记录默认:
OSS bucket
OSS region
endpointbaseDir 不属于全局 setup。每个项目必须在项目初始化时单独配置自己的 baseDir,用于限制该项目允许上传的 OSS 前缀。你可以把 OSS 浏览器目录页截图给 AI,地址栏里 oss://<bucket>/<path>/ 的 <path> 通常就是候选 baseDir。推荐填写 <path>;如果误填完整 oss://<bucket>/<path>/ 或前后多写了 /,工具会自动解析成相对前缀。
如果没有执行全局 setup,项目初始化会提示先运行 setup,因为项目初始化默认会复用全局 bucket 和 region。
兼容场景下,全局配置文件也可以手动保留一个 baseDir,仅用于在非项目目录执行 sd-oss dirs 查看 OSS 目录;上传仍然必须依赖项目 .oss-assets.json。
可选配置 TinyPNG/Tinify:
sd-oss tinify项目初始化
进入项目根目录后执行:
sd-oss initsd-oss init 会进入交互初始化,并要求填写当前项目自己的 OSS 根目录 baseDir。
如果想跳过交互,可以直接传当前项目的 baseDir。推荐填写 bucket 后面的路径;完整 OSS 路径也兼容,会自动解析:
sd-oss init --base-dir path/to/project-prefix例如下面两种写法最终都会写入 static/demo-mobile:
sd-oss init --base-dir /static/demo-mobile/
sd-oss init --base-dir oss://demo-market-assets/static/demo-mobile/需要逐项确认时再使用交互模式:
sd-oss init --interactive交互初始化会依次询问:
项目名
OSS bucket,默认使用全局 setup
OSS region,默认使用全局 setup
项目 OSS 根目录 baseDir
公网访问基础 URL
默认模块目录,默认 oss-assetsbaseDir 和 --dir 的区别:
baseDir = 项目级固定根目录,必须提前存在,写进 .oss-assets.json
--dir = 本次上传的业务子目录,可以是新的
例子:
baseDir: static/demo-mobile
--dir: test-oss-asset
最终 key:
static/demo-mobile/test-oss-asset/xxx.png生成后,后续所有上传都会被限制在项目配置的 baseDir 下。例如:
oss://your-oss-bucket/path/to/project-prefix/初始化默认会用 ossutil ls 验证这个前缀已经存在。也就是说项目只能绑定到提前建好的 OSS 目录,避免成员误填未确认的前缀后把资源上传到错误位置。
如果 .oss-assets.json 已存在,初始化默认会拒绝覆盖。确认要重建时才加 --force。
特殊情况下,如果你只是离线生成配置、暂时无法连 OSS,可以显式跳过目录存在性检查:
sd-oss init --interactive --skip-base-dir-check跳过检查只影响初始化;真正上传时仍然只能上传到 baseDir 下。
上传文件/素材
先 dry-run:
sd-oss \
--asset ./banner.png \
--dir home \
--name home-banner确认 OSS key 和 URL 后真实上传:
sd-oss upload ./banner.png --dir home --name home-bannerupload 子命令表示确认上传,会真实写 OSS。如果只是想预览 OSS key 和 URL,使用兼容写法并省略 --upload:
sd-oss --asset ./banner.png --dir home --name home-banner真实上传前工具会校验项目 baseDir 已存在;dry-run 不做远端 OSS 校验,只预览 key 和 URL。--dir 只是 baseDir 内部的子路径,可以是已有目录,也可以是新的业务子目录。
如果不传 --dir,默认上传到项目配置的 defaultModule。
上传文件名会自动追加固定 16 位内容 hash,用户无需配置。默认上传不会覆盖 OSS 已有对象;同一目录、业务名和相同内容可以复用已有地址,不同内容会使用不同地址,无法安全确认时会明确失败。生产环境下显式 --overwrite 也会被拒绝。
本 CLI 不提供删除 OSS 对象的能力。需要删除时,请在 OSS 控制台或经审批的官方工具中手动处理;delete、remove、rm 这类命令会直接拒绝执行。
上传限制:
- 单文件最大为 5 GB。
- 上传会创建本地临时副本,需要预留接近文件大小的额外磁盘空间。
- OSS 账号需要具备列目录、上传对象和读取对象信息的权限;权限不足时请联系 OSS 管理员处理。
- 处理结果包含失败项时,CLI 会返回非零退出码。不要把部分成功视为全部完成。
如果需要指定上传到 baseDir 下的某个业务子目录,用 --dir:
sd-oss upload ./banner.png --dir pc/home --name home-banner这会生成类似下面的 key:
path/to/project-prefix/pc/home/home-banner-0123456789abcdef.png--dir 只能决定 baseDir 内部的子目录,不能跳出项目允许的 OSS 前缀。
如果项目配置了多个允许的 baseDir,可以单次临时指定:
sd-oss upload ./banner.png \
--base-dir path/to/another-project-prefix \
--dir home \
--name home-banner--base-dir 必须等于当前项目 .oss-assets.json 中的默认 baseDir,或 baseDirs 白名单里的某一项。工具不会接受配置文件里不存在的新前缀。
可以查看 OSS 已有目录:
sd-oss dirs目录列表来自 baseDir 下已经存在的第一层目录,. 表示直接上传到 baseDir 根目录。深层目录可以用 --dir pc/home 直接指定;如果该子目录尚不存在,会随对象上传自然形成。
如果只是想查看当前项目可选目录,可以在项目目录执行:
sd-oss dirs该命令只读取当前项目的 .oss-assets.json。如果当前目录不是项目目录,请进入项目目录执行,或传 --cwd <projectDir>。
如果当前目录没有项目配置,dirs 会尝试读取全局配置里的 baseDir,用于查看全局 OSS 目录:
{
"bucket": "your-oss-bucket",
"region": "your-oss-region",
"endpoint": "https://oss.example.com",
"baseDir": "path/to/prefix"
}全局 baseDir 只用于查看目录,不参与上传权限控制。
查看非默认 baseDir 下的目录时,同样需要先把该前缀加入项目配置的 baseDirs:
sd-oss dirs --base-dir path/to/another-project-prefix本地历史
默认不写上传记录。如果个人需要回查,可以显式加:
sd-oss \
--asset ./banner.png \
--dir home \
--name home-banner \
--history记录会追加到用户本机全局目录,不会写进项目:
~/.oss-asset-upload/history/YYYY-MM-DD.jsonl压缩模式
未配置 Tinify API key 时,默认不压缩,直接上传原图:
sd-oss --asset ./banner.png --dir home --name banner配置 Tinify API key 后,后续上传默认走 Tinify 压缩:
sd-oss tinify也可以单次显式选择 Tinify:
sd-oss \
--asset ./banner.png \
--dir home \
--name banner \
--compress tinify需要临时跳过压缩时:
sd-oss \
--asset ./banner.png \
--dir home \
--name banner \
--compress none注意:TinyPNG 会把图片发送到 Tinify API,属于有损压缩,并受 API key 的次数/费用限制。PDF、Word、Excel、GIF 等非 Tinify 支持格式请使用默认不压缩上传,或显式 --compress none。
Tinify 生成的临时文件会写入 ~/.oss-asset-upload/work,不会写到当前业务项目。
批量上传
也可以通过资源清单批量上传:
{
"assets": [
{
"localPath": "assets/banner.png",
"source": {
"sourceLink": "https://example.com/source",
"nodeName": "Banner",
"format": "png"
}
}
]
}调用:
sd-oss \
--asset-manifest assets/assets.json \
--source https://example.com/source \
--dir home \
--name home-banner \
--uploadAI Agent 集成
可以在项目里生成 AI 可用的命令模板,并把命名 skill 同步到常见 Agent 的全局目录:
sd-oss install-ai all生成项目内辅助文件:
.claude/commands/oss-upload.md
.claude/commands/oss-dirs.md
.claude/commands/oss-init.md
.codex/skills/oss-asset-upload/SKILL.md同步全局命名 skill:
~/.agents/skills/oss-asset-upload/SKILL.md
~/.claude/skills/oss-asset-upload/SKILL.md
~/.cursor/skills/oss-asset-upload/SKILL.md
~/.qoder/skills/oss-asset-upload/SKILL.md
~/.gemini/config/skills/oss-asset-upload/SKILL.md
~/.antigravity/skills/oss-asset-upload/SKILL.md
~/.windsurf/skills/oss-asset-upload/SKILL.md
~/.aider/skills/oss-asset-upload/SKILL.md
~/.trae/skills/oss-asset-upload/SKILL.md
~/.hermes/skills/oss-asset-upload/SKILL.md只安装 Claude 命令:
sd-oss install-ai claude只安装 Codex skill 模板:
sd-oss install-ai codex只安装某个 Agent 的全局命名 skill:
sd-oss install-ai qoder
sd-oss install-ai cursor
sd-oss install-ai gemini可用目标包括:claude、codex、agents、claude-skill、cursor、qoder、gemini、antigravity、windsurf、aider、trae、hermes、all。
如果项目里或全局 skill 目录已经存在同名文件,命令会拒绝覆盖。确认要重装模板时加:
sd-oss install-ai all --forceAI 侧日常提示可以很短:
上传这张图到 OSS,目录 home,命名 home-banner:./banner.pngAI 应调用:
sd-oss upload ./banner.png --dir home --name home-banner环境自检
sd-oss --version
sd-oss doctor
ossutil version如果 oss-asset-upload doctor 提示缺少 Tinify API key,只影响压缩,不影响不压缩上传;需要压缩时先运行 oss-asset-upload tinify。
常见错误:
| 错误或现象 | 处理方式 |
| --- | --- |
| OSSUTIL_MISSING 或提示找不到 ossutil | 安装阿里云官方 ossutil v2,并确认它已加入 PATH;也可以传入 --ossutil <path>。 |
| OSSUTIL_VERSION_UNSUPPORTED | 当前是 ossutil v1 或无法识别的版本。执行 ossutil version,升级到 v2,并检查 OSSUTIL_PATH。 |
| 提示未配置授权 | 执行 ossutil config,填写当前 OSS 环境的授权信息。 |
| AccessDenied、Forbidden 或其他权限错误 | 联系 OSS 管理员,确认账号具备列目录、上传对象和读取对象信息的权限。 |
