Skip to content
Back to Resources
Guide

Which ClickUp tasks map to shipped code, and which never did

Skopx Team
August 5, 2026
9 min read

It is the Tuesday after a release. The engineering manager has ClickUp open on one monitor, filtered to the sprint list, status column sorted so the twenty-three cards marked Done sit at the top. On the other monitor is GitHub, the repository's merged pull requests for the same two weeks, forty-one of them, most with a branch name that starts with a ClickUp task ID and some that do not.

The question came from the VP of product an hour ago, and it was reasonable: of the twenty-three things we told the customer-facing teams were done, which ones are actually in the release, and which are sitting in a branch or behind a flag or were closed because the requirement changed?

Nobody can answer it from either screen. The manager starts opening cards.

What ClickUp shows on its own

ClickUp is showing the truth about the task list, and it is showing it well. Each card has a status, an assignee, a sprint, time in status, and a full comment thread. The custom field for release version is populated on maybe two thirds of the cards. Dashboards can chart velocity, cycle time, status distribution, burndown. If the question were "how much did this team move through the board in two weeks", ClickUp answers it completely and without help.

The GitHub integration is real and it is useful. Connect it and a card can show linked branches, commits and pull requests, and an automation can move a task to a status when a PR merges. On the cards where that link exists, the manager can see the PR right there.

Where it stops is the population, not the individual card. ClickUp knows about the links that were created. It does not know about the pull requests nobody linked, and it has no way to know, because an unlinked PR is not absent data in ClickUp, it is not data in ClickUp at all. So the dashboard can tell you that twenty-three cards are Done. It cannot tell you that four of those twenty-three have no merged code behind them, because from ClickUp's side those four look exactly like the ones that do. Status Done is a field a person set. It reports what was claimed, faithfully.

What GitHub shows on its own

GitHub is showing the truth about the code, and it is showing that well too. Forty-one merged pull requests, each with an author, a merge commit, a base branch, files changed, review approvals and the checks that passed. Insights gives contribution and pull request volume over the period. The compare view between the previous release tag and this one gives an exact, unarguable list of every commit that shipped.

GitHub also has the reverse link. Mention a task in a PR title or body, or name the branch after it, and the connection is recorded on that side.

Where GitHub stops is intent. A merged pull request tells you code changed. It does not tell you which promise that change was keeping, whether the promise was the whole of the card or one third of it, or whether the card it referenced was later split into three. Some PRs are refactors that no card asked for. Some cards needed four PRs across two repositories. And the ones that matter most for this question, the four Done cards with nothing behind them, are invisible in GitHub by definition. You cannot find a missing pull request by looking at the list of pull requests.

QuestionClickUp aloneGitHub alone
How many tasks were marked DoneYesNo
What code shipped in the releaseNoYes
Which Done tasks have merged codeOnly where a link was createdOnly where a task was referenced
Which Done tasks have no code at allNoStructurally no
Whether "Done" meant doneNoNo

Why the gap is structural

Look at what each half of the evidence actually is.

The GitHub half is a record. A merge happened at a timestamp, on a commit SHA, into a named branch. It was produced by a machine as a side effect of an action, and it is exact. Two people looking at it will read the same thing.

The ClickUp half is partly a record and partly a sentence somebody wrote. The status field and the sprint are records. But the reason a card was closed lives in a comment: "closing this, we agreed in standup to fold it into the auth rework", or "shipped behind the beta flag, will flip next week", or "duplicate of 8291". The card title is prose. The acceptance criteria are prose. When the manager opens the four suspicious cards, what resolves each one is a paragraph a human typed, and no field on the card encodes it.

That is why this is not a reporting feature either product forgot to build. ClickUp can only join on links that exist inside ClickUp. GitHub can only join on references that exist inside GitHub. Both are complete over their own domain and both are blind to the other's negative space. And even a perfect two-way sync would leave the last step untouched, because the last step is reading a comment thread and deciding what it means.

It is worth being precise about the neighbouring tools too. Zapier and Make connect ClickUp and GitHub genuinely well, and can keep statuses in step in both directions. But automation is trigger based: it fires when something happens and moves the next record along. It has no view of a fortnight that has already passed, so it cannot be asked what the last two weeks added up to. A BI tool pointed at exported ClickUp and GitHub tables can do the counting cleanly. What it cannot do is read the comment that says the card was folded into another one, because a paragraph of English is not a modelled field. The gap is not inside any of these products. It is between the record half and the sentence half.

What the join actually requires

Two things, and only one of them is mechanical.

The key is the task ID, found wherever it appears: the branch name, the PR title, the PR body, the commit messages, and the linked-item list on the card itself. Each of those alone covers part of the population. Together they cover most of it. Everything left over is genuinely unlinked, and that residue is the interesting part, not an error to be cleaned up.

The judgement call is what to do with the residue and the ambiguities. A card marked Done with no PR anywhere might be a documentation change, a decision, a card superseded by another, or a card that was closed optimistically. A card with one PR might still be half shipped. Deciding which is which means reading the closing comment and the description and forming a view. That is not a matching problem and no join key will get you there.

Answering it with Skopx

Skopx connects to ClickUp and GitHub as two of nearly 1,000 integrations, and the question gets asked in chat the way you would ask a colleague:

For the sprint that closed last Friday, list every ClickUp task marked Done and tell me whether it has a merged GitHub PR in the release. For any that don't, read the closing comment and tell me why it was closed.

What comes back is one table with a row per task, the merged PRs matched against it, and for the unmatched ones a short line drawn from the actual comment: folded into the auth rework, behind the beta flag, duplicate. Every row cites the card and the pull request it came from, so the manager can click through and check rather than trust.

When the same question gets asked every sprint, the sentence becomes a console. Ask for it in chat and Skopx builds a standing view over the same two connections: Done tasks this sprint, matched code, the unmatched list with its reasons, and a per-engineer breakdown. It reads live each time it is opened, so it is never a stale export. It can also carry a small number of actions, a button to post the summary into the sprint's ClickUp comment thread, for instance, which asks for confirmation before it does anything. That is the whole shape of an internal app: read across both tools, show the answer, and let a person click one thing.

What this does not do

It does not decide for you. When a card is Done with no code, Skopx will tell you what the comment says and where the ambiguity is. It will not rule that the card was closed wrongly.

It does not create or change anything on its own. There is no scheduled run, no alert when a mismatch appears, no record written into ClickUp unless someone reads the console and clicks the button and confirms. There are no forms and nothing is stored.

It cannot recover a link that was never made anywhere. If a pull request has no task ID in the branch, the title, the body or the commits, and the card has no linked item, nothing can pair them but a human who remembers. Skopx will show you that pair as unresolved rather than guess.

And it is only as good as what people wrote. If the closing comment says "done" and nothing more, the answer for that row is that nobody recorded why. That is still useful, because it is a specific gap on a specific card rather than a vague sense that the board might be optimistic.

Team is $16 per seat per month with 2.3 million AI tokens included, Solo is $5. SOC 2 controls are in place, and per-viewer permissions mean the console shows each person only the ClickUp and GitHub data their own connected accounts can see.

Share this article

Skopx Team

The Skopx engineering and product team

Related Articles

Stay Updated

Get the latest insights on AI-powered code intelligence delivered to your inbox.