The Claude /deploy skill felt convenient at first. One command and it handled everything — SSH connection, docker compose restart, the works. But every deployment burned tokens. Run the skill, check server status, handle errors, retry. A few rounds of that and I was burning a surprising number of tokens on something completely mechanical.
It Started with a Self-Hosted Runner Rabbit Hole
When I first set up CI/CD for trading_mvp, I went through the GitHub website to register a self-hosted runner. That meant going into the Actions tab, running the install script, registering the runner daemon on the server, and setting it up as a persistent service. The setup itself wasn’t hard, but it changed the server’s structure. My usual workflow was just ssh hong and poke around directly — having a runner process operating in its own separate context made it hard to track what was actually running where.
While figuring out how to add deployment for slowloop-lab on top of that, I came across appleboy/ssh-action.
One yml + Four Secrets + One Line in authorized_keys
The mechanics turned out to be straightforward: a GitHub cloud runner SSH’s into your server and runs a command. On the server side, all you add is one dedicated key line in authorized_keys. No runner daemon, no service registration, no changes to the server’s internal structure. The workflow stays exactly like my usual ssh hong flow.
I set everything up with gh CLI in a single session:
# Generate a dedicated key
ssh-keygen -t ed25519 -f /tmp/deploy_app -N "" -C "gha-deploy-app"
# Register the public key on the server
cat /tmp/deploy_app.pub | ssh hong 'cat >> ~/.ssh/authorized_keys'
# Register secrets in the repo (no GitHub website needed)
gh secret set SSH_HOST --body "korat.iptime.org"
gh secret set SSH_USER --body "hong"
gh secret set SSH_PORT --body "22"
gh secret set SSH_PRIVATE_KEY < /tmp/deploy_app
# Clean up local keys
rm /tmp/deploy_app /tmp/deploy_app.pub
Add appleboy/ssh-action@v1 to the workflow yml, set the push trigger branch, and you’re done. I validated it on slowloop-lab on 2026-06-24, then applied the exact same setup to hansaiam the next day. The hansaiam /deploy skill got deleted.
The One Thing That Tripped Me Up
Early in the slowloop-lab setup, I pushed the workflow file before registering the secrets. Every run died within 10 seconds with “missing server host” — and nobody noticed until I actually opened the Actions tab. Always check the first run log right after switching over. Missing secrets fail silently.
What I Took Away
Deploying via Claude skill feels like “AI is handling it for me, how convenient” — but in reality, that convenience has a token cost attached. Skills make sense for one-off tasks or situations that require judgment. Routine deployments don’t qualify.
SSH-action is one yml file and four secrets. Far simpler than the runner approach, and the server stays clean.