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
208
209
210
211
212
[]
= "dev-prune"
= "1.5.0"
= "2024"
= ["VKrishna04"]
= "Universal, lockfile-safe workspace pruner and background dependency cleaner"
= "Apache-2.0"
= "README.md"
= "https://github.com/Life-Experimentalist/dev-prune"
= "https://devprune.vkrishna04.me"
# Not docs.rs. This is a binary crate: docs.rs would build the library surface, which is
# nothing anyone installing `dev-prune` wants to read. Point at the docs that describe
# the commands instead — crates.io links this field directly.
= "https://github.com/Life-Experimentalist/dev-prune/blob/main/docs/README.md"
= ["cli", "workspace", "cleanup", "node_modules", "venv"]
# Five is the crates.io maximum and every one of them is a category page this tool
# genuinely belongs on — those pages are how people browsing crates.io find it at all.
= [
"command-line-utilities",
"development-tools",
"development-tools::build-utils",
"filesystem",
"caching",
]
= "1.88"
# An allowlist, not an exclude list, and deliberately so.
#
# Three of these entries are load-bearing: `build.rs` reads `assets/icon.ico`, and the
# binary embeds `schemas/`, `assets/mimetype/` and `.agents/skills/dev-prune/SKILL.md`
# with `include_bytes!`/`include_str!`. A published crate missing any of them does not
# fail at runtime — it fails to compile, for everyone, and the only fix is a new version.
#
# The dotted path has to be spelled out: cargo does not pick up `.agents/` on its own.
# `site/` is omitted on purpose; its `node_modules` is 16k files and belongs nowhere near
# a crate tarball.
= [
"/src",
"/tests",
"/build.rs",
"/Cargo.toml",
"/Cargo.lock",
"/README.md",
"/LICENSE.md",
"/NOTICE",
"/CHANGELOG.md",
"/SECURITY.md",
"/clippy.toml",
"/rustfmt.toml",
"/docs",
"/schemas",
"/assets/icon.ico",
"/assets/icon.png",
"/assets/icon.icns",
"/assets/mimetype",
"/assets/README.md",
"/.agents/skills/dev-prune/SKILL.md",
"/.agents/rules/dev-prune.rules.md",
]
# `cargo install dev-prune` compiles from source, because crates.io stores source and
# nothing else — there is no binary on the registry for cargo to fetch. `cargo binstall
# dev-prune` reads the table below, downloads the matching GitHub release asset and
# unpacks the executable, so it needs no toolchain and finishes in seconds.
#
# The URLs restate the asset names built by `.github/workflows/release.yml`, which are
# already a contract with `scripts/install.sh` and `scripts/install.ps1`. binstall's own
# `{ target-arch }` / `{ target-family }` placeholders expand to `x86_64` and `unix`, not
# the `x64` and `darwin` this project uses, so every target is spelled out. Renaming an
# asset means editing this table too, and `cargo binstall` failing over to a from-source
# build is the only symptom if it is forgotten.
#
# Both libc flavours of each Linux target are listed: binstall probes the host and asks
# for gnu or musl depending on what it finds, while the published asset is one statically
# linked musl build that serves both.
[]
= "{ bin }{ binary-ext }"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-x64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-x64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-arm64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-arm64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-darwin-x64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-darwin-arm64.tar.gz"
= "tgz"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-windows-x64.zip"
= "zip"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-windows-arm64.zip"
= "zip"
[]
= "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-windows-x86.zip"
= "zip"
[[]]
= "dev-prune"
= "src/main.rs"
[]
# CLI argument parsing
= { = "4", = ["derive", "color", "suggestions"] }
# Shell completion scripts for `devp completions`. Generated from the same clap
# definition the binary parses with, so a new flag cannot be missing from them.
= "4"
# Man pages for `devp man`. Same clap definition again, same reason.
= "0.3"
# Serialization
= { = "1", = ["derive"] }
= "1"
# Error handling
= "1"
# Timestamps & time
= { = "0.4", = ["serde"] }
# Cross-platform paths
= "6"
# Directory walking
= "2"
# Terminal UI & Spinners
#
# crossterm is held at 0.29 because ratatui 0.30's default `crossterm_0_29` feature
# depends on it. Taking a different crossterm on its own puts two copies of the
# terminal's raw-mode state in one binary, and ratatui's MSRV moves with it (0.30 is
# what pushed `rust-version` to 1.88). Bump all three together, or none.
= "0.30"
= "0.29"
= "0.18"
# Terminal column widths for the plain-text tables.
#
# Not a new dependency: ratatui-core, indicatif and console all already pull this in,
# so it is compiled into the binary either way. Naming it directly costs nothing and
# buys correct alignment for CJK and emoji paths, where one `char` occupies two
# columns and `{:<35}` — which counts `char`s — overshoots by the number of wide
# characters in the name.
= "0.2"
# Colored terminal output
= "3"
# Human-readable byte sizes
= "2"
# HTTP. Used by exactly one module — `commands::update` — and nothing else in the binary
# opens a socket. rustls with bundled roots rather than the platform verifier, so the
# release check behaves the same on a bare CI container as on a developer laptop.
= { = "3.4", = false, = ["rustls", "gzip"] }
# SHA-256, for `devp update --install`: the release publishes an uncompressed binary
# beside each archive, and the sidecar hash is the only thing standing between a
# download and executing it. Verification is the whole point of the direct route, so
# this is not an optional dependency. Nothing else is pulled in to unpack an archive —
# that is why the raw binary is published at all.
= "0.11"
# Restoring the default SIGPIPE disposition, which Rust ignores at startup. Without it
# `devp status | head` dies in a panic instead of exiting quietly.
[]
= "0.2"
# Hardlink counts. pnpm and bun link store files into `node_modules` instead of copying
# them, and on Windows the link count lives behind an opened handle
# (`GetFileInformationByHandle`) — std only exposes it on unstable. Already in the
# dependency tree transitively, so this pins no new crate.
[]
= { = "0.61", = [
"Win32_Foundation",
"Win32_Storage_FileSystem",
# `GetConsoleWindow`, for the child-window policy in `src/spawn.rs`.
"Win32_System_Console",
] }
[]
# Mock filesystems for testing
= "3"
# Assertions
= "2"
= "3"
[]
= "0.1"
[]
= true
= 1
= true
= 3