Auto-sync
Five ways to keep your repowise wiki current as code changes: post-commit hook, file watcher, GitHub webhook, GitLab webhook, and a polling safety net.
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.
Upgrading
Upgrade the repowise package, run repowise update, and your existing index keeps working. No reindex in the normal case; a full reindex is only ever recommended, never forced.
Git worktrees
Index a linked git worktree without re-indexing from scratch, by seeding from the base checkout and catching up incrementally.