Every push, already deployed
Two lines in the root of your repo install a pre-push hook. After that the site goes up on its own, off the command you already type — no CI service, no tokens in the project, nothing new to remember.
You need the CLI and a git repo. Node 18 or newer, and a folder you have deployed at least once.
printf '#!/bin/sh\nharvis deploy .\n' > .git/hooks/pre-push chmod +x .git/hooks/pre-push
Set it up once, forget it
The hook does not replace the CLI, it types it for you. So the first deploy still happens by hand — that is the one that creates the site the hook will keep updating.
- 01
Link the project
Run "harvis" once in the folder you want online. That first deploy creates the site and records it, so every later run updates the same address.
- 02
Install the hook
Paste the two-line command below into the root of your repo. It writes the script git looks for and marks it executable.
- 03
Push
From then on "git push" deploys first and pushes second. If the deploy fails, the push stops with it.
Write your hook
Name the folder you publish and the command below is the one to run. It writes .git/hooks/pre-push and makes it executable — git runs that script before it sends anything to the remote.
The folder holding the finished site. "." is the repo root, which is right for hand-written HTML; a static-site generator writes somewhere else.
Runs the build first, with "set -e" above it — so a failed build stops the push instead of republishing whatever the folder held last time.
pre-push fires on every branch and every remote, so a feature branch would publish over your live site. With this on, a push from anywhere else exits early and goes through untouched.
printf '#!/bin/sh\nharvis deploy .\n' > .git/hooks/pre-push chmod +x .git/hooks/pre-push
Whatever folder you pick, hidden files, node_modules and OS junk are skipped, so a repo root never uploads its own plumbing. It does upload your source, though — point the hook at a build folder if that is not what you want online.
Where this trips people up
Deploy once by hand first
The first deploy is what creates the site and links the folder to it. Skip it and the hook has nothing to update: every push publishes a brand-new site at a brand-new address.
A failed deploy blocks the push
That is the point of pre-push, and usually what you want. If you would rather push anyway, end the line with "|| true". To skip the hook for a single push, use "git push --no-verify".
Hooks are not committed
.git/hooks belongs to your clone, so a teammate who clones the repo gets nothing. To share it, commit a .githooks folder and have everyone run "git config core.hooksPath .githooks" once.
The deploy token is not in your repo
It lives in ~/.config/harvis/credentials.json, on your machine only. The harvis.json the CLI writes into the project holds the site name and nothing else, so it is safe to commit — and once it is, a teammate's clone deploys to the same site rather than a new one.
Desktop git clients have their own PATH
Hooks run in a bare shell, and GUI clients often start without the PATH your terminal has — a Node installed through nvm is the usual casualty. If it works in the terminal but not in the app, call the CLI by the absolute path that "which harvis" prints.
Windows runs hooks through Git Bash
Git for Windows executes hooks with the bundled sh, so paste the command into Git Bash rather than PowerShell and it works as written.
Questions
Should I use pre-push or post-commit?
pre-push is the sane default: it runs once per push, so an afternoon of five commits is one deploy rather than five. Use post-commit if you want every single commit live, or post-merge if you want a teammate's changes to publish when you pull them.
Does it upload my .git folder or node_modules?
No. Anything starting with a dot — .git, .env, .github — plus node_modules and OS junk files are skipped on every deploy, hook or not. Your source files are uploaded though, so if the repo holds more than the site, point the hook at the build folder instead of the dot.
Do I need an account for this?
No. Deploys are anonymous and the hook works the same either way. But an unclaimed site expires 24 hours after its last deploy, so if this site is meant to stay online, open the claim link from the first deploy and sign in once.
How do I give the hook to the rest of the team?
Commit the script as .githooks/pre-push and have everyone run "git config core.hooksPath .githooks" after cloning. Git will not enable hooks from a repo on its own — that would let a clone run code on your machine — so that one command per person is unavoidable.
Can I deploy from CI instead of from my laptop?
Yes, and for a shared project that is usually the better answer. Put the site's deploy token in your CI environment as HARVIS_DEPLOY_TOKEN and run "harvis deploy dist" from the pipeline; there is a GitHub Action that wraps the same thing. A git hook is the version that needs nothing but your own machine.
Can I use npx in the hook instead of installing the CLI?
"npx harvis deploy ." works, but it resolves the package on every push and needs Node on the hook's PATH, which is exactly where desktop git clients fall over. A global install makes the hook faster and less fragile.
How do I remove the hook?
Delete the file: "rm .git/hooks/pre-push". Nothing else changes — the site stays online and you can keep deploying by running the CLI yourself.
Start with one deploy
The hook only automates a command you can already run. Install the CLI, run it in your folder, and you have a live URL before you write a single line of shell.