Actions are taken only when an owner or admin presses the button for them. Every one is recorded in Activity with who pressed it, what the platform returned and what it saves, and in the audit log. Viewers cannot take actions.
Fix pull requests
Open fix PR appears next to a workflow in superseded runs and hung jobs.
What changes
Patches are textual insertions. The file is not parsed and re-serialised, which would reorder keys, drop comments and turn a five-line change into a rewrite. After patching, the file is parsed again and must be identical to the original apart from the added keys; if it is not, no pull request opens.
@@ -4,4 +4,10 @@
push:
branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ # Cancels superseded pull request runs only. Pushes to a branch are
+ # never cancelled, so deploys and release builds run to completion.
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
# the jobs
@@ -3,4 +3,5 @@
jobs:
build:
+ timeout-minutes: 40
runs-on: ubuntu-latest
steps:
The group is keyed on the pull request number, so two pull requests never cancel each other, and cancel-in-progress is true only for pull_request events. A push to main is never cancelled.
opsen does not patch a file that already sets top-level concurrency, or a job that calls a reusable workflow (uses:), which cannot take a timeout.
Linting
Before the pull request opens, the patched file is run through actionlint in an isolated sandbox. A file that fails lint never becomes a pull request; the failure is recorded in Activity. If the sandbox is unreachable the pull request still opens and its description says it was not linted.
The pull request
| Branch | opsen/cancel-superseded-runs-<file> or opsen/job-timeouts-<file> |
| Base | the repository's default branch |
| Body | why, the measured monthly saving, the lint result, a link to the report |
Pressing the button again before the next audit changes nothing. After it, while the pull request is still open, it links to the existing one and counts no new saving. Closing it changes nothing else.
Reclaim Copilot seats
DELETE /orgs/{org}/copilot/billing/selected_users. Seats go to pending cancellation and keep working to the end of the cycle. See Copilot seats.
Restore, on the Activity page, gives the seats back (POST /orgs/{org}/copilot/billing/selected_users). A seat still pending cancellation is simply kept, so nothing lapses. The person goes on the keep list so opsen does not reclaim it again.
Cancel invitations
DELETE /orgs/{org}/invitations/{id}, one per selected invitation. Failures are listed individually.
Disable a schedule
PUT /repos/{org}/{repo}/actions/workflows/{id}/disable. Restore, on the Activity page, turns it back on (PUT …/enable), or re-enable it from the repository's Actions tab.
Keeping a seat on purpose
Some idle seats are meant to be idle: someone on leave, a service account, a reviewer who signs in once a quarter. Press Keep next to the person in any recommendation, or add them under Settings, Kept on purpose, with a reason and, if you like, an end date (30, 90, 180 or 365 days).
A kept person leaves the findings and the waste figure on every platform you chose, at once and in every later audit. Recommendations shows how much is kept and links to the list. Nothing is changed anywhere: opsen just stops counting the seat. When the date passes, or someone presses Take off, the person comes back in the current report straight away, without waiting for an audit. Adding and removing are in the audit log, and report.json lists them under kept.
Only people are kept. A workflow, a schedule or a repository is fixed or left in the report.
Automatic reclaim
For each kind of seat opsen can reclaim in one click (idle Copilot seats, stale invitations, and idle seats on GitLab, JetBrains, Azure DevOps, Cursor and the rest), an owner or admin can switch it on under Settings, Autopilot, with a grace period of 3, 7 or 14 days, and untick any kind they want left alone.
- Ask. Each person holding an idle seat gets an email: the seat goes on a date unless they press Keep my seat. The link opens a page with one button, so a mail scanner that follows links keeps nothing. Pressing it puts them on the keep list for 180 days, and the audit log shows they asked.
- Wait, then check again. When the grace period ends, opsen reclaims the seat only if an audit taken after that date still shows it idle. If the latest audit is older, opsen starts one first. Anyone who used the seat in the meantime is never touched.
- Reclaim through the same checks as the button. Only seats in the latest audit reach the platform, nothing is changed twice, and each reclaim is in the activity log as approved by the policy and the person who switched it on.
opsen emails the address the platform holds. For GitHub, that is the email the person signed in to opsen with, their email on a domain your organisation verified, or the author email of their latest commit in the organisation. GitHub noreply addresses never count. People with no email are skipped and listed, unless you choose Reclaim anyway. Invitations are cancelled after the grace period without an email: there is nobody to ask.
Switching a policy off stops every reclaim that has not happened yet. A policy never removes people from an organisation, deletes anything, or changes billing settings.
Autopilot
Autopilot is one switch, on the overview or under Settings, Autopilot, for the hands-off version of everything above:
- Idle seats of every kind opsen can reclaim in one click are handled as described under Automatic reclaim. Each person is asked first and has the grace period (7 days by default) to keep their seat. Kinds that later audits find are covered too.
- CI fixes open as pull requests for you to merge: concurrency groups for superseded runs and timeouts for hung jobs. The largest go first, at most three a day and five waiting to be merged at once, only where the fix is worth at least $5 a month. A file never gets two pull requests for the same fix, and a pull request someone closed without merging is never opened again.
- Spend jumps and renewals alert owners as usual.
Licences are covered by default: Copilot and IDE seats, add-ons like Duo, and downgrades to a free tier such as Azure DevOps Stakeholder. Anything that removes a person's access, like removing a GitLab member or Atlassian product access, is off until an owner ticks it. Only an owner can switch autopilot on or change it; admins act one change at a time. A kind of seat you untick stays off, and its notices are withdrawn. Autopilot only runs on a plan that includes actions: nobody is told a seat goes when it could not. Switching autopilot off withdraws every notice it sent; nobody told under it loses a seat. Autopilot acts with the authority of the owner who switched it on. If that person loses access, autopilot pauses and says so. Its changes appear in the activity log as "Autopilot, on by" that owner.
Your code. Autopilot never pushes to a branch people work on and never merges anything. A CI fix is one edited workflow file on a new opsen/ branch, opened as a pull request against your default branch, so branch protection, required reviews and CODEOWNERS apply exactly as for any contributor. opsen only resets an opsen/ branch it created itself. If anyone else has committed to that branch, opsen leaves it alone. Close the pull request and nothing has changed.
Undo a change
Every change opsen makes is a row in Activity. Press Restore on that row to put it back as it was:
- Copilot seats: reassigned to the same people. Seats still pending cancellation keep running; nothing is billed twice.
- Dormant schedules: turned back on.
- Other platforms: back at the same role, access level or licence (see the table under Changes on other platforms).
The row then reads Restored, the saving stops counting from that moment, and the people go on the keep list so the next audit does not flag them again. Restore is never blocked by billing. Cancelled invitations and Atlassian access removals have no Restore: invite the person again, or grant access in admin.atlassian.com.
Not offered
Removing members or collaborators, deleting repositories, deleting workflows, or changing billing settings. These are listed and exported; GitHub is where they are done.
Changes on other platforms
Findings from connected platforms carry their own one-click change. Each person is listed with a checkbox; untick anyone who should keep access.
| Platform | Button | What happens | Undo |
|---|---|---|---|
| GitLab (gitlab.com) | Remove members | Removed from the top-level group and every subgroup and project, after opsen records each membership and role | Restore in Activity: back in every group and project at the same role |
| GitLab (self-managed) | Deactivate users | The licence seat frees; they are reactivated on their next sign-in | Reactivate in the admin area |
| GitLab Duo | Unassign seats | The Duo seat is unassigned; GitLab access is unchanged | Restore in Activity: the seat back to the same person |
| Azure DevOps | Move to Stakeholder | The Basic or Test Plans charge stops; account and work items stay. opsen records each person's access level first | Restore in Activity: the same access level back |
| Atlassian | Remove access | That product's access is removed; account and other products stay | Grant access in admin.atlassian.com |
| JetBrains | Revoke licences | The licence returns to your pool; opsen records who held it | Restore in Activity: the same licence back to them, without an email |
The key you connected needs write access for these; each platform's guide says which.
Everything put back with Restore stops counting toward savings from that moment, and the people go on the keep list. Restore is never blocked by billing. Cancelled invitations and Atlassian access removals have no Restore: invite again, or grant access in admin.atlassian.com.
Fix in your IDE
Findings that are fixed in code (superseded runs, hung jobs, dormant schedules, failing CircleCI workflows) have a Fix in your IDE menu on each row. It opens Cursor, Claude Code or Codex with a prompt that names the repository and file, the measured cost, the exact change and how to check it, for you to review before it runs. Run in the cloud starts the same fix with Devin, a Cursor cloud agent or GitHub Copilot's coding agent, which opens a pull request. Connect Devin and Cursor in Settings → Coding agents; Copilot uses your own GitHub sign-in. See MCP, plugins and API.