返回资讯中心
外部精选
软件工程
#开发者实时流

Show HN: Shipback – SFTP deploys your AI agent can undo

It's late, and the agent says "Deployed ✓". Then the client's contact form is gone. The agent overwrote a

Hacker News 最新aldoh2026/10/18 · 19 天前16 分钟阅读

以下正文同步自 Hacker News 最新,版权归原站所有,已转换为易读排版。

It's late, and the agent says "Deployed ✓". Then the client's contact form is gone. The agent overwrote a file someone had fixed by hand in cPanel last week, and shared hosting has no git revert.

Shipback deploys a folder to any SFTP host: cPanel, Plesk, DirectAdmin, a plain VPS. Every deploy can be undone with one command. You can run it yourself, script it, or hand it to Claude Code, Cursor or any MCP client.

No git or SSH shell is needed on the server, just SFTP. It needs Node 18+. The tests run on Windows, macOS and Linux with Node 18, 20 and 22 on every push. Passwords are kept in the OS keychain and never pass through the model.

It has run in production. The deploy engine underneath has shipped aldo.today 235 times since September 2026 (2,907 files to a cPanel host). Restore and the MCP server are new in 0.1.

npm install -g shipback-sftp # installs the shipback and shipback-mcp commands cd ~/sites # any folder with a sites.json in it (format below) shipback mysite --dry-run # see the plan; asks for the password once and stores it shipback mysite # deploy shipback mysite --restore # changed your mind? undo it

No global install? npx -p shipback-sftp shipback mysite --dry-run works the same way. --sites <file> points at a sites.json in another folder.

From source: git clone https://github.com/aldohushi1-stack/shipback-sftp.git, npm install, then node bin/cli.js wherever these docs say shipback.

{ "sites": [ { "name": "mysite", "host": "server123.example-host.com", "port": 22, "username": "cpaneluser", "remoteRoot": "/home/cpaneluser/public_html", "localDir": "/Users/you/sites/mysite", "ignore": ["drafts/", "*.psd"] } ] }

Many shared hosts run SFTP on their own port rather than 22 (check SSH Access in your control panel), and some only accept connections from allow-listed IPs. If a connection times out, check those two first. Use "privateKeyPath" instead of a password if your host has your key.

shipback <site> --dry-run # what a deploy would upload shipback <site> # deploy: backup, upload, record shipback <site> --local <folder> # deploy a different folder than localDir shipback <site> --pull --dry-run # what changed on the server since the last deploy? shipback <site> --pull # bring those changes down (local copies backed up first) shipback <site> --backups # list backups: what each run overwrote, added, deleted shipback <site> --restore --dry-run # what an undo of the latest deploy would do shipback <site> --restore [<backup>] # undo it (or name an older _backup-… folder) shipback <site> --prune --keep 10 # tidy old backups; refuses any holding the only copy of a file shipback --history [site] # what went up, when, from where

Add --json to any command for machine-readable output. A refused restore exits with code 4.

--mirror (delete server files that aren't in the local folder) and --no-backup exist for humans who know they want them. The agent tools don't offer them, and the guard hook blocks Claude from typing them.

Each deploy writes _backup-YYYY-MM-DD-HHMM/ in the remote root. It holds:

--restore reads that record and checks each live file first:

Before writing anything, restore saves the current live files into a new _backup-… folder with its own record, so --restore on that folder takes you forward again. It also clears the restored paths from .deploy-manifest.json, so the next deploy compares them by content instead of trusting stale hashes.

Backup folders are skipped by deploys and pulls, and are never deleted except by --prune.

shipback-mcp (bin/mcp.js) is an MCP server over stdio.

claude mcp add shipback-sftp -- npx -y -p shipback-sftp shipback-mcp --sites /path/to/sites.json

Cursor, Claude Desktop, and others (mcp.json / claude_desktop_config.json):

{ "mcpServers": { "shipback-sftp": { "command": "npx", "args": ["-y", "-p", "shipback-sftp", "shipback-mcp", "--sites", "/path/to/sites.json"] } } }

On Windows, if the client can't start npx, use "command": "cmd" with "/c", "npx" at the front of args. After a global install, "command": "shipback-mcp" works too, and from a clone it's node with bin/mcp.js as the first arg.

Run any CLI command for a site once first (for example shipback mysite --backups). That stores the password in the OS keychain, where the MCP server reads it. The model never sees it. For CI you can set SFTP_PASSWORD in the server's environment instead.

What the tools leave out is deliberate: there is no mirror/delete, no way to skip the backup, and no pruning of backups.

Some agent setups can write files but can't run commands. While the local app is running (npm start, or start.bat on Windows), anything that can write a file can queue a job:

queue/<name>.request.json { "action": "deploy", "site": "mysite", "dryRun": true, "note": "new homepage" } queue/<name>.result.json ← written when it finishes, with a .log.txt beside it

Actions: deploy, preview, pull, restore, backups, prune.

npm start opens a small UI on http://127.0.0.1:4646: add sites, preview, deploy, pull, drag in one-off uploads, browse the server, and see history. It only answers requests from your own machine.

If Claude also runs the CLI directly, add bin/claude-guard.js as a PreToolUse hook. It blocks --mirror and --no-backup in shell commands, queue files and API calls, and tells Claude why. You can still run them yourself in a terminal. After npm install -g shipback-sftp, the file is in the folder npm root -g prints, under shipback-sftp/bin/.

{ "hooks": { "PreToolUse": [ { "matcher": "Bash|PowerShell|Write|Edit|MultiEdit", "hooks": [{ "type": "command", "command": "node /path/to/shipback-sftp/bin/claude-guard.js" }] } ] } }

Tests

npm test

The suite uses node:test and needs no network. Deploy, restore, the CLI and the MCP server are each also exercised end to end against a real SFTP server started inside the test run.

It compares by size and SHA-256. The first deploy to a site that already has files reads the server copies of any same-size files to compare them.

Backups live on the same server as the site. They protect against bad deploys, not against losing the hosting account. Keep your host's own backups too.

Files over 8 MB with the same size on both sides are assumed unchanged when there is no manifest hash to compare.

License

MIT © 2026 Aldo Hushi

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →