Search for a feature flag cleanup tool and you get a list of products that do three genuinely different jobs. One tells you a flag is dead and stops there. The next hands your code to a language model and asks it to delete the flag, and the third parses the source and applies rewrite rules to it. All three get filed under the same phrase, and picking the wrong one wastes a quarter.
Automated removal itself is no longer unusual. LaunchDarkly, Datadog, Harness and Reflag all ship something that opens a pull request against your repository. The interesting question moved on with them. What matters now is what produces the diff, which languages the rewrite actually covers, and what ends up holding write access to your repo.
Everything below was read from each vendor’s own documentation on September 17, 2026. Product pages in this category change fast, so check the primary source before you sign anything.
1. Three things get called a cleanup tool
The first split is how far the tool goes.
Detect and mark. Unleash marks a flag potentially stale once it passes its expected lifetime, and its documentation is candid about where that ends: it points at integrations that can open pull requests to remove stale flags, without shipping one itself. Vercel puts an Unreferenced badge on flags its discovery endpoint cannot find in your latest production deployment, and its own cleanup guide is a manual procedure that starts with rg "old-onboarding-flow". Most platforms live here.
Model-written removal. Reflag’s bot refactors with an LLM and opens a pull request. LaunchDarkly’s Vega is an AI agent that does the same on a 1, 7 or 30-day schedule. Harness ships pipeline templates that call a cleanup agent. Datadog’s stale-flag banner carries a Generate Removal PR with Bits button, which opens a pull request removing the flag-gating logic from your application code.
Deterministic rewriting. The source gets parsed into a syntax tree and rewrite rules are applied to it. Two products do this, ours and FlagShark’s. Being deterministic does not on its own separate one from the other. What does is which languages the rewrite actually reaches and where the tool ends up running, which is what the rest of this covers.
2. What changes when a model writes the diff
Run a rule-based rewriter twice on the same commit and you get the same diff. Come back in November, after four months of releases, and that same commit still produces it. That property sounds boring until you are the reviewer, because it means a rewrite you approved once cannot come back different, and a run you audit is the run everyone gets.
A model does not offer that. The same flag, the same file and the same prompt can produce a diff that differs between runs, and it certainly differs between model versions you do not control. LaunchDarkly’s documentation makes the shape of this explicit without meaning to: Vega reads instructions from an AGENTS.md or CLAUDE.md file in your repository to improve its results. That is prompt engineering as a configuration surface, which is a reasonable design and a very different thing from a rule set.
A model can also do something the rules cannot. It reads your own useFlag("checkout-v2") wrapper, works out what the thing does, and rewrites through it. Rule-based matching keys on callee name plus key string, so an unrecognized wrapper is invisible and the run reports nothing to change. That is real reach a rule set does not have, and if your codebase never calls the SDK directly it may be the reach that matters.
You give up knowing in advance. A deterministic tool can publish the list of shapes it declines, because the list is the rules, and we publish ours. A model’s refusals are discovered one run at a time.
One practical wrinkle sits underneath Harness: the cleanup agent requires an Anthropic API key, supplied by you. The model bill is yours, and so is the rate limit.
3. Ask which languages the rewrite covers, not the scan
This is the question that separates a demo from a deployment, and almost nobody asks it.
Finding a dead flag in a Kotlin file is easy, because you are looking for a string. Rewriting that file is a different job. It needs a grammar, a parser and a rule set per language. So a product can honestly advertise detection across a dozen or more languages while its rewriter reaches eight of them, and the two numbers appear on different pages.
FlagShark is the clearest published example, and it is transparent about both halves if you read both: the homepage describes AST-based scanning for TypeScript, JavaScript, Go, Python, Java, C#, PHP and Rust with precise regex for the other five, while the cleanup-PR documentation gives a different eight for removal, swapping C#, PHP and Rust out for Kotlin, Swift and Ruby.
Reflag documents its own boundary plainly. The clean-up bot removes isEnabled and leaves track, config and requestFeedback alone, it keeps the codepath that grants access instead of evaluating which branch survives, and it works best with the React SDK while the capability is in beta.
LaunchDarkly and Datadog publish no language list for the removal step at all, so that is a question for your account team, not something to infer from their SDK matrix.
For what it is worth on our side, the same thirteen languages that get scanned get rewritten, ERB templates included, because both steps run through the same registry. Rails view code is the one that surprises people, and it is where a fair amount of flag logic actually lives.
4. Where it runs, and what holds the write bit
A tool that opens a pull request has to be able to push a branch. Where that permission lives differs more than the feature comparison suggests.
Four of the five products above are vendor-hosted. Datadog’s runs through its GitHub App with read and write on repository contents and pull requests. Vega installs a GitHub App at the organization level and additionally authenticates your personal GitHub account so it can act on your behalf, works only with private repositories, supports GitHub alone for pull requests, and executes scheduled runs using a stored member’s permissions. Reflag connects at the organization level and its bot submits the pull request.
Harness is the exception among the hosted products. Its templates run in your own pipeline, with a Git connector and repository token you supply, alongside the Anthropic key from section 2.
Ours runs as a step in your workflow, so the credential that pushes the branch is the GITHUB_TOKEN your workflow already carries, with contents: write and pull-requests: write. The parsing happens in the container on your runner. There is a fuller answer about what a cleanup run can reach if that is the part your security review will ask about.
Plenty of teams will install the app and be right to. It is a procurement question with a real answer, and some organizations cannot grant repository write to an outside app no matter how good the feature is.
5. Which shape fits which codebase
Four situations decide this, and a feature table rarely does.
Your code never calls the SDK directly. If every read goes through a house wrapper, a rule-based tool needs that wrapper named before it can do anything, and until you name it the run is silent. Naming it takes one line of config. If the wrapper layer is genuinely irregular, with reads behind three different helpers and a registry, the model-based tools handle that better today.
You ship a mobile app, or a polyglot monorepo. Removal coverage binds here, not detection coverage. Swift, Kotlin and Dart are where the published lists thin out, so check the rewriter’s list against the languages your flags actually live in before anything else.
You already run the platform. If your flags are in Datadog or LaunchDarkly, the first-party tool is the lowest-friction thing available and the integration cost is close to zero. That advantage is real, and no argument about determinism erases it. Weigh it against the reproducibility question and whether their rewriter covers your languages.
You have eleven dead flags and a quiet week. Then you do not need any of this. The manual cleanup playbook covers the procedure, and for a handful of flags a careful afternoon beats evaluating vendors.
6. What to check before switching any of them on
Five questions, in the order that saves you the most time.
Can you see a full run before it writes anything? A dry run that computes every diff and opens nothing is the cheapest possible evaluation, and it shows you fit that no demo will.
How many pull requests can one run open? A tool that proposes two hundred branches on the first morning has turned a code problem into a review problem.
What happens when it cannot safely rewrite something? Silence and a clean exit are the dangerous answer, because they read exactly like a clean codebase.
Who holds write access, and for how long? Section 4 has the shapes, and this is the question your security review will open with.
Does the flag itself get retired when the code does? A removal that leaves the flag sitting in the dashboard has moved the debt without paying it. Closing that loop is worth asking about, and it is usually a separate opt-in workflow rather than something on by default.
The shorter version
- Three different products answer to the phrase cleanup tool: mark the flag, have a model rewrite it, or rewrite it with a parser and rules.
- Automated removal pull requests are common now. LaunchDarkly, Datadog, Harness and Reflag all ship one, so the capability is a qualifier rather than a differentiator.
- A deterministic rewrite gives the same diff for the same input and can publish what it declines. A model reaches shapes rules cannot express and cannot tell you in advance what it will do.
- Detection coverage and rewrite coverage are different lists. Ask for the second one.
- Four of the five hosted products open pull requests through an app holding repository write. That is a procurement question with a real answer.
- Reflag’s cleanup sits on its Pro plan and is in beta. Vega is GitHub-only and private-repo-only. Constraints like these settle evaluations before the feature list is opened.
- If you have a dozen dead flags, clean them up by hand and spend the evaluation time elsewhere.
Frequently asked questions
What is a feature flag cleanup tool?
Any tool that helps retire a flag after its release is finished. In practice the phrase covers three jobs: detecting flags that no longer change behavior, rewriting the source to remove the dead branch, and opening the pull request that carries that change. Most flag platforms automate the first and leave the rest to you. Only a handful do all three.
Is automated feature flag cleanup safe?
It depends on what the tool does when it is unsure. The failure worth worrying about is a rewrite that compiles and still changes behavior, such as folding a mocked flag read so a test quietly stops asserting anything. A tool that stops and names the file is behaving correctly. A tool that finishes silently on a codebase full of flags is telling you less than it appears to.
Which languages can automated flag removal handle?
That depends on the rewriter, not the scanner, and the two lists differ per product. Deterministic tools publish their rewrite languages because the rules are per-language. Model-based tools mostly publish nothing on this, which makes it a question to ask directly rather than an assumption to make.
Do I need my flag vendor’s own cleanup tool?
No, and the tradeoff is straightforward. A first-party tool already knows which of your flags are dead, so setup is trivial. A third-party tool works across vendors, which matters if you are mid-migration, though it cannot archive the flag afterward in a platform it does not control.
Does removing the code archive the flag?
Usually not by default. Code removal and flag retirement are separate systems, and a tool that does the first and not the second leaves a dashboard slowly filling with flags whose code is already gone. Where closing that loop is supported it is normally an opt-in workflow with its own credential, since archiving a flag is a write and scanning for dead ones is not.
Featureflip is built by a small team who got tired of flag debt outliving the features that caused it. The cleanup Action is deterministic, covers thirteen languages, and runs as a step in your own CI. Start free and point it at one repository in dry-run mode.