必须在 composer.json 根级显式禁用 packagist.org:{"packagist.org": false},并配置 type: "composer" 且以 / 结尾的私有仓库 url;satis output-dir 需为绝对路径,web 服务器须正确托管该目录并支持 application/json mime 类型。

客户端 composer.json 必须显式禁用 packagist.org
不关掉默认源,Satis 仓库就只是 fallback,根本不会被查询。Composer 不会主动“发现”你配的私有源,它只按规则执行:先查 packagist.org,查不到才轮到你列的 repositories。
必须在项目 composer.json 的最外层(和 require、autoload 同级)加这一行:
{"packagist.org": false}
-
"packagist.org": false是键名,不能写成"repos.packagist"或"packagist",大小写、点号、值类型都必须严格匹配 - 如果同时用了 Artifactory 和 Satis,也得关;只关一个没用
- 改完立刻删掉
vendor/和composer.lock,否则旧 lock 文件仍指向官方源,校验失败
repositories URL 必须以 / 结尾且类型为 composer
Satis 是静态文件生成器,不是 Web 服务,所以客户端必须把它的输出目录当作一个标准 Composer 类型仓库来访问——也就是 type: "composer",不是 vcs。
示例配置(写在 composer.json 的 repositories 数组里):
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
[
{
"type": "composer",
"url": "https://pkg.internal/"
}
]
-
url末尾的/绝对不能省,少一个就会让 Composer 拼出https://pkg.internal/packages.json/packages.json - URL 必须能直接 GET 到
packages.json:运行curl -I https://pkg.internal/packages.json应返回 HTTP 200 +Content-Type: application/json - 别写成
https://pkg.internal/api/composer(那是 Artifactory 的路径),Satis 就是根路径直出
Web 服务器必须正确托管 output-dir 目录
Satis 构建后只生成一堆文件,没有内置 HTTP 服务。404 不是网络不通,而是 Nginx/Apache 没暴露对的路径。
假设你在 satis.json 中写了:
"output-dir": "/var/www/satis/web"
那么 Nginx 配置必须是:
root /var/www/satis/web;
-
root值必须精确匹配output-dir,不能多一层/web也不能少 - Nginx 要显式支持 JSON MIME 类型:
types { application/json json; },否则返回text/plain,Composer 拒收 - dist ZIP 文件路径如
dist/vendor-package/abcd1234.zip也要能被公开 GET 到,否则安装时会回退到 source,甚至失败
satis.json 的 output-dir 必须用绝对路径
相对路径会导致构建结果散落、权限混乱、Web 服务找不到文件。Satis 不报错,但生成的 packages.json 里可能压根没包。
- 写成
"output-dir": "web"或"output-dir": "./web"是常见错误,构建后文件实际落在当前命令执行目录下,而非你预期的 Web 根目录 - 推荐写全路径,例如
"output-dir": "/var/www/satis/web"(Linux/macOS)或"output-dir": "C:\satis\web"(Windows) - 确保运行
php bin/satis build的用户对该路径有读写权限,尤其是www-data或nginx用户要能读取生成的文件
/,漏一个 root,缺一个 MIME 类型,都会导致 Composer 静默 fallback 到 packagist.org —— 它不报错,只沉默地跳过你的私有源。










