Decide who to unfollow on Instagram — from your own data, fully offline.
igsift reads your Instagram data export, scores every account you follow by a
keep_probability, and sorts them into keep / review / unfollow. It writes a
CSV, a Markdown summary, and a self-contained HTML report you can sort and filter
in your browser. No login, no API, no automation — you make the actual unfollows
by hand.
┌──────────────────────────┐ ┌─────────────────┐ ┌────────────────────┐
│ IG personal data export │ ──▶ │ CLI: igsift │ ──▶ │ following-audit.* │
│ dir / .zip / multipart │ │ score + rank │ │ CSV · MD · HTML │
└──────────────────────────┘ └─────────────────┘ └────────────────────┘
The run prints a dashboard to your terminal — bucket split, score distribution, and the strongest keeps next to the first accounts to drop:
The HTML report is the one you act from: sortable, filterable tables with a per-row Keep / Drop toggle. Your picks collect in a floating bar that copies or downloads the exact lines for your keeplist / droplist — nothing leaves the page. It follows your system light/dark setting out of the box, with an Auto / Light / Dark switcher in the header to override it — both themes below:
Synthetic sample, not a real export — personal accounts are fabricated; any brand pages shown are public. Regenerate with scripts/showcase-shots.sh (data from examples/showcase.rs, scored through the real pipeline).
In Instagram, request a Download Your Information export in JSON format
and download the .zip(s) once they're ready.
Pick whichever fits — a prebuilt binary if you just want to run it, or a build from source if you'd rather compile it yourself.
Option A — Download a release (fastest). Grab the binary for your platform
from the Releases page — it's
igsift on macOS/Linux and igsift.exe on Windows — then clear the
"downloaded from the internet" guard so the OS will run it:
# macOS / Linux
chmod +x igsift # mark it executable
xattr -d com.apple.quarantine igsift 2>/dev/null || true # macOS only# Windows (PowerShell)
Unblock-File .\igsift.exe # clear the SmartScreen blockOption B — Build from source (any OS). Needs a stable Rust toolchain — install it via rustup (the official installer) if you don't have one:
cargo build --release # binary lands at target/release/igsift (igsift.exe on Windows)Point it at the export — a folder, a single .zip, or the folder of multipart
.zip parts Instagram ships for large accounts:
./igsift ./instagram-export # macOS / Linux downloaded binary
cargo run -- ./instagram-export # from a source checkout (any OS).\igsift.exe .\instagram-export # Windows (PowerShell)Three files appear next to your input as following-audit_<date>.{csv,md,html}.
Open the HTML in a browser — a sortable, filterable table — then do the
unfollows by hand in Instagram. As you skim, you can flag accounts Keep or
Drop right in the report; a bar appears with Copy / Download buttons
that hand you the exact lines to paste into your keeplist / droplist (see
Customizing). Nothing is sent anywhere — the
selections live in your browser until you copy them out.
No config files are required; igsift ships with sensible defaults.
Input — an already-extracted directory, a single .zip, or a directory of
the multipart *.zip parts. Archives are extracted and cached next to the input;
--rebuild-cache forces a fresh extract.
Scoring presets — pick the lens that matches how you decide (--preset):
| Preset | Keeps the accounts that… |
|---|---|
balanced (default) |
…score well across all signals — no single one dominates |
engagement |
…you actually talk to and interact with; drops dormant follows |
tenure |
…you've followed for a long time, even if interaction has tailed off |
Subcommands
igsift <input> # score + write the audit (default; `run` is the explicit form)
igsift check <input> # dry-run: parse every source (✓/✗) and sanity-check your config
igsift init # scaffold the optional config files (see Customizing)Options
--out <PATH>— output stem (default:following-audit_<date>next to the input)--preset <name>—balanced|engagement|tenure(mutually exclusive with--config)--config <PATH>— use your own scoring-weights TOML instead of a preset--rebuild-cache— re-extract the archive even if a cache exists--trace <handle>— print the full per-signal score breakdown for one account--color <when>—auto(default) |always|never;autocolorizes the run summary only on an interactive terminal (also respectsNO_COLOR), so piped/redirected output stays plain-v/-vv— more logging (also hides the progress spinner)
Run igsift init to scaffold three optional files under config/:
keeplist.txt— accounts you'll never unfollow (floored to review at worst).droplist.txt— accounts to always force into unfollow, whatever the score (the exact mirror of the keeplist). A handle can't be on both lists.labels.txt— hand-label 20–30 accounts as keep/drop;igsiftreports how well its scores agree with you after each run.
The fastest way to fill keeplist.txt / droplist.txt is from the HTML report:
flag accounts as you read, then Copy (or Download) each list and paste it
into the matching file. The lists are case-insensitive, one handle per line.
To tune the scoring weights yourself, copy a preset to config/scoring.toml and
edit it — see docs/TUNING.md.
For each account you follow, igsift aggregates the signals in your export — DMs,
likes, comments, story interactions, how long you've followed, whether they
follow you back — into a keep_probability, then buckets it into keep / review /
unfollow. A few hard rules override the score: restricted accounts never drop
below review, keeplisted accounts are never unfollowed, and droplisted accounts
are always unfollowed. Accounts you've never interacted with in any direction are
floored to review rather than unfollow — an absence of evidence isn't
evidence to drop — and the report splits those never-engaged accounts out from
the genuinely faded ones so the review pile stays skimmable. Display names
mangled by Instagram's exporter are repaired on the way in.
Score-vs-intent agreement is feature-ceilinged — the export simply doesn't
separate every keep from every drop, which is what the keeplist and droplist
are for, not a bug to tune away. The algorithm is in
docs/DESIGN.md; the tuning journal and current measured
results are in docs/TUNING.md.
cargo build --all-targets
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo nextest run # or: cargo test
cargo deny check advisories bans sourcesLocal Lefthook hooks mirror these on
commit/push; CI runs them as the authoritative gate. See
CONTRIBUTING.md to contribute and
SECURITY.md to report a privacy/security issue.
Rust (edition 2024) — a single self-contained binary (Linux builds are fully
static via musl), no async, network, or database. clap, serde / serde_json,
serde_path_to_error (drift-tolerant parsing), toml, jiff, aho-corasick,
zip, indicatif, csv, tracing / tracing-subscriber, anyhow, and
console / anstyle / unicode-width for display-width-correct terminal
output. The HTML report is hand-rolled markup — no template engine. Full rationale and the deliberately-not-used list
are in docs/DESIGN.md.
No web/swipe UI, no Instagram API / scraping / automated unfollow, no daemon, no database, no login. The export is the source of truth; the run is one-shot.


