1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2026 VKrishna04
// SPDX-License-Identifier: Apache-2.0
// Centralized application constants and default configurations.
//
// Serves as the single source of truth for app metadata, versioning,
// default thresholds, and file paths.
/// Application crate version derived dynamically from `Cargo.toml`.
pub const VERSION: &str = env!;
/// Application name.
pub const APP_NAME: &str = "dev-prune";
/// Author of dev-prune.
pub const AUTHOR: &str = "VKrishna04";
/// Canonical source repository.
///
/// The one in `Cargo.toml` is only visible to people who already found the crate. This
/// one is compiled into the binary, so a copy of the executable still says where it came
/// from.
pub const REPO_URL: &str = "https://github.com/Life-Experimentalist/dev-prune";
/// Project homepage.
pub const HOMEPAGE_URL: &str = "https://devprune.vkrishna04.me";
/// The one-line credit printed under interactive output.
///
/// Deliberately plain text in plain sight: it is not obfuscated, not assembled at
/// runtime, and not checked anywhere. Anyone may fork this project and change this line
/// — the Apache-2.0 licence says so, and nothing in the code argues. It exists so that
/// the common case, someone running the published binary, shows where it came from.
pub const ATTRIBUTION_LINE: &str =
"dev-prune · made with ♥ by VKrishna04 · github.com/Life-Experimentalist/dev-prune";
/// The body of `devp --version`.
///
/// Built at runtime rather than with `concat!`, which only takes literals and would mean
/// spelling the author and the URL a second time. Two copies of a string are two things
/// that can disagree, and this one exists precisely so that a stray copy of the binary
/// can still be traced back.
pub static LONG_VERSION: LazyLock = new;
/// How many prune passes `devp stats` keeps a summary of.
///
/// The registry is rewritten in full on every save, so this list is a file-size decision
/// as much as a display one. Fifty passes is roughly a year of a fortnightly schedule.
pub const PRUNE_HISTORY_LIMIT: usize = 50;
/// The release that started recording per-repository totals and the pass history.
///
/// A machine that pruned for months on 1.0.0 has a large lifetime total and no history at
/// all, and reading that as "nothing was ever pruned here" would be wrong. Both `devp
/// stats` and its `--json` document quote this version so the gap is explained rather than
/// looking like data loss. It is deliberately not [`VERSION`]: it names the release the
/// format changed in, and does not move again.
pub const HISTORY_STARTS_AT: &str = "1.1.0";
/// Default idle threshold in days before a repository is eligible for pruning.
pub const DEFAULT_IDLE_DAYS: u64 = 15;
/// Default interval in days between background daemon prune runs.
pub const DEFAULT_CHECK_INTERVAL_DAYS: u64 = 2;
/// Whether the setup pass installs the OS scheduler.
///
/// On. A pruner that has to be remembered is a pruner that never runs; the scheduled
/// pass is the product, not an extra. It is still bounded by everything an interactive
/// run is bounded by — idle threshold, lockfile verification, per-repo opt-outs — and
/// `devp daemon uninstall` (or `devp config set auto_daemon false`) removes it.
pub const DEFAULT_AUTO_DAEMON: bool = true;
/// Whether the setup pass installs the global Git auto-registration hooks.
///
/// On, but conditionally: installation is skipped, not forced, when `core.hooksPath`
/// already belongs to husky, pre-commit or lefthook.
pub const DEFAULT_AUTO_HOOKS: bool = true;
/// Whether dev-prune installs its missing integrations by itself.
///
/// On. The pass runs once per installed version — on first run, and again after an
/// upgrade — and only creates what is absent. Set to `false`, or export
/// `DEV_PRUNE_NO_AUTO_SETUP`, to manage the integrations entirely by hand.
pub const DEFAULT_AUTO_SETUP: bool = true;
/// Default setting for requiring interactive confirmation before pruning.
pub const DEFAULT_REQUIRE_CONFIRMATION: bool = true;
/// Default size floor, in MiB, below which a bloat directory is left alone.
///
/// Zero — every recognised directory is a candidate. Raising it trades a little disk
/// space for fewer reinstalls: deleting a 3 MiB `node_modules` costs a full `npm ci`
/// and reclaims almost nothing.
pub const DEFAULT_MIN_SIZE_MB: u64 = 0;
/// How far below a repository root project discovery descends, by default.
///
/// Six covers `packages/scope/name/…` monorepo layouts with room to spare while keeping
/// the walk bounded on repositories with deep source trees. Configurable with
/// `devp config set scan_depth`, and per repository with `"scan_depth"` in
/// `.devprune.json`, because "deep enough" is a property of the layout, not of the tool.
pub const DEFAULT_SCAN_DEPTH: usize = 6;
/// Upper bound accepted for `scan_depth`.
///
/// Not a matter of taste. The walk is breadth-first over every directory that is not
/// excluded, so cost grows with the tree, and a repository with a deep generated tree
/// (a Bazel `bazel-out`, a `.terraform` provider cache) can turn an unbounded walk into
/// a multi-minute stall on a background pass nobody is watching.
pub const MAX_SCAN_DEPTH_LIMIT: usize = 32;
/// Whether an adapter whose sync command edits tracked manifests may run it.
///
/// Off. `cargo generate-lockfile` re-resolves every dependency and rewrites
/// `Cargo.lock`; `go mod tidy` edits `go.mod` and `go.sum` and can drop requirements.
/// A cleanup tool that silently changes files Git tracks has done something the user
/// did not ask for, so these run read-only and this switch is the informed opt-in.
pub const DEFAULT_ALLOW_MANIFEST_REWRITE: bool = false;
/// Whether the setup pass installs the Git hooks in front of another tool's.
///
/// Off. Chaining is behaviour-preserving — every hook is forwarded on and
/// `devp hook uninstall` restores the original `core.hooksPath` — but it still rewires
/// somebody else's Git configuration, which is not a thing to do unasked. Turn it on
/// with `devp config set auto_hooks_chain true`, or do it once with
/// `devp hook install --chain`.
pub const DEFAULT_AUTO_HOOKS_CHAIN: bool = false;
/// GitHub releases page, shown whenever an upgrade is relevant.
pub const RELEASES_URL: &str = "https://github.com/Life-Experimentalist/dev-prune/releases";
/// GitHub API endpoint for the latest published release.
///
/// Contacted only by `devp update --check`, never on any other code path. See the
/// network policy in `docs/PRIVACY.md`.
pub const LATEST_RELEASE_API_URL: &str =
"https://api.github.com/repos/Life-Experimentalist/dev-prune/releases/latest";
/// Whether the periodic release check runs. On by default — see `Settings::update_check`.
pub const DEFAULT_UPDATE_CHECK: bool = true;
/// Default interval, in days, between automatic release checks.
///
/// A week. Frequent enough that a security fix is not missed for long, rare enough that
/// it is invisible in day-to-day use. Override with
/// `devp config set update_check_interval_days`.
pub const UPDATE_CHECK_INTERVAL_DAYS: i64 = 7;
/// Default timeout for the release check. Short on purpose — this is a convenience,
/// and a user waiting on a hung socket is worse than not knowing. Override with
/// `devp config set update_check_timeout_secs` when a proxy needs longer.
pub const UPDATE_CHECK_TIMEOUT_SECS: u64 = 5;
/// Name of the registry JSON file.
pub const REGISTRY_FILENAME: &str = "registry.json";
/// Config directory name under user config root.
pub const CONFIG_DIR_NAME: &str = "dev-prune";
/// Global environment variable name to override config directory location.
pub const ENV_CONFIG_DIR_OVERRIDE: &str = "DEV_PRUNE_CONFIG_DIR";
/// Filename that, when present in a repo root, causes dev-prune to skip that repo entirely.
///
/// Create this file with: `touch ignore.devprune.json`
pub const DEVPRUNE_IGNORE_FILE: &str = "ignore.devprune.json";
/// Default timeout in seconds for lockfile enforcement / CLI commands (10 minutes).
pub const DEFAULT_COMMAND_TIMEOUT_SECS: u64 = 600;
/// Timeout for the "where does your cache live?" queries `devp caches` makes.
///
/// Deliberately not `command_timeout_secs`. That ceiling is sized for `npm ci` and
/// `cargo metadata`; `npm config get cache` prints one line and returns. A query that
/// has not answered in five seconds is a broken installation, and the report is better
/// off falling back to the conventional path than waiting ten minutes for it.
pub const CACHE_QUERY_TIMEOUT_SECS: u64 = 5;
/// Documentation URL for troubleshooting lockfile and pruning failures.
pub const TROUBLESHOOTING_URL: &str = "https://devprune.vkrishna04.me/docs/troubleshooting";
/// Name of the structured per-repository configuration file stored inside repo roots.
pub const PER_REPO_CONFIG_FILE: &str = ".devprune.json";
/// Public URL for the JSON Schema used by IDEs for .devprune.json IntelliSense.
pub const JSON_SCHEMA_URL: &str = "https://devprune.vkrishna04.me/schemas/v1/devprune.schema.json";
/// Directory under the user's home that marks a Claude Code installation.
///
/// Its presence is how the setup pass decides the machine has an agent to install the
/// skill for; the directory itself is only ever created by Claude Code.
pub const CLAUDE_HOME_DIR: &str = ".claude";
/// Subdirectory of an agent's home where Agent Skills live, one directory per skill.
pub const AGENT_SKILLS_SUBDIR: &str = "skills";
/// Marketplace identifier (`publisher.name`) of the VS Code extension, as understood
/// by `code --install-extension`.
pub const VSCODE_EXTENSION_ID: &str = "VKrishna04.dev-prune";