donnfelker/kamal-skills · Archived

hooks

Write and wire up Kamal deploy hooks — scripts in `.kamal/hooks` (docker-setup, pre-connect, pre-build, pre-deploy, post-deploy, pre-app-boot, post-app-boot, pre-proxy-reboot, post-proxy-reboot) that run at fixed points in a deploy, plus the `KAMAL_*` env vars (`KAMAL_VERSION`, `KAMAL_PERFORMER`, `KAMAL_HOSTS`, `KAMAL_RECORDED_AT`) passed to them for audit reporting, deploy notifications, CI gates, and load-balancer draining. Use when the user says "add a deploy hook," "run a script before/afte…

First seen Jul 6, 2026

Installation

$ npx skills add donnfelker/kamal-skills --skill hooks

Summary

  • Write and wire up Kamal deploy hooks — scripts in `.kamal/hooks` (docker-setup, pre-connect, pre-build, pre-deploy, post-deploy, pre-app-boot, post-app-boot, pre-proxy-reboot, post-proxy-reboot) that run at fixed points in a deploy, plus the `KAMAL_*` env vars (`KAMAL_VERSION`, `KAMAL_PERFORMER`, `KAMAL_HOSTS`, `KAMAL_RECORDED_AT`) passed to them for audit reporting, deploy notifications, CI gates, and load-balancer draining.
  • Use when the user says "add a deploy hook," "run a script before/after deploy," "post-deploy notification," "fail the deploy if CI hasn't passed," "block deploys unless I'm on the VPN," "run a script when kamal-proxy reboots," "where do hooks live," "hooks_path," "hooks_output," "skip hooks," or "what are the KAMAL_ env vars." Covers the `.kamal/hooks` folder from `kamal init`, naming rules, non-zero exit aborting the command, `hooks_path`/`hooks_output`, and `--skip-hooks`.
  • For the deploy sequence these fire within, see deploy.
  • For builds, see build.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from donnfelker/kamal-skills · top by installs.

npx skills add donnfelker/kamal-skills

Browse all from donnfelker/kamal-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
More metadata
version
1.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,082 B
  • docs SUMMARY.md 1,002 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Deploy Hooks

You are an expert in extending Kamal deploys with hooks. Your goal is to run the right custom script at the right point in a deploy — pre-flight checks, build gates, deployment notifications, load-balancer draining — and to read the KAMAL_* environment variables Kamal passes in so those scripts know what is being deployed, by whom, and where.

Before You Start

Read what already exists before asking the user questions:

  • .kamal/hooks/ — the default hooks folder. kamal init creates it with sample scripts. List it to see which hooks are already wired up.
  • config/deploy.yml — check for a hookspath (custom location) or hooksoutput (output visibility) setting.
  • .kamal/secrets — if a hook needs a token (for a webhook, an APM key), it is read from here.

How Hooks Work

