dev-prune 1.2.0

Universal, lockfile-safe workspace pruner and background dependency cleaner
Documentation
[package]
name = "dev-prune"
version = "1.2.0"
edition = "2024"
authors = ["VKrishna04"]
description = "Universal, lockfile-safe workspace pruner and background dependency cleaner"
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/Life-Experimentalist/dev-prune"
homepage = "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.
documentation = "https://github.com/Life-Experimentalist/dev-prune/blob/main/docs/README.md"
keywords = ["cli", "workspace", "cleanup", "node_modules", "venv"]
categories = ["command-line-utilities", "development-tools"]
rust-version = "1.85"

# 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.
include = [
    "/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",
]

# `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.
[package.metadata.binstall]
bin-dir = "{ bin }{ binary-ext }"

[package.metadata.binstall.overrides.x86_64-unknown-linux-gnu]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-x64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.x86_64-unknown-linux-musl]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-x64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.aarch64-unknown-linux-gnu]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-arm64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.aarch64-unknown-linux-musl]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-linux-arm64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.x86_64-apple-darwin]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-darwin-x64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.aarch64-apple-darwin]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-darwin-arm64.tar.gz"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-windows-x64.zip"
pkg-fmt = "zip"

[package.metadata.binstall.overrides.aarch64-pc-windows-msvc]
pkg-url = "{ repo }/releases/download/v{ version }/dev-prune-v{ version }-windows-arm64.zip"
pkg-fmt = "zip"

[[bin]]
name = "dev-prune"
path = "src/main.rs"

[dependencies]
# CLI argument parsing
clap = { version = "4", features = ["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.
clap_complete = "4"

# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"

# Error handling
anyhow = "1"

# Timestamps & time
chrono = { version = "0.4", features = ["serde"] }

# Cross-platform paths
dirs = "6"

# Directory walking
walkdir = "2"

# Terminal UI & Spinners
#
# crossterm is held at 0.28 because ratatui 0.29 depends on it. Taking crossterm 0.29 on
# its own puts two copies of the terminal's raw-mode state in one binary, and the ratatui
# release that wants 0.29 is 0.30, whose MSRV is 1.88 — above the 1.85 this crate
# advertises. Bump all three together, or none.
ratatui = "0.29"
crossterm = "0.28"
indicatif = "0.18"

# Colored terminal output
colored = "3"

# Human-readable byte sizes
humansize = "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.
ureq = { version = "3.4", default-features = false, features = ["rustls", "gzip"] }

# Restoring the default SIGPIPE disposition, which Rust ignores at startup. Without it
# `devp status | head` dies in a panic instead of exiting quietly.
[target.'cfg(unix)'.dependencies]
libc = "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.
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_Storage_FileSystem"] }

[dev-dependencies]
# Mock filesystems for testing
tempfile = "3"
# Assertions
assert_cmd = "2"
predicates = "3"

[target.'cfg(windows)'.build-dependencies]
winres = "0.1"

[profile.release]
lto = true
codegen-units = 1
strip = true
opt-level = 3