Guide
Drill in — one keystroke deeper
Press Enter on any row and octoscope opens a rich detail view of that repo, pull request or issue — without losing your place in the list.
What you can reach
- Repos → description, languages, release, a Checks section (c expands it past the first eight), and a 12-month star-history sparkline — v toggles it between density and a cumulative curve.
- Pull requests → metadata, reviewers, timeline, and an inline diff viewer (f → files → Enter).
- Issues → the full body rendered as markdown, labels and timeline.
- Gists → the one that goes two levels deep: enter opens a multi-file gist's file list, enter again opens a file — syntax-highlighted and scrollable — and c there copies the code rather than the link. A one-file gist opens straight into the file, because that was the only thing there was to see. GitHub truncates very large files and a gist can hold a binary; both are said out loud rather than rendered as noise.
Reached from the action menu
Press space on any list row — Repos, PRs, Issues, Gists or Inbox — for its action menu — open on github.com, copy the URL, view details, and (on a repo) run the integrity scan.
Supply-chain integrity scan
An on-demand, read-only check for the Shai-Hulud / Miasma class of self-replicating implant — the kind pushed to your own repos via a stolen token, that auto-executes the moment a repo is opened in an AI editor or npm install-ed.
It scores four filename-agnostic axes, explains the verdict with the evidence behind it — heaviest first, so what drove the verdict is what you read first — and now openly declares when its coverage was partial, because in a security tool a false negative is the expensive direction to be wrong in.
Verdicts run clean → watch → suspicious → likely compromised. When there's something to act on, y copies a remediation script and the report deep-links the right OAuth-grant revoke pages. It never mutates the repo.
What changed since last time
Each scan records a fingerprint of the repository's auto-execution surface — which scoring files exist on which branches, and whether each branch tip was signed — and the next scan reports what moved: a file that auto-executes appeared, an existing one changed, or a branch tip that used to be signed no longer is.
This is the most durable signal octoscope has, because it cares about neither the filename nor the contents: a variant that renames its dropper and obfuscates it differently still has to appear, and appearing is what gets caught.
- The first scan of a repo says so explicitly. No baseline means no comparison — never a confirmed "nothing changed".
- A baseline older than 30 days still lists what changed, but stops affecting the verdict: months of legitimate drift would otherwise train you to ignore it.
- Everyday files that change constantly —
package.json, editor task files — are deliberately not tracked, so real signal doesn't get buried under your own commits.
This is the one thing octoscope writes on its own: scan-baselines.json, next to your config file. Deleting it is harmless — the next scan simply starts a new baseline.
What a compromise could reach
The scan also reads your capability footprint: what permissions and triggers your workflows declare, plus self-hosted runners, write-access deploy keys and webhooks delivering off GitHub.
Holding power is not itself a finding. A release workflow asking for contents: write and reading secrets is completely normal — only someone who can already push a tag can trigger it, so it stays inventory. What scores is power reachable from untrusted input: a pull_request_target workflow holding the repository's secrets, or a self-hosted runner that an outsider's pull request can reach.
Since v0.28.0 it doesn't take a workflow file at its word, because one file is often not the whole story:
- Chains are followed. A fork-triggered workflow holding nothing that calls one reading a secret is two harmless files apart and one path to that secret together. The finding names the caller an outsider arrives through, so you're never told a
workflow_callfile is fork-triggered without being shown how. - Power is bounded by whoever granted it. A called workflow holds what its caller passed, never more — GitHub only lets it reduce that. So one whose caller hands over nothing isn't credited with the permissions it declares, and a file nobody in the repo calls says so rather than guessing.
- The permission never written down. A workflow declaring no
permissions:runs with your repository's default, which an owner can widen to read/write — invisible in the file. octoscope reads that setting and joins it in; where it can't, the report says so instead of deciding the workflow holds nothing.
Runners, deploy keys and webhooks need a token scope a minimal token won't have. Those checks fail open — the scan still runs — and the report names whichever ones it couldn't check, so a clean result is never mistaken for a complete one.
The full detection model — the four axes, the weighting, and the honest gaps — is written up in the supply-chain scan design doc.