Skip to content
vibstrVibstr home
Open Vibstr

Generic git hooks

Vibstr ships from ANY git workflow. The Claude Code page is the opinionated path — auto-changelog generation, AI semantic matching, BYO Anthropic key. This page is the generic path. Works with vanilla git, Husky, Lefthook, GitHub Actions, GitLab CI — anything that can run a script on commit or push.

💡 For the Claude Code-specific deep dive (auto-changelog generation, AI semantic matching, BYO Anthropic key, derive items from plans), see Claude Code integration.

What we are wiring

The auto-close path is the same one Claude Code uses. The only difference is what triggers it. Claude Code teams have the curl inside CLAUDE.md. Everyone else wires a hook.

Where to find your API key

  1. Open Vibstr → click the gear icon (top-right) to open Settings
  2. PROJECT section → click Connect Claude Code (the section is named after the original integration but the key works for any caller)
  3. The API key is shown masked (••••••••-1234). Click the eye icon to reveal, copy icon to copy
  4. Paste it into the VIBSTR_API_KEY line at the top of your script

The API key authenticates as the project, not a specific user. Anyone with the key can post builds to that project. Treat it as a secret — do not commit it into git. Use a .env file, a GitHub Actions secret, or your hook's environment.

If the key is ever exposed, regenerate it: same pane → Regenerate API key → confirm. Old key dies immediately.

Bash post-commit script

Drop this into .git/hooks/post-commit. Works on macOS, Linux, and Windows with Git for Windows / WSL.

#!/usr/bin/env bash
# Vibstr post-commit hook
# Install: copy to .git/hooks/post-commit and chmod +x

VIBSTR_API_KEY="YOUR_PROJECT_API_KEY_HERE"
VIBSTR_URL="https://abtludluoynmwdfyvrse.supabase.co/functions/v1/super-function"

# Capture commit metadata
COMMIT_HASH=$(git rev-parse --short HEAD)
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
VERSION=$(node -p "require('./package.json').version" 2>/dev/null || echo "")

