tools/tool-wrapper.design.md
A reusable system for downloading, verifying, and executing external tools with fixed versions and cryptographic checksums.
# Run uv (downloads automatically on first run)
./community/tools/uv.cmd --version
# Run npx (downloads Node.js automatically on first run)
./community/tools/npx.cmd --version
# Verify all platform binaries (CI/release verification)
TOOL_VERIFY_ALL_PLATFORMS=1 ./community/tools/uv.cmd
TOOL_VERIFY_ALL_PLATFORMS=1 ./community/tools/npx.cmd
┌─────────────┐ sets env vars ┌──────────────────┐
│ uv.cmd │ ────────────────────▶ │ tool-wrapper.* │
│ (polyglot) │ │ (.sh / .cmd) │
└─────────────┘ └────────┬─────────┘
│
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Check cache │ │ Download to │ │ Verify SHA256 │
│ for binary │──miss──▶ │ temp file │────────▶ │ checksum │
└───────────────┘ └───────────────┘ └───────┬───────┘
│ │
│ hit ┌───────┴───────┐
│ │ │
▼ pass ▼ fail ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ┌─────────┐
│ Execute with │◀─────────│ Extract with │◀─│ Validate │ │ Delete │
│ passthrough │ │ strip & cache │ │ structure │ │ & exit │
│ arguments │ └───────────────┘ └───────────────┘ └─────────┘
└───────────────┘
| Decision | Choice | Rationale |
|---|---|---|
| Configuration storage | Embedded in script | Self-contained, single file to update |
| Checksum algorithm | SHA-256 | Industry standard, published by releases |
| Error handling | Hard fail, never save bad downloads | Security first |
| Download tool (Unix) | curl | Standard, available everywhere |
| Download tool (Windows) | PowerShell (only when needed) | Native, no external dependencies |
| Archive extraction | Auto-detect and strip if nested | Handles both nested (single top-level dir) and flat archives |
| Archive structure | Support nested and flat | Nested archives stripped, flat archives extracted directly |
| Retry logic | None | Simple, user can retry manually |
| Version override | Not supported | Version pinned in script, no bypass |
| Windows arch detection | Registry query | More reliable than env var |
| Path handling | Quote all paths | Support spaces in usernames/paths |
| Concurrency | File locking (hard links on Unix, Mutex on Windows) | Safe for parallel runs |
| Cache scope | Full extracted tree | Supports tools with multiple files |
| Platform | Architecture | Target Triple (uv) |
|---|---|---|
| Linux | x86_64 | x86_64-unknown-linux-gnu |
| Linux | aarch64 | aarch64-unknown-linux-gnu |
| Windows | x64 | x86_64-pc-windows-msvc |
| Windows | arm64 | aarch64-pc-windows-msvc |
| macOS | x64 | x86_64-apple-darwin |
| macOS | arm64 | aarch64-apple-darwin |
# Linux
~/.cache/JetBrains/monorepo-tools/<tool>/<version>/<extracted-contents>
# macOS
~/Library/Caches/JetBrains/monorepo-tools/<tool>/<version>/<extracted-contents>
# Windows
%LOCALAPPDATA%\JetBrains\monorepo-tools\<tool>\<version>\<extracted-contents>
community/tools/<toolname>.cmd (polyglot script)TOOL_NAME - tool name (used in cache path)TOOL_VERSION - pinned versionTOOL_CHECKSUM_<PLATFORM> - SHA-256 for each platformTOOL_URL_<PLATFORM> - download URL for each platformTOOL_BINARY_UNIX - path to binary for Linux/macOS (e.g., uv or bin/npx)TOOL_BINARY_WINDOWS - path to binary for Windows (e.g., uv.exe or npx.cmd)tool-wrapper.sh (Unix) or tool-wrapper.cmd (Windows)# Required
TOOL_NAME="uv"
TOOL_VERSION="0.9.24"
# Checksums (SHA-256 of archive, not binary)
TOOL_CHECKSUM_LINUX_X64="abc123..."
TOOL_CHECKSUM_LINUX_ARM64="def456..."
TOOL_CHECKSUM_WINDOWS_X64="ghi789..."
TOOL_CHECKSUM_WINDOWS_ARM64="jkl012..."
TOOL_CHECKSUM_MACOS_ARM64="mno345..."
# Download URLs
TOOL_URL_LINUX_X64="https://github.com/.../uv-x86_64-unknown-linux-gnu.tar.gz"
TOOL_URL_LINUX_ARM64="https://github.com/.../uv-aarch64-unknown-linux-gnu.tar.gz"
TOOL_URL_WINDOWS_X64="https://github.com/.../uv-x86_64-pc-windows-msvc.zip"
TOOL_URL_WINDOWS_ARM64="https://github.com/.../uv-aarch64-pc-windows-msvc.zip"
TOOL_URL_MACOS_ARM64="https://github.com/.../uv-aarch64-apple-darwin.tar.gz"
# Binary path within extracted archive (after top-level directory is stripped)
TOOL_BINARY_UNIX="uv" # Used for Linux and macOS
TOOL_BINARY_WINDOWS="uv.exe" # Used for Windows
# Example for tools with subdirectory paths:
TOOL_BINARY_UNIX="bin/npx" # Node.js on Unix
TOOL_BINARY_WINDOWS="npx.cmd" # Node.js on Windows
The wrapper supports two archive structures:
Archives with exactly one top-level directory have it stripped during extraction
(like tar --strip-components=1), so TOOL_BINARY should be the path relative
to the contents of that top-level directory.
Example: If an archive contains:
uv-0.9.24-x86_64-unknown-linux-gnu/
├── uv
└── README.md
Then TOOL_BINARY="uv" and after extraction the cache will contain:
~/.cache/JetBrains/monorepo-tools/uv/0.9.24/
├── uv
└── README.md
Archives with multiple top-level entries (or files at root) are extracted directly
without stripping. TOOL_BINARY should be the direct path to the binary.
Example: If an archive contains:
uv.exe
uvw.exe
uvx.exe
Then TOOL_BINARY="uv.exe" (on Windows) and the cache will contain:
%LOCALAPPDATA%\JetBrains\monorepo-tools\uv\0.9.24\
├── uv.exe
├── uvw.exe
└── uvx.exe
Note: Some tools (like uv) use nested structure for tar.gz but flat structure for zip archives. The wrapper auto-detects and handles both cases.
Set TOOL_VERIFY_ALL_PLATFORMS=1 to download and verify all 5 platform variants:
TOOL_VERIFY_ALL_PLATFORMS=1 ./community/tools/uv.cmd
This mode:
TOOL_BINARY exists (using TOOL_BINARY_UNIX/TOOL_BINARY_WINDOWS if set)Useful for:
The tool wrapper is safe for parallel execution (e.g., multiple CI jobs or build processes).
Mechanism:
Behavior:
.complete flag file# Safe to run in parallel
for i in {1..10}; do ./community/tools/uv.cmd --version & done; wait
TOOL_BINARY exists after extractionWhen updating a tool version:
TOOL_VERSION and all TOOL_CHECKSUM_* values in the scriptTOOL_VERIFY_ALL_PLATFORMS=1 ./community/tools/<tool>.cmd to verify all checksums and archive structure./community/tools/<tool>.cmd --versionIMPORTANT: Each wrapper script contains a reminder comment about this requirement. Never skip the verification step - checksums from release notes may differ from actual archives.