Docs/GitHub Integration

GitHub Integration

Updated 2026-08-10

GitHub Integration

Connect a repository to a PonderOS workspace and your commits find their own tasks. Mention a ticket in the commit message — fix: handle empty payload (inbox-10) — push, and the commit appears on task inbox-10, linked back to GitHub.

No branch conventions to follow, no bot to install, no PR template to fill in. Write the ticket in the message like you probably already do.


#Before you start

This integration is workspace-only and admin-only:

  • You need a shared workspace. There is no GitHub section in a personal space — if you're working solo in your own vault, switch to (or create) a workspace first. Local mode has no shared workspaces, so neither the integration nor the Commits section is available there.
  • You need to be an owner or admin of that workspace. Members and viewers won't see the section at all. If a teammate says the setting isn't there, that's why.
  • You'll need admin rights on the GitHub repository too, since you're adding a webhook to it.

One workspace connects to as many repos as you like — every repo uses the same webhook URL and secret.


#Set it up

  1. Switch to the workspace you want commits to land in.

  2. Open Settings and scroll to the Workspace section, then GitHub integration.

  3. Copy the Webhook URL. It ends in your workspace's id, which is how PonderOS knows where the commits belong.

  4. Click Generate secret — it reads Regenerate secret if this workspace already has one — and copy it. You'll only see it once — PonderOS keeps it to verify deliveries, but never displays it again. If you lose it, generate a new one.

  5. In your repository on GitHub, go to Settings → Webhooks → Add webhook and fill in:

    Field Value
    Payload URL The webhook URL you copied
    Content type application/jsonrequired, see below
    Secret The secret you copied
    Which events? Let me select individual events → tick Pushes and Pull requests
  6. Click Add webhook.

GitHub immediately sends a test delivery. Open Recent Deliveries on the webhook — a green tick on the ping means your URL and secret are both correct, and you're done.


#Content type must be application/json

This is the one setting people get wrong, and it's worth 15 seconds of explanation because the failure looks like a broken secret.

Every delivery is signed. GitHub computes a signature over the exact bytes it sends, using your secret, and PonderOS recomputes it on arrival — that signature is the only thing proving a delivery really came from your repo and not from someone who guessed your webhook URL.

GitHub's other content type, application/x-www-form-urlencoded, doesn't send your data as the body of the request. It wraps it in a form field first. The bytes change, so the signature no longer matches what PonderOS computes, and the delivery is rejected as unauthenticated — a red 401 in Recent Deliveries, even though your secret is perfectly correct. When PonderOS can tell the content type is the cause, it says so in the response rather than leaving you with a bare "Invalid signature".

Set it to application/json and it works. PonderOS won't accept a form-encoded delivery either way; loosening that check would mean accepting deliveries it can't verify.


A ticket reference is a name, a hyphen, and a number — the id shown on the task, like inbox-10 or roadmap-42.

PonderOS finds them anywhere in the commit message:

fix: reject empty payloads (inbox-10)
[roadmap-42] first pass at the importer
refactor per inbox-10 and inbox-11

Details worth knowing:

  • Case doesn't matter. INBOX-10 links the same task as inbox-10.
  • Several tickets in one message all get the commit. So do several commits in one push.
  • The whole message is searched, not just the first line — a ticket in the body counts.
  • Any branch works. Pushes to feature branches link exactly like pushes to your default branch.
  • The task must live in this workspace. A ticket id from a different workspace is ignored — nothing links, and nothing breaks.

#What you'll see

Open a task with linked commits and a Commits section appears, newest first — each row is the short sha, the first line of the message, the author, and how long ago it landed. Click the sha to open the commit on GitHub. Only the newest five show at once — past that, an expander below the list reveals the rest and collapses them again. On a task with no commits the section isn't there at all.

The first commit ever linked to a task also drops a line in its story: First commit linked: a1b2c3d by Sam. That happens once per task, not on every push.

Re-delivering a webhook, or force-pushing the same commit again, won't duplicate anything.


#Which events PonderOS listens to

Event What happens
Push Processed — commit messages scanned, matching tasks updated.
Pull request Processed — the PR's title, body, and branch name are scanned for tickets; matching tasks show the PR and its state (open, draft, merged, closed).
Ping Acknowledged. This is GitHub's setup handshake; a green tick confirms your URL and secret.
Anything else Acknowledged and ignored, so GitHub doesn't retry it.

Ticking just Pushes and Pull requests is the tidiest setup. Sending everything works too — the extra events are discarded — but it makes your delivery log noisier than it needs to be.


#Rotating and disconnecting

Regenerate secret issues a new secret and invalidates the old one immediately. Update the repo's webhook with the new value or deliveries start failing.

To disconnect, delete the webhook in GitHub. Commits already linked to tasks stay where they are.


#When it isn't working

Recent Deliveries in GitHub tells you almost everything — each delivery shows the response PonderOS sent back.

What GitHub shows What it means
401, message starting Invalid signature The signature didn't match. Nearly always the content type — check it's application/json, and if that's the cause the message says so. Otherwise the secret is wrong or was regenerated; generate a fresh one and paste it into both places.
404 No integration configured for that workspace id. The URL is wrong, or the secret was never generated for this workspace.
200, "linked": 0 The delivery was accepted, but no ticket in it matched a task in this workspace. Check the id spelling and that the task is in this workspace.
200, "linked": 1 or more It worked. Open the task.

#Where to learn more

  • User Guide — the full tour: vault, tasks, projects, sharing.
  • MCP Guide — connect Claude Code, Cursor, or your own agent.
  • Troubleshooting — common issues and fixes.