# Build the JSON payload via node so newlines, quotes, and special chars
# in the commit body are JSON-encoded safely. Shell-string interpolation
# breaks the moment a commit body has a newline or a backtick.
PAYLOAD=$(node -e "
const msg = process.argv[1];
const hash = process.argv[2];
const ver = process.argv[3];
console.log(JSON.stringify({
  api_key: '$VIBSTR_API_KEY',
  prompt: 'git post-commit hook',
  output: 'Auto-reported from git hook',
  version: ver,
  commit_hash: hash,
  commit_message: msg,
}));
" "$COMMIT_MESSAGE" "$COMMIT_HASH" "$VERSION")

# Send the request. Fail silently if Vibstr is down — a hook that
# crashes the commit is worse than a hook that drops one report.
curl -s -X POST "$VIBSTR_URL" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD" > /dev/null 2>&1 || true

Install

# 1. Copy the script above into .git/hooks/post-commit
nano .git/hooks/post-commit

# 2. Make it executable
chmod +x .git/hooks/post-commit

# 3. Edit VIBSTR_API_KEY at the top — get it from Settings → PROJECT → Connect Claude Code

Test it: make a commit with closes #1 in the body, then check the Builds tab in Vibstr. Item #1 should be in the closed list with a match_source: 'commit_msg' tag in its activity log.

Husky variant

If your repo uses Husky, put the same body in .husky/post-commit instead:

npx husky add .husky/post-commit ""
# Then open .husky/post-commit and paste the bash script body (without the shebang at the top — Husky adds its own).

The script content is identical. Husky just runs it via a different mechanism.

PowerShell post-commit (Windows)

For Windows users not using WSL or Git for Windows. Save as .git/hooks/post-commit.ps1 and create a wrapper to call it.

# Vibstr post-commit hook (PowerShell)
# Install: save as .git/hooks/post-commit.ps1, wire a batch wrapper

$VIBSTR_API_KEY = "YOUR_PROJECT_API_KEY_HERE"
$VIBSTR_URL = "https://abtludluoynmwdfyvrse.supabase.co/functions/v1/super-function"

# Capture commit metadata
$COMMIT_HASH = (git rev-parse --short HEAD).Trim()
$COMMIT_MESSAGE = (git log -1 --pretty=%B).Trim()
$VERSION = if (Test-Path "package.json") {
  (Get-Content package.json | ConvertFrom-Json).version
} else {
  ""
}

# Build payload — ConvertTo-Json handles newlines + quotes safely
$body = @{
  api_key = $VIBSTR_API_KEY
  prompt = "git post-commit hook"
  output = "Auto-reported from git hook (PowerShell)"
  version = $VERSION
  commit_hash = $COMMIT_HASH
  commit_message = $COMMIT_MESSAGE
} | ConvertTo-Json -Depth 5 -Compress

# Send request. Fail silently — never block a commit.
try {
  Invoke-RestMethod -Uri $VIBSTR_URL -Method Post -ContentType "application/json" -Body $body | Out-Null
} catch {
  # Silent fail
}

Wrapper at .git/hooks/post-commit (no extension — git looks for this exact filename):

@echo off
powershell -ExecutionPolicy Bypass -File "%~dp0post-commit.ps1"

The batch file is the actual hook git invokes. It bootstraps PowerShell with the right execution policy and runs the .ps1 file.

GitHub Actions workflow

For teams without local git hooks — CI-driven workflows where the build report fires from the runner, not from a developer's machine. Save as .github/workflows/vibstr-report.yml:

name: Report build to Vibstr

on:
  push:
    branches: [main, master]

jobs:
  report-vibstr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 2

      - name: Capture metadata
        id: meta
        run: |
          echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
          {
            echo "commit_message<<EOF"
            git log -1 --pretty=%B
            echo "EOF"
          } >> $GITHUB_OUTPUT
          if [ -f package.json ]; then
            echo "version=$(node -p \"require('./package.json').version\")" >> $GITHUB_OUTPUT
          fi

      - name: Report to Vibstr
        env:
          VIBSTR_API_KEY: ${{ secrets.VIBSTR_API_KEY }}
          COMMIT_HASH: ${{ steps.meta.outputs.commit_hash }}
          COMMIT_MESSAGE: ${{ steps.meta.outputs.commit_message }}
          VERSION: ${{ steps.meta.outputs.version }}
        run: |
          PAYLOAD=$(node -e "
            console.log(JSON.stringify({
              api_key: process.env.VIBSTR_API_KEY,
              prompt: 'GitHub Actions push',
              output: 'Auto-reported from GitHub Actions',
              version: process.env.VERSION || '',
              commit_hash: process.env.COMMIT_HASH,
              commit_message: process.env.COMMIT_MESSAGE,
            }));
          ")
          curl -s -X POST "https://abtludluoynmwdfyvrse.supabase.co/functions/v1/super-function" \
            -H "Content-Type: application/json" \
            -d "$PAYLOAD"

Setup

  1. Save the file at .github/workflows/vibstr-report.yml and commit it
  2. GitHub repo → Settings → Secrets and variables → Actions → New repository secret
  3. Name: VIBSTR_API_KEY, Value: your project's API key (from the Vibstr Settings pane)
  4. Push to main → workflow runs → build reports to Vibstr

The env: block pipes secrets into the script rather than inlining them as ${{ }} interpolation. This matters: it stops the commit message body (which might contain backticks or $ characters) from being shell-interpreted before node -e ever sees it.

Troubleshooting

401 Unauthorized — the API key is wrong or stale. Open Settings → PROJECT → Connect Claude Code, re-copy, paste fresh.

403 Forbidden — the project the key belongs to was deleted, or the key was regenerated and you have the old value. Regenerate again, copy the new key.

Nothing happens, no error — your hook fired but the request never landed. Check that your network can reach https://abtludluoynmwdfyvrse.supabase.co. Some corporate proxies block Supabase URLs. Try the curl manually from your terminal: if that works but the hook does not, the issue is in the hook's environment (PATH, permissions, working directory).

#NN references not closing items — verify the items are open or checking status (already-closed items do not re-close). Verify the project's items table actually has the numbers you referenced (item numbers are per-project, not global). Build cards on the Builds tab show which references parsed and which did not.

Closing the loop

The deterministic #NN parser is the same one Claude Code uses. The auto-ingest endpoint does not care how the build was reported — it parses, matches, closes, writes the activity log. Your team gets the same closing behaviour whether you wire a hook, a CI job, or paste the Claude Code curl into CLAUDE.md.

Want the Claude Code-specific deep dive (auto-changelog generation, AI semantic matching, BYO Anthropic key)? Read Claude Code integration.

Open Vibstr →