StorOps
See where your storage goes. Understand why. Move what matters. Clean what doesn't.
StorOps is not a disk scanner and not a disk cleaner. WizTree already answers
"what is taking up space" -- StorOps answers what those things are, whether
they're safe to touch, and carries out a cleanup or migration safely once the
user says go. Full rationale in docs/DESIGN.md.
This file defines how an agent should behave when using StorOps -- not just
which commands exist. Prefer following the workflows below over calling
commands ad hoc; the user should not need to know command names.
Non-negotiable rules
- Analysis before action. Always scan/inspect/identify before proposing
anything, and never skip straight to a write operation. - Everything defaults to read-only.
storops scan,storops inspect,
storops search,storops identify,storops cleanup plan, and
storops migrate plannever modify the filesystem -- run them freely,
without asking first. - Never guess what a path is from its name. Only
storops identify(backed
byrules/*.yaml) determines category/risk/deletability. A path with no
matching rule comes backunknown/critical-- treat that as "do not
touch", not as an invitation to reason about it from the folder name. - Never treat "cache" or "temp" in a name as license to delete. Only act on
whatstorops identify/storops cleanup planactually classified. - Critical-risk paths (Windows, Program Files, unknown system files, user
documents) are never offered for deletion or migration. This is enforced
in code (assert_not_criticalinsrc/storops/core/risk.py), not just
by convention -- don't try to route around it. - Every write operation (
storops cleanup execute,storops migrate execute) requires the user's explicit, itemized confirmation first, and
the CLI itself refuses to run without--confirm. Show the plan, wait for
a real "yes", then pass--confirm-- never on the user's behalf
pre-emptively. - If an application may be running, do not move its data.
storops migrate planflagsRequiresAppClosed;storops migrate executerefuses to
run without an explicit--app-closedacknowledgement in that case. Tell
the user to close the app -- don't assume it's closed and don't kill the
process yourself. - For large, re-downloadable AI model/cache data (Hugging Face cache,
Ollama/LM Studio models, etc.), always state the consequence out loud
("this will need to be re-downloaded") before it's included in anything
the user approves. - Prefer migration over deletion for anything the user identifies as
valuable. Deletion is for reclaimable/disposable data; large model or
project data that isn't disposable should be offered as MOVE, not DELETE. - Prefer an application's own config-based relocation over a Junction.
storops migrate planalready encodes this precedence -- don't override
it towards Junction just because it seems simpler. - Verify after every migration (
storops verifyagainst the result file
storops migrate executewrites). If verification fails, say so plainly
and stop -- never delete or further modify anything to "clean up" a
failed verification. - Don't let the scan backend (WizTree on Windows, gdu/du on Linux/macOS)
become a hard dependency in your reasoning. If it's missing entirely, the
CLI raises a clear error pointing at where to get it (WizTree:
https://diskanalyzer.com/ or$env:STOROPS_WIZTREE_PATH; gdu:
https://github.com/dundee/gdu or$env:STOROPS_GDU_PATH) -- relay that
to the user rather than trying to work around it some other way. - On Linux/macOS, every
--jsonresult from a read/plan-tier command
(scan/inspect/search/cleanup plan/migrate plan) carries
BackendandBackendAdvicefields.BackendAdviceis non-null only
when StorOps fell back to the slowerdubackend becausegduwasn't
found. Mention it to the user once per conversation if it's non-null
(e.g. "by the way, installing gdu would make these scans noticeably
faster") -- don't repeat it on every single command, and don't mention it
at all on Windows or when it'snull.
Workflow: "why is my drive full?"
storops scan C:\(or the drive the user mentioned) for top-level
consumers and free space.- To see what's inside several large entries at once, prefer one
storops search <path> --folders --max-depth 2(bump to3if two levels isn't
enough) overstorops inspect-ing each one individually.inspect
re-walks its whole target subtree from scratch every time it's called;
inspecting N large (and often nested/overlapping) subdirectories one at a
time repeats stat work a singlesearchpass already covers, and
search's rows carry the same risk/recommended-action infoinspect's
do. Reach forstorops inspect <path>only to drill into one specific
directory further than that search already went. - Cross-reference every notable entry with
storops identify(scan/inspect/
search already attach identity + recommended action, but call it
directly for a single path the user asks about). - Present a ranked breakdown: what it is, how big, and the recommended
action (KEEP / DELETE / MOVE / CHECK) with reason and risk. - Never delete or move anything at this stage -- this is purely diagnostic.
Workflow: "clean up disk space" / "delete X"
- Make sure the target has already been scanned/identified (run the scan
workflow above first if not). - Run
storops cleanup plan(default--max-risk low; only raise it if
the user explicitly says they're fine with medium/high-risk items too).
This produces an itemized JSON plan -- nothing is deleted yet. - Present the plan grouped by risk tier, each item's size, application, and
consequence (call out medium/high-risk consequences explicitly, e.g. "may
need to be re-downloaded"). Show the total reclaimable size. - Ask the user to confirm. If they only want a subset, regenerate with a
tighter--max-riskor point out which items to skip -- don't hand-edit
Approvedflags in the plan file without telling the user exactly what
changed. - Only once the user confirms, run
storops cleanup execute --plan-file <path> --confirm. - Report the result per item (deleted / skipped / failed) and the total
reclaimed size. Afaileditem (e.g. file in use) is reported, not
retried forcefully.
Workflow: "migrate X to another drive"
- Identify the source path (
storops identifyif not already known from a
scan). If it's notMigratable, say so and explain why (e.g. critical,
or no known migration path) instead of improvising one. - Run
storops migrate plan <source> <destination>. This decides the
method (application config change, or Junction as fallback), and
produces an ordered step list -- nothing is moved yet. - Present the plan: source, destination, size, method, and whether the
application must be closed first. IfRequiresAppClosed, explicitly
ask the user to close it before proceeding. - Ask for confirmation on the plan as a whole.
- Run
storops migrate execute --plan-file <path> --confirm(add
--app-closedonce the user has confirmed the app is closed). This
copies the data, verifies file count/size against the source, and only
then removes the original -- for the Junction method it also relinks the
old path. - If the method was an application config change (not a Junction), tell the
user the exact config change to make (from the plan'sMigrationHint)
-- StorOps does not edit arbitrary app config files itself. - Run
storops verify --result-file <path from migrate execute output>and
report PASS/FAIL per check. On FAIL, stop and describe exactly what
didn't match -- never delete remaining data to "resolve" a failed
verification.
Workflow: "is it safe to delete/move <path>?"
Just run storops identify <path> and relay Category, Deletable,
Migratable, CleanupRisk, Consequence, and the recommended action verbatim --
this is the direct, deterministic answer; don't editorialize past what the
rule base actually says, and don't guess for an unknown result.
Command reference
| Tier | Commands | Confirmation |
|---|---|---|
| Read | storops scan, storops inspect, storops search, storops identify |
none |
| Plan | storops cleanup plan, storops migrate plan |
none (produces a plan file only) |
| Write | storops cleanup execute, storops migrate execute |
requires --confirm (and --app-closed for migrations that need it) |
| Verify | storops verify |
none (read-only re-check) |
Every command supports --json for machine-readable output. Invoke as
python -m storops <command> ..., or storops <command> ... if the package
has been pip install-ed.
See README.md for setup/requirements and rules/README.md for the rule
schema behind identification.