publish-pilot
publish-pilot is an MCP server that lets Claude, or any other agent, take a project from an empty folder to a published GitHub repo and an npm, PyPI or crates.io package. It checks your tools, handles logins, scaffolds the project, runs checks, publishes and releases. You only do the sign-in, 2FA and approval clicks.
It works through the command line, not by controlling your screen, so you can keep using your computer, or publish several projects at once, while Claude works.
Install
You need Node.js 22 or newer. To publish, you also need git, the GitHub CLI (gh) and your registry's CLI; doctor shows what's missing, and Claude can install it for you.
- Windows installer from qlinter.org (
publish-pilot-setup-0.4.0.exe). It adds publish-pilot to Claude Code, Claude Desktop or both. Restart Claude Desktop afterwards. - macOS package from qlinter.org (
publish-pilot-0.4.0.pkg). It does the same on a Mac. - Claude Code, by hand (macOS, Linux, WSL):
claude mcp add publish-pilot -- npx -y publish-pilot-mcp
On native Windows, wrap npx in cmd /c:
claude mcp add publish-pilot -- cmd /c npx -y publish-pilot-mcp
- Claude Desktop, by hand: open Settings → Developer → Edit Config and add this under
mcpServers, then restart Claude Desktop. On macOS and Linux, use"command": "npx"and"args": ["-y", "publish-pilot-mcp"].
{
"mcpServers": {
"publish-pilot": { "command": "cmd", "args": ["/c", "npx", "-y", "publish-pilot-mcp"] }
}
}
- Any other MCP client: run
npx -y publish-pilot-mcpas a stdio server (cmd /c npx -y publish-pilot-mcpon Windows).
npx checks the registry each time the server starts, which adds about 0.7 s. For a faster start, npm install -g publish-pilot-mcp and point the client at node and the installed dist/cli.js. You then update it yourself.
Quick start
Check that your machine is ready:
npx -y publish-pilot-mcp doctor both npm
This lists the tools that are installed or missing (git, gh, node and npm) and whether you're logged in to GitHub and npm. The arguments are doctor [repo|package|both] [npm|pypi|crates].
Then ask Claude, naming the folder:
Use publish-pilot to make an npm package called my-tool in C:\code\my-tool that converts CSV to JSON, and publish it to both GitHub and npm.
In Claude Code, the built-in plan is also a command: /mcp__publish-pilot__publish_project. It takes optional target, name, description, registry, visibility, license, what and dir arguments, and Claude asks for anything you leave out.
Claude works through the plan: preflight, scaffold, code and tests, checks, dry run, commit, GitHub repo, publish, trusted publishing, tag, release and a final install test. When it needs you, it sends a desktop notification and opens the right page, or a terminal window where npm asks for your approval.
What you do yourself
The server never types passwords or 2FA codes, and never clicks Authorize, Approve or Save. Expect to:
- Sign in to GitHub and click Authorize, if
ghisn't logged in yet. - Sign in to npm, if
npm whoamifails. - Approve the first
npm publishwith 2FA. - Approve the trusted-publisher link (
npm trust github) with 2FA.
npm only shows its approval link in a real terminal, so on Windows and macOS those steps open a visible PowerShell or Terminal window. If it says "Press ENTER to open in the browser", press Enter there and approve.
npm can only add a trusted publisher to a package that already exists. So a new package is published once from your computer, and every later version from GitHub Actions: each release is a pushed v* tag, published with OIDC, and no tokens are stored.
Tools
| Tool | What it does |
|---|---|
preflight |
Checks git, gh, the registry CLI, your logins and your git identity. Starts no logins. |
install_tool |
Installs a missing tool with winget (Windows), brew (macOS) or apt (Linux). |
check_names |
Checks that the package and repo names are valid and free, and picks the best free alternative. |
login |
Starts a browser login: gh auth login --web, returning the one-time code and URL, or npm login --auth-type=web in a terminal window. |
job_status |
Polls a running login or publish job: status, output, URLs and codes. |
scaffold_project |
Creates source, tests, README, LICENSE, CHANGELOG, .gitignore, manifest and workflows. Never overwrites files. target: "repo" makes a clone-and-build project that can't be published to a registry; private: true keeps CI on Ubuntu. |
add_workflows |
Writes ci.yml and a release.yml that publishes with OIDC, skips versions that already exist and creates a GitHub release from the CHANGELOG. |
run_checks |
Secret scan, then install, lint, typecheck, build and test (npm scripts, a Python .venv with pytest, or cargo). |
inspect_package |
Runs the publish dry run and lists the files that would ship, flagging junk and secrets. |
git_commit |
Runs git init -b main if needed and commits. Refuses if secrets would be committed. |
create_github_repo |
gh repo create <name> --public/--private --source . --push. Warns when a private repo's CI would use paid Windows or macOS minutes. |
publish_package |
npm publish (in a terminal window, for the 2FA approval), twine upload or cargo publish. Skips versions that already exist, and waits 24 hours after a rate-limit error. |
setup_trusted_publishing |
Connects the package to release.yml: npm trust github, or the PyPI or crates.io settings page with the exact values to enter. |
tag_and_release |
Tags v<version>, pushes the branch and tag together, and creates the GitHub release from the CHANGELOG unless release.yml does. |
watch_workflow |
Waits for the workflow run of the current commit and returns the failing log if it fails. |
bump_version |
Bumps the patch, minor or major version and adds a CHANGELOG entry. |
verify_install |
Installs from the real registry, or clones the repo, into a new temp folder and runs your README steps one by one. |
notify |
Desktop notification. With url, also opens a page on github.com, npmjs.com, pypi.org or crates.io. |
run_command |
Runs a command in PowerShell (Windows) or sh. Destructive commands are refused. |
How it works
publish-pilot is a stdio MCP server written in TypeScript. Each tool wraps the real command-line tools (git, gh, npm, uv or twine, cargo) and returns their results to Claude. A built-in playbook (the publish_project prompt) gives Claude the order of steps.
Long-running steps such as logins and publishes run as background jobs that Claude polls with job_status. Steps that need you open a browser page or a visible terminal window and send a desktop notification.
Safety is built into the server, not left to the model:
- All command output is scanned, and tokens (GitHub, npm, PyPI, crates.io, AWS and others) are replaced with
***before Claude sees them. - Commits and publishes are blocked when
.envfiles, private keys or tokens would be included. - It never deletes, force-pushes or unpublishes anything, tags included. A failed release is fixed with a new patch version.
run_commandrefuses force-push, deleting tags, repos or releases,npm unpublish,cargo yank, logout and token commands, and recursive deletes. - It only opens
https://pages on github.com, npmjs.com, pypi.org and crates.io.
It can also be used as a library: createServer() plus helpers such as preflight, scaffoldProject, releaseWorkflow, scanProject and checkPackageName, with TypeScript types.
Files
| Item | Where |
|---|---|
| npm rate-limit record | ~/.publish-pilot/rate-limits.json |
| Claude Desktop config | claude_desktop_config.json (open it from Settings → Developer → Edit Config) |
| Claude Desktop server log | mcp-server-publish-pilot.log, in %LOCALAPPDATA%\Claude\logs or %APPDATA%\Claude\logs on Windows |
Limits and troubleshooting
doctorsays a tool is MISSING: ask Claude to runinstall_tool, or install it yourself, for examplewinget install --id GitHub.cli -e. Then restart your MCP client so it picks up the new PATH.- The server doesn't start on Windows (
spawn npx ENOENT,EINVALor "Connection closed"): use thecmd /c npx -y publish-pilot-mcpform and restart the client. npx publish-pilot-mcpisn't recognised: you ran it inside the publish-pilot-mcp source folder. Run it from any other folder.npm publishfails with E429: npm limits how many packages and versions one account can publish. Nothing was published. Don't retry soon, because every failed attempt can extend the block.publish_packagerefuses to try again for 24 hours unless called withforce.- The npm approval link expired: ask Claude to call
publish_packageagain. Each call opens a fresh link. - The release workflow says the tag doesn't match the version: the
v*tag must equal the manifest version. Ask Claude tobump_version, commit and tag the new version. Old tags are never moved. npm publishfrom Actions fails with 404 or 401: trusted publishing isn't set up yet. Runsetup_trusted_publishing; the package must already exist on npm.
Worked examples
A new npm package, start to finish.
Use publish-pilot to make an npm package called csv-mini in C:\code\csv-mini that converts CSV to JSON, and publish it to both GitHub and npm.
Claude runs preflight, check_names (suggesting @you/csv-mini if the name is taken), scaffold_project, writes the code and tests, run_checks, inspect_package, git_commit, create_github_repo, then publish_package. A terminal window opens for npm's 2FA approval. Then setup_trusted_publishing, tag_and_release, watch_workflow and verify_install.
A GitHub repo only, no package. Ask for "just a GitHub repo". scaffold_project with target: "repo" writes a clone-and-build README and blocks registry publishing in the manifest.
A private repo. Ask for a private repo. CI runs on Ubuntu only, because private repos pay for Actions minutes and Windows and macOS runners cost 2× and 10× more.
The next version of an existing package. Ask Claude to release a patch. It runs bump_version, commits, and tag_and_release; release.yml publishes with OIDC and makes the GitHub release.
A Python package. Name PyPI as the registry. Checks run in a .venv with pytest, publishing uses twine upload, and trusted publishing is set up on PyPI's settings page with the values Claude gives you.
A Rust crate. Name crates.io. Checks use cargo, the first version is published with cargo publish, and later ones from GitHub Actions.
Edge cases
- Name taken:
check_namespicks the best free alternative, such as a scoped@you/nameon npm. - Not logged in:
loginstarts the browser login; you finish it. - A secret in the project: commits and publishes are refused until it's removed.
- Version already published:
publish_packageskips it, andrelease.ymlskips existing versions too. - A failed release: nothing is deleted or moved. Bump to a new patch version and release again.
- npm rate limit (E429):
publish_packagerefuses to retry for 24 hours unless called withforce. - Existing files:
scaffold_projectnever overwrites them. - Links Claude wants to open: only
https://pages on github.com, npmjs.com, pypi.org and crates.io.
FAQ
Does it store my tokens? No. It uses your existing gh and registry logins, and releases publish with OIDC.
Will it type my password? No. It never types passwords or 2FA codes and never clicks Authorize, Approve or Save.
Why does a terminal window open? npm only shows its approval link in a real terminal.
Can I keep using my computer? Yes. It works through the command line, not by controlling your screen.
Which clients does it work in? Claude Code, Claude Desktop and any MCP client that runs stdio servers.
Can it delete or unpublish things? No, and run_command refuses commands that would.
How is it different from shipkit? Same job; publish-pilot is an MCP server, shipkit is a CLI plus a Claude Code skill and hook, and costs fewer tokens per turn.
Do I need Node? Yes, Node.js 22 or newer.
Version and source
This page describes publish-pilot 0.4.0.
- Source: https://github.com/acus9345/publish-pilot-mcp
- npm: https://www.npmjs.com/package/publish-pilot-mcp
- License: MIT
publish-pilot 是一個 MCP 伺服器,讓 Claude 或任何其他 agent 把專案從空資料夾一路帶到已發布的 GitHub repo,以及 npm、PyPI 或 crates.io 套件。它會檢查你的工具、處理登入、建立專案骨架、執行檢查、發布並建立 release。你只需要登入、2FA 和按核准。
它透過命令列工作,不是控制你的畫面,所以 Claude 工作時你可以繼續用電腦,或同時發布好幾個專案。
安裝
你需要 Node.js 22 或更新版本。要發布,還需要 git、GitHub CLI(gh)和你的套件庫 CLI;doctor 會顯示缺少什麼,Claude 也能幫你安裝。
- Windows 安裝程式,來自 qlinter.org(
publish-pilot-setup-0.4.0.exe)。它會把 publish-pilot 加到 Claude Code、Claude Desktop 或兩者。之後請重新啟動 Claude Desktop。 - macOS 安裝套件,來自 qlinter.org(
publish-pilot-0.4.0.pkg)。在 Mac 上做同樣的事。 - 手動加到 Claude Code(macOS、Linux、WSL):
claude mcp add publish-pilot -- npx -y publish-pilot-mcp
在原生 Windows 上,用 cmd /c 包住 npx:
claude mcp add publish-pilot -- cmd /c npx -y publish-pilot-mcp
- 手動加到 Claude Desktop: 打開 Settings → Developer → Edit Config,在
mcpServers底下加入以下內容,然後重新啟動 Claude Desktop。在 macOS 和 Linux 上,改用"command": "npx"和"args": ["-y", "publish-pilot-mcp"]。
{
"mcpServers": {
"publish-pilot": { "command": "cmd", "args": ["/c", "npx", "-y", "publish-pilot-mcp"] }
}
}
- 其他 MCP 用戶端: 以 stdio 伺服器執行
npx -y publish-pilot-mcp(Windows 上是cmd /c npx -y publish-pilot-mcp)。
npx 每次啟動伺服器都會查詢套件庫,多花約 0.7 秒。想啟動快一點,可以 npm install -g publish-pilot-mcp,並讓用戶端指向 node 和安裝好的 dist/cli.js。之後要自己更新。
快速開始
確認你的電腦已準備好:
npx -y publish-pilot-mcp doctor both npm
它會列出已安裝或缺少的工具(git、gh、node 和 npm),以及你是否已登入 GitHub 和 npm。參數格式是 doctor [repo|package|both] [npm|pypi|crates]。
然後告訴 Claude,並指定資料夾:
Use publish-pilot to make an npm package called my-tool in C:\code\my-tool that converts CSV to JSON, and publish it to both GitHub and npm.
在 Claude Code 中,內建流程也是一個指令:/mcp__publish-pilot__publish_project。它接受可選的 target、name、description、registry、visibility、license、what 和 dir 參數,你沒填的 Claude 會先問。
Claude 會依序執行:預檢、建立骨架、程式碼與測試、檢查、dry run、commit、GitHub repo、發布、trusted publishing、打 tag、release,最後做安裝測試。需要你時,它會送出桌面通知,並打開正確的網頁,或打開讓 npm 請你核准的終端機視窗。
你要自己做的事
伺服器從不輸入密碼或 2FA 驗證碼,也從不按 Authorize、Approve 或 Save。你需要:
- 如果
gh還沒登入,登入 GitHub 並按 Authorize。 - 如果
npm whoami失敗,登入 npm。 - 以 2FA 核准第一次
npm publish。 - 以 2FA 核准 trusted publisher 連結(
npm trust github)。
npm 只在真正的終端機中顯示核准連結,所以在 Windows 和 macOS 上,這些步驟會打開一個看得見的 PowerShell 或 Terminal 視窗。如果它顯示「Press ENTER to open in the browser」,就在那裡按 Enter 並核准。
npm 只能為已存在的套件加入 trusted publisher。所以新套件第一次從你的電腦發布,之後每個版本都從 GitHub Actions 發布:每次 release 就是推送一個 v* tag,以 OIDC 發布,不儲存任何權杖。
工具
| 工具 | 作用 |
|---|---|
preflight |
檢查 git、gh、套件庫 CLI、你的登入狀態和 git 身分。不會啟動任何登入。 |
install_tool |
用 winget(Windows)、brew(macOS)或 apt(Linux)安裝缺少的工具。 |
check_names |
檢查套件和 repo 名稱是否有效且可用,並挑出最好的可用替代名稱。 |
login |
啟動瀏覽器登入:gh auth login --web,回傳一次性驗證碼和網址;或在終端機視窗中執行 npm login --auth-type=web。 |
job_status |
查詢進行中的登入或發布工作:狀態、輸出、網址和驗證碼。 |
scaffold_project |
建立原始碼、測試、README、LICENSE、CHANGELOG、.gitignore、manifest 和 workflow。從不覆寫檔案。target: "repo" 建立只能 clone 後建置、無法發布到套件庫的專案;private: true 讓 CI 只在 Ubuntu 上跑。 |
add_workflows |
寫入 ci.yml 和 release.yml:以 OIDC 發布、略過已存在的版本,並從 CHANGELOG 建立 GitHub release。 |
run_checks |
密鑰掃描,接著安裝、lint、型別檢查、建置和測試(npm script、Python .venv 加 pytest,或 cargo)。 |
inspect_package |
執行發布 dry run,列出會發布的檔案,並標出垃圾檔與密鑰。 |
git_commit |
需要時執行 git init -b main 並 commit。有密鑰會被 commit 時拒絕。 |
create_github_repo |
gh repo create <name> --public/--private --source . --push。私人 repo 的 CI 會用到付費的 Windows 或 macOS 分鐘數時提出警告。 |
publish_package |
npm publish(在終端機視窗中,供 2FA 核准)、twine upload 或 cargo publish。略過已存在的版本,碰到速率限制錯誤後等待 24 小時。 |
setup_trusted_publishing |
把套件連到 release.yml:npm trust github,或打開 PyPI、crates.io 設定頁並給出要填的確切數值。 |
tag_and_release |
打 v<version> tag,同時推送分支和 tag,並從 CHANGELOG 建立 GitHub release(除非 release.yml 會做)。 |
watch_workflow |
等待目前 commit 的 workflow 執行,失敗時回傳失敗的 log。 |
bump_version |
升級 patch、minor 或 major 版本,並新增 CHANGELOG 項目。 |
verify_install |
在新的暫存資料夾從真實套件庫安裝(或 clone repo),逐一執行 README 的步驟。 |
notify |
桌面通知。帶 url 時,也會打開 github.com、npmjs.com、pypi.org 或 crates.io 上的頁面。 |
run_command |
在 PowerShell(Windows)或 sh 中執行指令。具破壞性的指令會被拒絕。 |
運作原理
publish-pilot 是用 TypeScript 寫的 stdio MCP 伺服器。每個工具都包裝真正的命令列工具(git、gh、npm、uv 或 twine、cargo),並把結果回傳給 Claude。內建的流程(publish_project prompt)告訴 Claude 步驟的順序。
登入和發布這類耗時步驟會以背景工作執行,Claude 用 job_status 查詢。需要你的步驟會打開瀏覽器頁面或看得見的終端機視窗,並送出桌面通知。
安全機制內建在伺服器裡,而不是交給模型決定:
- 所有指令輸出都會被掃描,權杖(GitHub、npm、PyPI、crates.io、AWS 等)在 Claude 看到之前就換成
***。 - 有
.env檔、私密金鑰或權杖會被包含時,commit 和發布會被擋下。 - 它從不刪除、強制推送或取消發布任何東西,tag 也一樣。失敗的 release 用新的 patch 版本修正。
run_command會拒絕強制推送、刪除 tag、repo 或 release、npm unpublish、cargo yank、登出與權杖指令,以及遞迴刪除。 - 它只打開 github.com、npmjs.com、pypi.org 和 crates.io 上的
https://頁面。
它也能當函式庫使用:createServer(),加上 preflight、scaffoldProject、releaseWorkflow、scanProject 和 checkPackageName 等輔助函式,附 TypeScript 型別。
檔案
| 項目 | 位置 |
|---|---|
| npm 速率限制紀錄 | ~/.publish-pilot/rate-limits.json |
| Claude Desktop 設定 | claude_desktop_config.json(從 Settings → Developer → Edit Config 打開) |
| Claude Desktop 伺服器 log | mcp-server-publish-pilot.log,Windows 上在 %LOCALAPPDATA%\Claude\logs 或 %APPDATA%\Claude\logs |
限制與疑難排解
doctor顯示某工具 MISSING: 請 Claude 執行install_tool,或自己安裝,例如winget install --id GitHub.cli -e。然後重新啟動 MCP 用戶端,讓它讀到新的 PATH。- 伺服器在 Windows 上無法啟動(
spawn npx ENOENT、EINVAL或「Connection closed」):改用cmd /c npx -y publish-pilot-mcp的寫法並重新啟動用戶端。 npx publish-pilot-mcp無法辨識: 你是在 publish-pilot-mcp 的原始碼資料夾裡執行的。請在其他任何資料夾執行。npm publish以 E429 失敗: npm 會限制一個帳號能發布多少套件和版本。什麼都沒發布出去。不要很快重試,因為每次失敗都可能延長封鎖。publish_package會在 24 小時內拒絕重試,除非帶force呼叫。- npm 核准連結過期: 請 Claude 再呼叫一次
publish_package。每次呼叫都會開一個新連結。 - release workflow 說 tag 和版本不符:
v*tag 必須等於 manifest 的版本。請 Claudebump_version、commit 並為新版本打 tag。舊 tag 永遠不會移動。 - 從 Actions 執行
npm publish出現 404 或 401: 還沒設定 trusted publishing。執行setup_trusted_publishing;套件必須已存在於 npm。
實例
一個全新的 npm 套件,從頭到尾。
Use publish-pilot to make an npm package called csv-mini in C:\code\csv-mini that converts CSV to JSON, and publish it to both GitHub and npm.
Claude 會執行 preflight、check_names(名稱被占用時建議 @you/csv-mini)、scaffold_project,寫程式碼和測試,run_checks、inspect_package、git_commit、create_github_repo,然後 publish_package。會打開一個終端機視窗讓你做 npm 的 2FA 核准。接著 setup_trusted_publishing、tag_and_release、watch_workflow 和 verify_install。
只要 GitHub repo,不要套件。 說「just a GitHub repo」。scaffold_project 帶 target: "repo" 會寫出 clone 後建置的 README,並在 manifest 中禁止發布到套件庫。
私人 repo。 要求私人 repo。CI 只在 Ubuntu 上跑,因為私人 repo 的 Actions 分鐘數要付費,Windows 和 macOS runner 分別貴 2 倍和 10 倍。
現有套件的下一個版本。 請 Claude 發一個 patch。它會執行 bump_version、commit,再 tag_and_release;release.yml 以 OIDC 發布並建立 GitHub release。
Python 套件。 指定 PyPI 為套件庫。檢查在 .venv 中用 pytest 執行,發布使用 twine upload,trusted publishing 則依 Claude 給的數值在 PyPI 設定頁上設定。
Rust crate。 指定 crates.io。檢查使用 cargo,第一版用 cargo publish 發布,之後的版本從 GitHub Actions 發布。
特殊情況
- 名稱被占用:
check_names會挑出最好的可用替代名稱,例如 npm 上帶 scope 的@you/name。 - 沒登入:
login會啟動瀏覽器登入;由你完成。 - 專案中有密鑰: 在移除前,commit 和發布都會被拒絕。
- 版本已發布:
publish_package會略過,release.yml也會略過已存在的版本。 - release 失敗: 不會刪除或移動任何東西。升到新的 patch 版本再發布一次。
- npm 速率限制(E429):
publish_package在 24 小時內拒絕重試,除非帶force呼叫。 - 已存在的檔案:
scaffold_project從不覆寫。 - Claude 想打開的連結: 只限 github.com、npmjs.com、pypi.org 和 crates.io 上的
https://頁面。
常見問題
它會儲存我的權杖嗎? 不會。它使用你現有的 gh 和套件庫登入,release 以 OIDC 發布。
它會輸入我的密碼嗎? 不會。它從不輸入密碼或 2FA 驗證碼,也從不按 Authorize、Approve 或 Save。
為什麼會打開終端機視窗? npm 只在真正的終端機中顯示核准連結。
我可以繼續用電腦嗎? 可以。它透過命令列工作,不是控制你的畫面。
它能在哪些用戶端使用? Claude Code、Claude Desktop,以及任何能執行 stdio 伺服器的 MCP 用戶端。
它能刪除或取消發布東西嗎? 不能,而且 run_command 會拒絕會這樣做的指令。
它和 shipkit 有什麼不同? 做的事一樣;publish-pilot 是 MCP 伺服器,shipkit 是 CLI 加上 Claude Code skill 和 hook,每回合花的 token 比較少。
需要 Node 嗎? 需要,Node.js 22 或更新版本。
版本與原始碼
本頁說明 publish-pilot 0.4.0。