A typical single-commit update touches 3 to 10 pages and completes in about 30-60 seconds. The question isn't whether to auto-sync; it's which method fits your workflow. Pick one (or combine them).
| Method | Command / setup | Best for |
|---|---|---|
| Post-commit hook | repowise hook install | Solo dev, set-and-forget |
| File watcher | repowise watch | Active iteration without committing |
| GitHub webhook | server + REPOWISE_GITHUB_WEBHOOK_SECRET | Teams, CI/CD |
| GitLab webhook | server + REPOWISE_GITLAB_WEBHOOK_TOKEN | Teams on GitLab |
| Polling fallback | automatic with repowise serve | Safety net for missed webhooks |
Post-commit hook
Runs repowise update in the background after every local commit
without blocking the terminal.
repowise hook install # current repo
repowise hook install --workspace # all workspace repos
repowise hook status # check if installed
repowise hook uninstall # remove the hookThe hook is marker-delimited, so it coexists safely with other hooks
(linters, formatters). If it doesn't fire, make sure
.git/hooks/post-commit is executable: chmod +x .git/hooks/post-commit.
File watcher
Watches the working directory for file saves and triggers an update without requiring a commit. Best when you want the wiki current between commits. Unlike the post-commit hook, the watcher indexes the working tree, so staged, unstaged, and untracked files all reach the index without a commit.
repowise watch # current dir
repowise watch --debounce 5000 # wait 5s after the last change (default 2s)
repowise watch --workspace # all repos in a workspace
repowise watch --index-only # no model calls per saveChanges inside .repowise/ are ignored to prevent loops. Press Ctrl+C
to stop. Best for short bursts, not a long-running daemon. On a repo
indexed with docs, each trigger regenerates the changed files' pages
with a model; use --index-only to keep the index current for free and
leave the prose for a later repowise update.
GitHub webhook
Self-hosted teams point GitHub at repowise serve's webhook endpoint;
push events trigger incremental updates. HMAC-SHA256 signature
verification is mandatory.
repowise serve # starts on :7337
export REPOWISE_GITHUB_WEBHOOK_SECRET="your-secret"Then in GitHub: Settings → Webhooks → Add webhook
- Payload URL:
https://your-server.example.com/api/webhooks/github - Secret: same value as
REPOWISE_GITHUB_WEBHOOK_SECRET - Events: Push events only
Successful deliveries return 200 with {"status": "accepted"}. With a
secret configured, a missing or invalid signature returns 401.
If you leave REPOWISE_GITHUB_WEBHOOK_SECRET unset, the endpoint fails
closed for anything remote: non-local callers get 403. Local callers on
loopback are still accepted, which keeps development convenient, so treat
an unset secret as dev-only and always set one on an exposed server.
Check Settings → Webhooks → Recent Deliveries for diagnostics.
GitLab webhook
Same idea, token-based auth via the X-Gitlab-Token header.
export REPOWISE_GITLAB_WEBHOOK_TOKEN="your-token"In GitLab: Settings → Webhooks
- URL:
https://your-server.example.com/api/webhooks/gitlab - Secret token: same value as
REPOWISE_GITLAB_WEBHOOK_TOKEN - Trigger: Push events
Tokens are verified via constant-time comparison.
Polling fallback
When repowise serve is running, a background job polls registered
repos every 15 minutes. If a webhook delivery fails, polling catches
the missed push and triggers an update.
No configuration needed. Just don't rely on this alone: it has a 15-minute lag.
CLI update vs. server sync
The CLI (repowise update) and the server (POST /api/repos/{id}/sync,
which webhooks and polling trigger) take different paths, and the
difference is cost-relevant:
repowise updatediffs against the last synced commit, rebuilds the dependency graph, re-indexes git metadata for changed files, runs partial dead-code analysis, re-scans for decisions, then calls the LLM to regenerate only the affected pages.- Server sync re-traverses and re-parses every file, rebuilds the
graph, re-indexes git metadata, and runs a full dead-code and decision
scan, but it does not regenerate wiki pages, so it makes no LLM
calls. Use Full Re-index (
POST /api/repos/{id}/full-resync) to also regenerate all wiki pages after a server sync.
So a webhook-triggered sync keeps the graph and metadata current for free; the prose only catches up once you run a CLI update or trigger a full re-index.
Troubleshooting
"No previous sync found": run repowise init first to create the
initial wiki before using any auto-sync method.
"Already up to date": the wiki is already synced to the latest commit. Nothing to do.
Hook doesn't fire: make sure the hook file is executable:
chmod +x .git/hooks/post-commit.
Webhook returns 401: check that the secret/token matches between your git hosting provider and the environment variable on the server.
Webhook returns 403: the server received a request with no
signature at all. This usually means REPOWISE_GITHUB_WEBHOOK_SECRET
(or REPOWISE_GITLAB_WEBHOOK_TOKEN) is not set on the server. Set the
environment variable, restart the server, and re-deliver the payload
from your provider's webhook settings page.
Hosted version
If you're on repowise.dev, webhook setup is automatic. Installing the GitHub App registers the webhook, and pushes auto-sync the index without you doing anything.
Belt and braces: combine the post-commit hook (local) with a GitHub webhook (server). Local commits sync instantly; pushes from other branches keep the server in sync. The polling fallback catches the rare miss.