Hooks let you run custom scripts at specific points during Kamal commands.

  • Hooks live in the .kamal/hooks folder by default. Change the location with hooks_path (see [Configuring Location and Output](#configuring-location-and-output)).
  • The hook filename must be the hook name with no extension — for example pre-deploy, not pre-deploy.sh or pre-deploy.rb.
  • If a hook script returns a non-zero exit code, the command is aborted. This is how a pre-deploy or pre-build hook gates a deploy.
  • Kamal passes KAMAL environment variables into every hook so the script knows what is happening (see [KAMAL Environment Variables](#kamal-env)).
  • Skip all hooks for one command with --skip-hooks (see [Skipping Hooks](#skipping-hooks)).

Running kamal init scaffolds the folder and drops in sample scripts you can edit or delete.

The Available Hooks

Each hook fires at a documented point. Name your script exactly as the hook name.

Hook When it runs Typical use
docker-setup Once Docker is installed on a server, before any app-specific actions Configure Docker itself
pre-connect Before taking the deploy lock, before connecting to remote hosts DNS warming, checking you are on the VPN
pre-build Before the image build Ensure no uncommitted changes, or that CI has passed
pre-deploy Final checks before deploying Check CI completed
post-deploy After a deploy, redeploy, or rollback Broadcast a deployment message, register the version with an APM
pre-app-boot Before booting the app container (kamal app boot, or via kamal deploy) Prepare for the new container
post-app-boot After booting the app container (kamal app boot, or via kamal deploy) Verify or announce the new container
pre-proxy-reboot Before rebooting the kamal-proxy container (kamal proxy reboot) Drain a server from an external load balancer
post-proxy-reboot After rebooting the kamal-proxy container Re-enable the server in the load balancer

For the full detail on each hook — including the grouped-boot and rolling-reboot behaviors — see [references/hook-reference.md](references/hook-reference.md).

Walk-Through: Add a Hook

Step 1 — Create the hook file

Put a script in .kamal/hooks named exactly after the hook, with no extension. For a pre-deploy gate:

# .kamal/hooks/pre-deploy

Give it a shebang and make it executable — Kamal runs the file directly:

chmod +x .kamal/hooks/pre-deploy

Step 2 — Write the script and exit non-zero to abort

A non-zero exit code aborts the command, so a pre-deploy or pre-build hook can stop a bad deploy before it starts:

#!/usr/bin/env bash
# .kamal/hooks/pre-build — refuse to build with uncommitted changes
if [ -n "$(git status --porcelain)" ]; then
  echo "Uncommitted changes present — commit before deploying." >&2
  exit 1
fi

Step 3 — Use the KAMAL_* variables

Kamal passes context in as environment variables. Read them to make the script aware of the version, performer, and target hosts:

#!/usr/bin/env bash
# .kamal/hooks/pre-deploy
echo "Deploying ${KAMAL_VERSION} to ${KAMAL_HOSTS} as ${KAMAL_PERFORMER}"

Step 4 — Deploy

Run your command as usual. The hooks fire at their points automatically:

kamal deploy

If you need to deploy without running any hooks this once, add --skip-hooks.

KAMAL_* Environment Variables

These variables are available to every hook command, intended for fine-grained audit reporting — triggering deployment reports or firing a JSON webhook:

Variable Value
KAMALRECORDEDAT UTC timestamp in ISO 8601 format, e.g. 2023-04-14T17:07:31Z
KAMAL_PERFORMER The local user performing the command (from whoami)
KAMAL_SERVICE The service name, e.g. app
KAMALSERVICEVERSION Abbreviated service and version for messages, e.g. app@150b24f
KAMAL_VERSION The full version being deployed
KAMAL_HOSTS Comma-separated list of the hosts targeted by the command
KAMAL_COMMAND The command being run
KAMAL_SUBCOMMAND Optional: the subcommand being run
KAMAL_DESTINATION Optional: destination, e.g. staging
KAMAL_ROLE Optional: role targeted, e.g. web

The post-deploy hook additionally receives KAMAL_RUNTIME, set to the total seconds the deploy took.

Worked Example: A post-deploy Notification

The post-deploy hook runs after a deploy, redeploy, or rollback — a natural place to broadcast a deployment message or register the new version with an APM. This example posts a line to a preconfigured chatbot:

#!/usr/bin/env bash
# .kamal/hooks/post-deploy
curl -q -d content="[My App] ${KAMAL_PERFORMER} Rolled back to version ${KAMAL_VERSION}" https://3.basecamp.com/XXXXX/integrations/XXXXX/buckets/XXXXX/chats/XXXXX/lines

That posts a message like:

[My App] [dhh] Rolled back to version d264c4e92470ad1bd18590f04466787262f605de

Because post-deploy also gets KAMAL_RUNTIME, you can include the deploy duration in the message.

Configuring Location and Output

Both keys go in the root of config/deploy.yml.

hooks_path

Path to the hooks folder. Defaults to .kamal/hooks. Override it to keep hooks elsewhere:

hooks_path: /user_home/kamal/hooks

hooks_output

Controls hook output visibility. Set it globally or per-hook. CLI flags (-v, -q) override these settings.

Value Effect
:quiet Hook output is hidden
:verbose Hook output is shown

With no setting, hook output follows the CLI verbosity flags. Failed hooks always show their output in the error message regardless of this setting.

Global setting for all hooks:

hooks_output: :verbose

Or per-hook:

hooks_output:
  pre-deploy: :verbose
  pre-build: :quiet

Skipping Hooks

Pass --skip-hooks (-H) to run a command without its hooks:

kamal deploy --skip-hooks

Use it when you need to bypass a gate for a one-off deploy. For how --skip-hooks fits into the deploy command's other flags, see the deploy skill.

Quick Reference

Goal How
Scaffold the hooks folder with samples kamal init
Add a hook Create .kamal/hooks/<hook-name> (no extension), make it executable
Gate / abort a command Exit the hook script with a non-zero code
Know the version / performer / hosts in a hook Read KAMALVERSION, KAMALPERFORMER, KAMAL_HOSTS
Get the deploy duration Read KAMAL_RUNTIME in post-deploy
Move the hooks folder hooks_path: in config/deploy.yml
Show or hide hook output hooks_output: :verbose / :quiet (global or per-hook)
Run a command without hooks --skip-hooks (-H)

Related Skills

  • deploy: For the full kamal deploy / kamal redeploy sequence these hooks fire within, and the other flags that pair with --skip-hooks.
  • build: For the kamal build step where the pre-connect and pre-build hooks run.