declaude
Remove Claude/AI attribution from a GitHub repo in one command.
declaude OWNER/REPO
It clones the repo, strips Claude/AI traces from your entire commit history
(e.g. Co-Authored-By: Claude <noreply@anthropic.com> or "Generated with
Claude Code"), force-pushes the cleaned branches, and refreshes GitHub's
Contributors graph so @claude actually disappears — all without touching your
code or your commit authorship.
Video
Why @claude won't go away by itself
AI tools append a Co-Authored-By: Claude … trailer to commits, and GitHub's
Insights → Contributors graph counts those co-authors. That graph is a
cached, background-computed view — a force-push (or a flush, or a commit)
on its own doesn't reliably update it, so @claude lingers even after the
history and the REST API are clean.
What actually works is a specific order:
remove Claude → flush (rename the default branch) → push a fresh commit
The flush resets GitHub's cached graph; the following commit triggers a
recompute against the now-clean history. declaude does all three for you (the
refresh commit is chore: refresh GitHub contributors, reusing your latest
commit's author so no new identity appears). It runs even when the history is
already clean, which is exactly what a previously-cleaned repo needs.
Timing matters too. GitHub serves its old commit index for a little while after
a force-push, and flushing against that stale index just rebuilds the graph from
the old history — putting @claude right back. So declaude waits until
GitHub itself reports the history as clean before flushing, then verifies the
rebuilt graph and repeats the flush → refresh if @claude survived. That's why
one run is enough; you don't have to run it twice.
Install
pip install declaude # installs the `declaude` command + git-filter-repo
Want the latest unreleased changes? Install straight from GitHub:
pip install git+https://github.com/ediiloupatty/declaude
# or, from a local clone:
pip install .
pip puts a declaude command on your PATH and pulls in git-filter-repo
automatically — no manual setup. The one prerequisite pip can't install is the
GitHub CLI, used to flush GitHub's Contributors-graph cache:
# Windows (winget):
winget install GitHub.cli
# macOS (Homebrew):
brew install gh
# Linux: https://cli.github.com/manual/installation
Windows note: after
winget install GitHub.cli, open a new terminal before runninggh— the current session won't see it yet.
Then log in:
gh auth login
declaude checks for gh and a valid login up front and tells you exactly what's
missing before it touches anything.
After installing on Windows — how to run it
After pip install declaude, pip may print a warning that the Scripts folder
isn't on your PATH. That's normal and harmless — it only means typing
declaude directly might say "command not found". Just run it like this and it
always works:
python -m declaude OWNER/REPO
That's the whole trick: put python -m in front. For example:
python -m declaude ediiloupatty/my-repo
python -m declaude --help
Prefer the short declaude command? The quickest fix is to let declaude add its
own install directory to your PATH:
python -m declaude path
Then open a new terminal and declaude works on its own. (Works on
macOS/Linux too, where it appends a PATH line to your shell rc file.)
Or install with pipx, which sets up PATH for you:
python -m pip install --user pipx
python -m pipx ensurepath
pipx install declaude
…or run the included install.ps1 from a clone of this repo (it adds the
Scripts folder to your PATH automatically):
powershell -ExecutionPolicy Bypass -File .\install.ps1 -FromPyPI
Then open a new terminal and declaude works on its own.
Usage
Run declaude --help (or python -m declaude --help on Windows) any time to
see the full reference:
usage: declaude [-h] [--version] [-y] [--dry-run] [--no-refresh] [--no-backup]
target
Remove Claude/AI attribution from a GitHub repo (clean history + force-push +
refresh Contributors graph).
positional arguments:
target GitHub URL or OWNER/REPO slug
options:
-h, --help show this help message and exit
--version show program's version number and exit
-y, --yes skip confirmation
--dry-run show the plan only
--no-refresh don't push the empty commit that refreshes the contributors
graph
--no-backup skip the restorable backup bundle before rewriting (not
recommended)
Other: `declaude prevent` turns off Claude Code attribution going forward.
Examples:
declaude ediiloupatty/my-repo # OWNER/REPO slug
declaude https://github.com/ediiloupatty/my-repo # full GitHub URL
declaude my-repo --dry-run # show the plan, change nothing
declaude my-repo -y # skip the confirmation prompt
declaude my-repo --no-refresh # clean + push only, skip the refresh commit
declaude my-repo --no-backup # skip the restorable backup bundle (not recommended)
declaude prevent # turn off Claude Code attribution going forward
declaude --version # print the installed version
The repo is cloned to a temp dir, cleaned, force-pushed, refreshed, then
discarded — you never clone by hand. Before any rewrite, a backup bundle is
written to ~/.declaude-backups/ and is fully restorable:
git -C <repo> fetch ~/.declaude-backups/<name>.bundle '*:*'
Honest caveats
- Claude authorship (rare). If a commit's author is Claude (not just a
co-author),
declaudewarns but does not change it — usegit filter-repo --mailmapto rewrite authorship. - Tags get force-updated. A tag can point at commits that no branch
reaches, so cleaning branches alone would leave those commits — and
@claudewith them — live on the remote.declaudetherefore force-pushes any tag whose commits actually changed, and reports them asaffected tags. Tags that were already clean keep their existing SHA. If a tag has a GitHub Release attached, the release follows the tag name and its uploaded assets are preserved, but GitHub regenerates the auto-generated source archives, so their checksums change. Collaborators needgit fetch --tags --force. A tag protection rule or release ruleset will block the push;declaudesays so instead of failing silently. - The refresh commit. declaude leaves one
chore: refresh GitHub contributorsempty commit on the default branch (authored as you). It's harmless; drop it later withgit rebaseif you like. Skip the whole refresh with--no-refresh. - Shared repos. The flush renames the default branch and back. Collaborators
with a local clone may see GitHub's "default branch renamed" notice. Use
--no-refreshif that's a problem. - Graph lag. declaude waits for GitHub to rebuild the graph and retries the flush + refresh up to 3 times, but GitHub's cache can still lag. If it ends with "the graph is not confirmed clean", the history is already clean — recheck in Incognito in a few minutes, or just re-run declaude.
- Closed pull requests. GitHub keeps old commits in
refs/pull/N/head, which users can't delete. The Contributors graph is computed from the default branch (clean + refreshed), so@claudeshould still drop; if it persists, only GitHub Support can purge the PR-ref cache.
Verifying it worked
declaude checks the server itself, across branches and tags, before it
flushes the cache. To confirm independently:
# every ref on the remote, including tags — should print 0
git clone --mirror https://github.com/OWNER/REPO.git /tmp/check
git -C /tmp/check log --all --format='%s%n%b' | grep -ci 'claude\|anthropic'
Note that GitHub has more than one contributor cache. stats/contributors
(which backs Insights → Contributors) answers HTTP 202 with an empty body
while it recomputes — an empty response means "not ready", not "no
contributors". The list on the repo overview sidebar is a separate cache and can
lag behind it. If the mirror check above prints 0, the history is clean and any
remaining @claude is cache lag; recheck in a private window.
Commands
| Command | Purpose |
|---|---|
declaude TARGET [-y] [--dry-run] [--no-refresh] [--no-backup] |
Clean history + force-push + refresh contributors graph. TARGET = GitHub URL or OWNER/REPO. |
declaude path |
Add declaude's install (Scripts) directory to your PATH so the bare declaude command works. |
declaude prevent |
Set includeCoAuthoredBy:false in ~/.claude/settings.json. |
declaude --version |
Print the installed version. |
Requirements
- Python 3.8+ and
pip gitgh(GitHub CLI, logged in) — install separately from https://cli.github.comgit-filter-repo— installed automatically as a pip dependency
Windows: works in PowerShell and Windows Terminal (ANSI colors are enabled
automatically; set NO_COLOR=1 to disable). git, gh, and Python must be on
your PATH.
Development
pip install -e ".[dev]" # editable install with test deps
python -m pytest # run the scrubber tests
python -m declaude --help # run without installing the console script
License
MIT © ediiloupatty
Metadata
Release files for declaude 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| declaude-0.2.1.tar.gz | 483.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| declaude-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 502.4 kB
Release files / declaude-0.2.1.tar.gz
| Download URL | declaude-0.2.1.tar.gz |
|---|---|
| Size | 483.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aad65ae3e0fdef48255a4f64ef2b3905af0045ac6f295b571076ba209bb56828
|
|
BLAKE2b-256 checksum How to use checksums |
9f33f0adc6451a3bb5e58233e8f3e50359166de4ff56efe4f0df342c5e8073f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / declaude-0.2.1-py3-none-any.whl
| Download URL | declaude-0.2.1-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e03f8b2134d4031f2cf513a004e88a584136a3101e7a51bebd580b4133bbb67b
|
|
BLAKE2b-256 checksum How to use checksums |
d559053066760c204e503262c1e311f988b2debdd0ddd04023dadcb9b49e29e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|