X bookmarks are a useful signal source, but they are a terrible source of truth.
They collect ideas, workflows, teardown threads, product angles, and market hints faster than a human can process them. The failure mode is obvious: you pull everything into your project tracker, create a pile of low-quality tickets, and then pay again later to rediscover the same inputs.
The better pattern is to treat X as a paid inbox and GitHub Issues as the operating queue.
For Build Lean SaaS, the default destination is now:
GitHub Issues hold the actionable queue. Obsidian remains the context layer for long-form notes, specs, and decisions. Linear is archive/read-only unless someone explicitly asks to go back there.
The rule: check GitHub inbox capacity before calling X
Before fetching bookmarks, check how many GitHub issues are still open in the X inbox.
For our Build Lean SaaS queue, the cap is intentionally simple:
If the queue is already at or above the cap, the automation stops before touching X.
That one gate prevents the expensive failure mode: paying for more inputs when the team has no room to act on them.
X is the scarce input; GitHub is the work queue
The cost model matters.
GitHub API calls are cheap enough for normal operational use. They still have rate limits, but counting, creating, and updating a small number of issues is not the scarce resource.
X API calls are different. For meaningful API usage, they are paid or credit-limited. So every X read should produce one of three outcomes:
- A GitHub issue was created in
buildleansaas/obsidian-vault. - The bookmark was identified as a duplicate of something already captured.
- The bookmark was intentionally skipped and recorded as processed.
If none of those things happen, the read was waste.
The ingestion loop
The workflow is intentionally conservative:
The important safety rule is this:
Never remove the X bookmark until the idea has either been captured in GitHub Issues or intentionally recorded as processed.
Bookmarks should disappear only after the system has somewhere else to point.
Why use a consistent inbox label?
The label gives us a clean operational boundary:
That lets agents and humans ask a simple question before spending X credits:
Is the X inbox already full?
It also keeps Build Lean SaaS from mixing raw bookmark captures with repo-owned execution work too early. The raw capture belongs in buildleansaas/obsidian-vault; once a bookmark becomes a concrete task for a product repo, it can be promoted or copied into that owning repo with a backlink.
Dedupe by source URL, not title
Titles drift. Summaries vary. Agents rewrite things differently from run to run.
The stable keys are:
- tweet ID
- tweet URL
- GitHub issue number
- GitHub issue URL
A local cache can be as simple as JSON:
GitHub issue bodies should also include the source URL. That gives you a second dedupe path if the local cache is missing or the automation runs from a different machine.
What changed from the Linear version
The old version used Linear as the operating queue and checked Linear capacity before calling X. That was right for the old workflow, but Build Lean SaaS has moved execution to GitHub Issues.
The new version keeps the same credit-safety principle and changes the destination:
The pre-fetch guard now counts open inbox issues in GitHub, not active Linear issues.
The operating principle
A good automation does not just move data between tools. It protects the system from creating work it cannot absorb.
For this workflow, the principle is:
Pull from X only when GitHub has inbox capacity. Create one issue per new bookmark. Label every raw capture with existing inbox labels. Promote work to owning repos only after triage.
That keeps the queue clean, preserves the source trail, and avoids paying to process the same idea twice.