self
Self-management commands for the CLI
The self command provides subcommands for managing the squirrel CLI itself: installation, updates, diagnostics, and settings.
Subcommands
- install - Bootstrap local installation
- update - Check and apply updates
- completion - Generate shell completions
- doctor - Run health checks
- disk - Report what
~/.squirrelis using - version - Show version information
- settings - Manage CLI settings
- uninstall - Remove squirrel from the system
install
Bootstrap the local installation by creating necessary directories and symlinking the binary.
Usage
squirrel self installOptions
| Option | Description |
|---|---|
--bin-dir | Custom bin directory for symlink (default: ~/.local/bin) |
Output
Installed v0.1.0
Binary: ~/.local/share/squirrel/releases/0.1.0/squirrel
Symlink: ~/.local/bin/squirrelIf ~/.local/bin is not in your $PATH, the command will show:
Add to your shell profile:
export PATH="~/.local/bin:$PATH"What it does
- Creates
~/.squirrel/for settings - Creates
~/.local/share/squirrel/releases/for cached releases - Creates symlink at
~/.local/bin/squirrel - Registers installation for update checks
update
Check for and apply updates to the CLI.
Automatic updates
You usually don’t need this command. With auto_update enabled (the default), squirrel updates itself: any CLI run checks for a new release in the background, and when one is found a detached background process downloads it, verifies its SHA-256 checksum, and switches over silently. Your next run prints a one-line notice:
✓ squirrel auto-updated v0.0.42 → v0.0.43A download that stops sending data for a minute, or has not finished after 20 minutes, is abandoned and tried again on a later run. The running process is never interrupted - the new version takes effect on the next run. From v0.0.99, that run also refreshes the squirrelscan agent skills you have installed, in the background (see skills; turn just that off with squirrel self settings set skills_auto_update false). Turn this off with:
squirrel self settings set auto_update falseWith auto-update off you still get an update notification box (unless notifications is also off), and squirrel self update applies updates manually.
Automatic updates only run for managed installs (installed via the install script, npm, Homebrew, or self install). A Homebrew install is a managed install after its first run: update it with squirrel self update, not brew upgrade. See Homebrew. If you copied the binary somewhere yourself, squirrel tells you how to update instead of touching your setup.
Check frequency
The background check runs on CLI invocations but is throttled so it hits the network at most once per interval, no matter how often you run squirrel, so it never adds latency on every start. The default is once per hour; tune it (in hours, fractional allowed, minimum 0.05 ≈ 3 min) to pick up hotfixes faster:
squirrel self settings set update_check_interval_hours 0.25 # every 15 minCI and locked-down environments
squirrel makes no outbound update requests when it detects CI (CI, GITHUB_ACTIONS, GITLAB_CI, CIRCLECI, BUILDKITE, JENKINS_URL, TEAMCITY_VERSION, TF_BUILD): neither the check nor the silent install runs, so pipelines stay deterministic. To opt out anywhere else (air-gapped or restricted networks), set:
export SQUIRREL_NO_UPDATE=1Any value other than empty, 0, or false (case-insensitive, surrounding whitespace ignored) enables the opt-out, so an empty or whitespace-only SQUIRREL_NO_UPDATE= does not suppress updates.
Both CI detection and SQUIRREL_NO_UPDATE only suppress the automatic paths; an explicit squirrel self update still works. (For a fully offline single run, use the --offline flag instead.)
Usage
squirrel self update [options]Options
| Option | Description |
|---|---|
--check | Only check for updates, don’t install |
--dismiss | Dismiss update notification for current version |
--force | Update even if this binary isn’t a managed install |
Examples
Check for updates
squirrel self update --checkOutput if update available:
Update available: v0.2.0
Run 'squirrel self update' to installOutput if up to date:
Already on latest version (0.1.0)Install update
squirrel self updateOutput:
Updated to v0.2.0
See release notes: https://github.com/squirrelscan/squirrelscan/releases/tag/v0.2.0Dismiss update notification
squirrel self update --dismissThis dismisses the update notification until the next version is released. A dismissed version is also skipped by automatic updates.
Update channels
squirrel has two update channels configured via settings:
stable- Production releases (recommended)beta- Pre-release versions with latest features
Change channel:
squirrel self settings set channel betacompletion
Generate shell completion scripts for bash, zsh, or fish.
Usage
squirrel self completion <shell>Arguments
| Argument | Description |
|---|---|
shell | Shell type: bash, zsh, or fish (required) |
Examples
Bash
Add to ~/.bashrc:
eval "$(squirrel self completion bash)"Zsh
Add to ~/.zshrc:
eval "$(squirrel self completion zsh)"Fish
Add to ~/.config/fish/config.fish:
squirrel self completion fish | sourceWhat it provides
Completions include:
- Command names
- Subcommand names
- Option flags
- File paths for relevant arguments
doctor
Run health checks on your installation.
Usage
squirrel self doctorOutput
Running health checks...
[OK] Binary: Executable found at ~/.local/bin/squirrel
[OK] Version: 0.1.0
[OK] Permissions: Binary is executable
[OK] Config: Valid squirrel.toml found
[WARN] Cache: 125MB of cached data at ~/.local/share/squirrel
[OK] Settings: Valid settings at ~/.squirrel/settings.json
Passed: 5 | Warnings: 1 | Failed: 0What it checks
- Binary installation and permissions
- Config file validity
- Settings file validity
- Cache size and location
- Update status
- Content store size, its cap and the last eviction
The content store line reads like this:
[OK] Content store: 812.4 MB in 5,210 entries, cap 1.0 GB; last eviction 3h ago (1,204 entries, 205.3 MB)It warns when the store is over its cap, which happens after an audit larger
than the cap (an audit never evicts its own pages): the next audit evicts the
least recently used pages first. Change the cap with
[storage] content_store_max_bytes
or SQUIRREL_CONTENT_STORE_MAX_BYTES. The cap shown is the default or the
environment variable; a project’s squirrel.toml applies during its own audits.
Exit codes
| Code | Meaning |
|---|---|
0 | All checks passed (warnings are OK) |
1 | One or more checks failed |
disk
Reports what the squirrel data directory is costing, per project and in total.
squirrel self diskProjects
406 MB sweetdeals-com-au (7 audits)
194 MB acme-docs (13 audits)
86.8 MB www-example-com (2 audits)
... and 65 more
Totals
2.7 GB projects
948 MB content store (shared)
12.4 MB link cache (shared)
203 MB releases
4.0 MB logs
3.8 GB totalProjects are listed largest first. The count in brackets is how many audits that project has recorded.
The last 3 audits are kept. A successful audit retires anything older, so a
project settles at roughly the size of its window instead of growing by one
audit every run. On a 1,000-page site an audit is about 95 MB, and most of it is
the per-check results: around 204 rows per page, which with their indexes are
about 70% of the file. Change the window, or turn retention off, with
[storage] keep_audits.
Retiring frees that space inside the file for the next audit to reuse rather
than returning it to the filesystem, which is what --prune below is for.
The content store and the external-link cache are shared by every project rather than owned by one, so they are reported separately. A shared database that has been pointed inside a project directory is counted once, against that directory.
Options
| Flag | Description |
|---|---|
--json | Emit the usage as JSON, for scripting |
--limit <n> | Show at most this many projects (default 15) |
Reporting opens each project database read-only, and the command is excluded from the usual startup maintenance, so running it will not rotate the logs it is about to measure.
Reclaiming space
--prune retires the audits beyond the newest --keep, then rebuilds the
database so the space returns to the filesystem.
squirrel self disk --prune --keep 3 --dry-run
squirrel self disk --prune --keep 3--keep is required and has no default, and it is independent of
[storage] keep_audits: this command reclaims to the
window you name here, on the projects it finds, and rebuilds each file. Use it
to hand space back to the filesystem, to prune below the automatic window, or to
clear a backlog on a project you have not audited since retention arrived.
A retired audit’s report can no longer be rendered, and report --list,
report --diff and report --regression-since all reach back into that
history, so how many audits to keep is your call rather than a number this
command picks for you.
Abandoned crawls
An audit killed before it finishes (kill -9, a watchdog, an out-of-memory
kill) leaves its crawl behind as running, paused, stopped or crawled.
Once a newer audit of the project has finished and the crawl has had no activity
(no page fetched) for 30 minutes, nothing can resume or analyze it, so --prune
treats it as abandoned. stopped and paused crawls, which --resume continues
(Ctrl-C leaves one), wait 7 days idle instead. A failed crawl follows the same
rule as the others and never takes a slot of the --keep window: it retires it, and it takes no
slot of the --keep window. --dry-run lists these apart from the finished
audits, with each crawl’s status and age:
acme-docs 2.3 GB retiring 2 of 5 audits
2026-09-07 6a1b45df
abandoned (never finished, older than the newest finished audit):
2026-10-02 7021c515 crawled, 17d oldWhile an audit, crawl or analyze runs, the process records itself on the
crawl: its pid, host name and a heartbeat refreshed every 15 seconds, and it
clears the owner when the command ends. --prune and the automatic retirement
read it, so liveness is recorded rather than guessed from newer audits:
- A crawl whose heartbeat is under 5 minutes old is never retired, even when a later audit of the project finished first (two audits running at once).
- A heartbeat older than that does not retire it while its owner process is still alive on this machine, for up to 24 hours of silence. That covers a busy or suspended audit (a sleeping laptop: the heartbeat resumes within 15 seconds of waking). After 24 hours a pid is not trusted, because it may have been reused by another program. A container that shares a host name with the host cannot see the host’s pids, so it cannot tell a live owner from a dead one that way.
- An owner on another machine, or one that cannot be read, counts as live until the 5 minutes pass.
- A killed crawl whose owner is gone is retired without waiting for a later
audit to finish, once its heartbeat is stale: a
crawledcrawl after 5 minutes, arunningcrawl (what--resumecontinues) after 24 hours. Astopped,pausedorfailedcrawl is never retired sooner by a dead lease; it follows the idle rules above (7 days forstoppedandpaused). In every case a newer finished audit plus 30 minutes idle retires it as before. - A crawl written by an older version carries no lease and follows the rules
above. A crawl whose command ended normally (Ctrl-C, or
crawlwaiting foranalyze) clears its owner and follows them too.
--dry-run lists a held crawl as skipped with its owner pid, host and the age of
its last heartbeat.
An unfinished crawl (including a failed one) newer than the newest finished
audit, or still within its idle time, is never retired. It may be a live audit, or a crawl waiting for squirrel analyze, so it is listed
as skipped with that reason instead.
Summary and exit code
Each project is handled on its own. A project that cannot be planned or pruned (a locked or unreadable database, for example) is reported with its reason and the rest still run. A crawl that becomes active between the plan and the write is skipped on its own, and the rest of that project is still retired. When the volume does not have room for the rebuild, the project’s crawls are still retired, the rebuild is skipped and the project is reported as skipped. A final line counts the projects pruned, skipped and failed, and the bytes reclaimed. The command exits 1 only when at least one project failed; a skip is not a failure.
Pressing Ctrl-C during squirrel audit records the interrupted crawl as
stopped, so --resume continues it and it is not mistaken for a killed one.
A project whose old audits an audit already retired has nothing left to retire and is still holding the space those deletes freed, so the plan offers the rebuild on its own:
Keeping the newest 3 audit(s) per project.
acme-docs 412 MB rebuilding to return 96.4 MB
Nothing left to retire: 96.4 MB across 1 project(s) is already free inside the
files and only a rebuild returns it.
Rebuild? [y/N]The plan is printed and confirmed before anything is deleted:
Keeping the newest 1 audit(s) per project.
acme-docs 11.5 MB retiring 1 of 2 audits
2026-09-07 6a1b45df
12,635 rows across 1 project(s). Their reports stop being renderable; the audits stay listed.
Retire them? [y/N]| Flag | Description |
|---|---|
--prune | Retire audits beyond --keep and reclaim the space |
--keep <n> | How many recent audits per project stay renderable. Required |
--project <name> | Limit the prune to one project directory |
--dry-run | List what would go and stop |
--yes | Skip the confirmation prompt |
What retiring removes is a crawl’s rule results, sitemaps, page features and
frontier, plus the page rows a newer audit already supersedes. What it keeps is
everything the next audit reads: the newest page record per URL (so an
incremental re-crawl still gets its ETag rather than refetching the site), the
sub-resource records, the links and images (a reused page copies those forward
from whichever crawl last saw them), and the crawls row itself, so the audit is
still listed.
A retired audit is marked as such and says when its data went:
06148d76 8 Sep 2026, 10:49 1 retired -
https://example.com
data reclaimed on 2026-09-08; this audit can no longer be openedOpening it, diffing against it, or using it as a --regression-since baseline
all refuse with the same sentence rather than rendering an empty report.
Measured on two audits of a 60-page site: 11.5 MB to 5.7 MB, and the next audit still reported every page unchanged rather than refetching it.
version
Show version information about the CLI.
Usage
squirrel self version [options]Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
Human-readable
squirrel self versionOutput:
squirrel v0.1.0
Channel: stable
Platform: darwin-arm64
Bun: 1.1.38JSON output
squirrel self version --jsonOutput:
{
"version": "0.1.0",
"channel": "stable",
"platform": "darwin-arm64",
"bun_version": "1.1.38"
}settings
Manage CLI settings stored at ~/.squirrel/settings.json or .squirrel/settings.json (local project).
Subcommands
show- Display settingsset- Update a setting
settings show
Display current settings.
Usage
squirrel self settings show [options]Options
| Option | Description |
|---|---|
--user | Show only user settings (~/.squirrel/settings.json) |
--local | Show only local project settings (.squirrel/settings.json) |
Examples
Effective settings (default)
Shows merged settings with source tracking:
squirrel self settings showOutput:
Effective Settings:
channel = stable (default)
auto_update = true (user)
notifications = true (local)
log_level = info (default) (read-only)
User: ~/.squirrel/settings.json
Local: /path/to/project/.squirrel/settings.jsonUser settings only
squirrel self settings show --userOutput:
User Settings (~/.squirrel/settings.json):
channel = stable
auto_update = true
user_feedback_email = you@example.comLocal settings only
squirrel self settings show --localOutput:
Local Settings (/path/to/project/.squirrel/settings.json):
notifications = falsesettings set
Update a setting value.
Usage
squirrel self settings set <key> <value> [options]Arguments
| Argument | Description |
|---|---|
key | Setting key (required) |
value | New value (required) |
Options
| Option | Description |
|---|---|
--local | Set in local project settings (.squirrel/settings.json) |
--user | Set in user settings (~/.squirrel/settings.json) (default) |
Available settings
| Key | Type | Description | Values |
|---|---|---|---|
channel | string | Update channel | stable, beta |
auto_update | boolean | Automatic background updates | true, false |
skills_auto_update | boolean | Update the installed agent skills along with the CLI (needs auto_update) | true, false |
update_check_interval_hours | number | How often the background update check may run (hours) | >= 0.05 (default 1) |
notifications | boolean | Show update notifications | true, false |
telemetry | boolean | Send minimal pseudonymous CLI telemetry | true, false |
tips | boolean | Show a random tip under the audit preamble | true, false |
Examples
Switch to beta channel
squirrel self settings set channel betaOutput:
Set channel = beta (user)
Written to: ~/.squirrel/settings.jsonDisable update notifications
squirrel self settings set notifications falseSet local project setting
squirrel self settings set notifications false --localThis creates .squirrel/settings.json in the current directory and sets the value there.
Telemetry
Telemetry is enabled by default. The CLI sends only the event name, CLI version, a random install ID, and a bounded error category. It does not send credentials, URLs, report contents, or raw error messages, and telemetry requests are never authenticated.
The CLI shows this disclosure once before its first telemetry-enabled command. Disable telemetry in user settings with:
squirrel self settings set telemetry falseFor CI, containers, or one-off commands, define NO_TELEMETRY. Its presence is the kill switch: any defined value, including an empty value, 0, or false, disables telemetry, install registration, and install-ID creation.
NO_TELEMETRY=1 squirrel audit https://example.comuninstall
Remove the managed install: the squirrel link, the release binaries, and with --purge your settings and data too.
Usage
squirrel self uninstall [options]Options
| Option | Description |
|---|---|
--purge | Also remove ~/.squirrel (settings, credentials, audit data) and the cache directory |
--yes | Skip the confirmation prompt |
--force | Same as --yes, kept for older scripts |
Examples
Interactive uninstall
squirrel self uninstallThis will remove:
- ~/.local/bin/squirrel
- ~/.squirrel/releases
Settings and credentials in ~/.squirrel are kept. Use --purge to remove them too.
Continue? [y/N]Remove everything
squirrel self uninstall --purgeWithout a prompt
squirrel self uninstall --yesWithout a terminal to ask in (a script, CI, a package manager hook), the command refuses to delete anything unless you pass --yes.
What gets removed
| Item | Default | With --purge |
|---|---|---|
The squirrel link (~/.local/bin/squirrel, or the directory you passed to self install --bin-dir) | Removed | Removed |
Release binaries (~/.squirrel/releases) | Removed | Removed |
Settings and credentials (~/.squirrel/settings.json) | Kept | Removed |
Audit data and logs (~/.squirrel/projects, ~/.squirrel/logs) | Kept | Removed |
Cache (~/Library/Caches/squirrel on macOS, ~/.cache/squirrel on Linux) | Kept | Removed |
Project configs (squirrel.toml) in your repositories | Kept | Kept |
On Windows the same layout lives under %LOCALAPPDATA%\squirrel, and the command removes the squirrel.exe in its bin folder. Windows locks a running exe, so the command first moves it to your temp folder. If it still cannot be deleted there, the command prints its path to delete afterwards.
Running it again after a successful uninstall finds nothing to remove and exits 0.
Shell completions
self install and self completion never write completion files. self completion prints a script, and your shell config runs it. If you added a line such as eval "$(squirrel self completion zsh)", remove it yourself. The command reminds you when it finishes.
Safety
self uninstall only deletes what a squirrelscan install put there:
- Every path is resolved with
realpathand must lie inside the managed directories. - A
squirrellink that points anywhere other than~/.squirrel/releasesis reported and left alone. So is a plain file at that path. - It never follows a symlink out of a managed directory. A symlinked
~/.squirrelor~/.squirrel/releasesis reported and left for you to remove. - A symlink inside the releases is removed as a link. What it points to is not touched.
- It refuses to run from a binary that is not the managed install, such as one you placed by hand. Run
~/.local/bin/squirrel self uninstallinstead. - Each path is checked again right before it is deleted, and skipped if it changed since the plan was printed.
Related
- Configuration - Project config file options
- CLI Reference - All CLI commands