Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,19 @@ jobs:
- name: Test every target with real CPU inference
run: cargo test --locked --workspace --all-targets

# The vendors' hosts are outside this project's control, so an outage
# there is reported here without blocking a build.
- name: Download and run the managed yt-dlp and FFmpeg
continue-on-error: true
run: cargo test --locked --test native_cli managed_downloads -- --ignored

- name: Build release executable
run: cargo build --locked --release -p justtools

- name: Build File Explorer extension
if: runner.os == 'Windows'
run: cargo build --locked --release -p justtools-shell

- name: Check release RMBG CPU inference
shell: pwsh
run: |
Expand All @@ -167,12 +177,40 @@ jobs:
- name: Package Windows artifact
if: matrix.archive == 'zip'
shell: pwsh
env:
JUSTTOOLS_SIGNING_PFX: ${{ secrets.JUSTTOOLS_SIGNING_PFX }}
JUSTTOOLS_SIGNING_PASSWORD: ${{ secrets.JUSTTOOLS_SIGNING_PASSWORD }}
run: |
$stage = "dist/${{ matrix.artifact }}"
$archive = "dist/${{ matrix.artifact }}.zip"
New-Item -ItemType Directory -Force -Path $stage | Out-Null
Copy-Item "target/release/${{ matrix.executable }}", README.md, AGENTS.md, LICENSE, THIRD_PARTY_LICENSES.md -Destination $stage
Copy-Item "target/release/justtools_shell.dll" -Destination $stage
Copy-Item docs, skills -Destination $stage -Recurse
if ($env:JUSTTOOLS_SIGNING_PFX) {
# A signed package identity is what admits the menu to the
# top-level Windows 11 context menu without Developer Mode.
$kit = Get-ChildItem "${env:ProgramFiles(x86)}/Windows Kits/10/bin/10.*/x64" -Directory |
Where-Object { Test-Path (Join-Path $_.FullName "makeappx.exe") } |
Sort-Object Name -Descending | Select-Object -First 1
if ($null -eq $kit) { throw "The Windows SDK packaging tools were not found." }
$certificate = Join-Path $env:RUNNER_TEMP "justtools-signing.pfx"
[IO.File]::WriteAllBytes($certificate, [Convert]::FromBase64String($env:JUSTTOOLS_SIGNING_PFX))
try {
$subject = (New-Object Security.Cryptography.X509Certificates.X509Certificate2(
$certificate, $env:JUSTTOOLS_SIGNING_PASSWORD)).Subject
$layout = Join-Path $env:RUNNER_TEMP "justtools-package"
& "target/release/${{ matrix.executable }}" context package --output $layout --publisher $subject
if ($LASTEXITCODE -ne 0) { throw "The package layout could not be written." }
$package = Join-Path $stage "justtools-shell.msix"
& (Join-Path $kit.FullName "makeappx.exe") pack /o /nv /d $layout /p $package
if ($LASTEXITCODE -ne 0) { throw "makeappx failed with exit code $LASTEXITCODE" }
& (Join-Path $kit.FullName "signtool.exe") sign /fd SHA256 /f $certificate /p $env:JUSTTOOLS_SIGNING_PASSWORD $package
if ($LASTEXITCODE -ne 0) { throw "signtool failed with exit code $LASTEXITCODE" }
} finally {
Remove-Item -LiteralPath $certificate -Force
}
}
Compress-Archive -Path "$stage/*" -DestinationPath $archive
$hash = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant()
$checksum = "$hash $([IO.Path]::GetFileName($archive))`n"
Expand Down Expand Up @@ -207,6 +245,11 @@ jobs:
& ./ready.ps1
& "$env:JUSTTOOLS_BIN/justready.exe" --help
& "$env:JUSTTOOLS_BIN/justcommit.exe" --help
if (-not (Test-Path -LiteralPath "$env:JUSTTOOLS_BIN/justtools_shell.dll" -PathType Leaf)) {
throw "The bootstrap did not install the File Explorer extension."
}
& "$env:JUSTTOOLS_BIN/just.exe" context status
if ($LASTEXITCODE -ne 0) { throw "just context status failed." }

- name: Exercise Unix bootstrap against packaged release
if: matrix.archive == 'tar.gz'
Expand Down
19 changes: 16 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Product contract

- Preserve one portable Rust binary with native `just*` aliases and short
dispatch through `just <tool>`.
dispatch through `just <tool>`. The only companion is the Windows File
Explorer extension, `justtools_shell.dll`, which holds no tool logic.
- A supported command with no arguments opens its console UI. Any explicit
argument or redirected input keeps deterministic headless behavior.
- Keep launchers visually consistent: saved settings are labeled, destination
Expand All @@ -12,8 +13,16 @@
- Persist changed defaults atomically. Never save inputs, payloads, credentials,
confirmation bypasses, or one-run actions such as kill, push, repair, check,
download, or dry run.
- Download only yt-dlp and FFmpeg without asking, only into the per-user
JustTools folder, and only after verifying the vendor's published SHA-256.
Every other dependency keeps its interactive confirmation.
- Preserve source files unless replacement is explicit. Reject ambiguous output
collisions before processing and install outputs atomically.
- Describe the File Explorer menu only in `explorer/menu`. A menu entry must be
an ordinary headless command or a launcher, must keep its source unless its
label says "in place", and must never pass `--yes`. Keep the menu one level
deep: Windows 11 leaves a nested flyout empty. The extension runs inside
Explorer and must not be able to panic.

## Changes

Expand All @@ -38,9 +47,13 @@ cargo +1.90.0 check --locked --workspace --all-targets
cargo build --locked --release -p justtools
```

On Windows, also build `-p justtools-shell`.

Exercise changed commands through both their bare launcher and explicit
headless form. For image operations, verify paths, formats, dimensions, alpha,
headless form. After changing the context menu, run `just context install` and
right-click a matching file in both the Windows 11 menu and "Show more options". For image operations, verify paths, formats, dimensions, alpha,
source retention, and overwrite behavior. Before pushing a version tag, require
a green six-platform branch matrix. Then verify the tagged run publishes all six
archives and their checksum sidecars, with `docs/`, `AGENTS.md`, and
`skills/justtools/` present in every archive.
`skills/justtools/` present in every archive and `justtools_shell.dll` in both
Windows archives.
79 changes: 76 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "justtools"
version = "2.5.0"
version = "2.6.0"
edition = "2024"
rust-version = "1.90"
description = "Fast, opinionated, cross-platform just* command-line tools"
license = "MIT"

[workspace]
members = ["ports/core-tools"]
members = ["explorer/menu", "explorer/shell", "ports/core-tools"]
default-members = ["."]
resolver = "3"

Expand All @@ -27,6 +27,7 @@ flate2 = "1.1"
image = { version = "0.25.10", default-features = false, features = ["bmp", "gif", "ico", "jpeg", "png", "pnm", "qoi", "tiff", "webp"] }
jpeg-encoder = "0.7.1"
justtools-core = { path = "ports/core-tools" }
justtools-menu = { path = "explorer/menu" }
netstat2 = "0.11.2"
ort = { version = "=2.0.0-rc.13", default-features = false, features = ["api-22", "coreml", "cuda", "directml", "load-dynamic", "std"] }
rayon = "1.10"
Expand All @@ -45,7 +46,7 @@ webp = { version = "0.3.1", default-features = false }
zip = { version = "4.3", default-features = false, features = ["deflate"] }

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_UI_WindowsAndMessaging"] }
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_System_DataExchange", "Win32_System_Memory", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
winreg = "0.55"

[dev-dependencies]
Expand Down
43 changes: 38 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ Windows, macOS, and Linux on x64 and ARM64.
just # browse every tool
justvideo # interactive console
justvideo clip.mov # direct/headless execution
justvideo clip.mov --resolution 1080p # 480p, 720p, 1080p, 1440p, 4k, source
justaudio https://example.com/watch?v=ID # yt-dlp download, then convert
justpaste --clipboard # download whatever the copied link is
justoptimize hero.png --dry-run
justrmbg portrait.jpg
```
Expand All @@ -46,11 +49,13 @@ and one-run actions never persist. The bottom line always shows the exact
| Need | Commands |
| --- | --- |
| Images | `justoptimize`, `justcrop`, `justjpg`, `justpng`, `justwebp`, `justavif`, `justresize`, `justrmbg` |
| Audio and video | `justaudio`, `justmp3`, `justwav`, `justvideo` |
| Audio and video | `justaudio`, `justmp3`, `justwav`, `justvideo` (also accept `http(s)` URLs) |
| Downloads | `justpaste` saves any link: a file as-is, a page through yt-dlp |
| Documents and data | `justjson`, `justpdf`, `justlinks`, `justsvg`, `justqr` |
| Development | `justports`, `justport`, `bunt`, `justcommit`, `justzip` |
| Development | `justports`, `justport`, `justip`, `bunt`, `justcommit`, `justzip` |
| Setup | `justready` |
| Shell helpers | `mkcd`, `claude_`, `codex_` (automatic in Windows PowerShell) |
| File Explorer | `just context install` adds a right-click menu on Windows |

Use `<command> --help` for every option. Direct aliases also work as short
dispatch, such as `just optimize`, `just ports`, and `just rmbg`.
Expand All @@ -65,6 +70,29 @@ also creates missing parents. `claude_` runs `claude --dangerously-skip-permissi
and `codex_` runs `codex --yolo`, forwarding additional arguments.
See the [shell helpers guide](docs/mkcd.md).

## Windows right-click menu

`just context install` adds **JustTools** to the File Explorer context menu for
the current user. Right-click a video for JustVideo at 480p, 720p, 1080p,
1440p, or 4K and JustMP3/JustAudio/JustWAV; an image for JustOptimize,
JustResize sizes, WebP/AVIF/JPEG conversion, JustCrop, and JustRMBG; a PDF,
SVG, JSON file, or document for the tools that read it; and a folder or its
background for **JustPaste**, which downloads the copied link into it. Each entry
opens a console showing its **Headless:** command, and sources are kept unless
an entry says "in place". On Windows 11 the top-level menu needs a signed
release package or Developer Mode; otherwise the menu sits under "Show more
options". See the [context menu guide](docs/context-menu.md).

## Media downloads

`justvideo`, `justaudio`, `justmp3`, and `justwav` accept an `http(s)` URL
wherever they accept a file. yt-dlp downloads it to a temporary folder and the
tool converts it with its usual settings into the current folder, or `--output`.
The download is never kept and `--playlist` opts into multi-entry links.
A missing yt-dlp or FFmpeg is downloaded automatically and verified, and
yt-dlp is updated whenever twelve hours have passed. See the
[downloads guide](docs/downloads.md).

## Safe image output

The console shows both the resolved output location and overwrite policy before
Expand Down Expand Up @@ -95,8 +123,9 @@ short, Shorts, live, and embed URLs merge into one clean video link without
timestamps, tracking, or playlist parameters.

For complete behavior, see the [console UI](docs/console-ui.md),
[JustPDF](docs/pdf.md), [JustLinks](docs/links.md), [JustPorts](docs/ports.md), [bunt](docs/bunt.md),
[JustCommit](docs/commit.md), and [JustReady](docs/ready.md) guides.
[context menu](docs/context-menu.md), [JustPaste](docs/paste.md), [JustPDF](docs/pdf.md), [JustLinks](docs/links.md), [JustPorts](docs/ports.md), [JustIP](docs/ip.md),
[bunt](docs/bunt.md), [JustCommit](docs/commit.md), [media downloads](docs/downloads.md), and
[JustReady](docs/ready.md) guides.

## Agent skill

Expand All @@ -120,10 +149,14 @@ cargo build --locked --release -p justtools
./target/release/just install
```

On Windows, add `-p justtools-shell` to build the File Explorer extension that
`just install` copies beside the executable.

Rust 1.90 is the minimum supported toolchain. Version tags build and publish
checksummed archives for all six supported OS/architecture targets through
[`native.yml`](.github/workflows/native.yml). Each archive includes the brief
README, complete guides, screenshots, agent instructions, and installable skill.
README, complete guides, screenshots, agent instructions, and installable skill;
Windows archives also carry the File Explorer extension.

MIT licensed. Third-party notices ship in
[`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md).
4 changes: 3 additions & 1 deletion docs/console-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ The following settings are remembered when changed:

| Tool group | Saved settings |
| --- | --- |
| Image/media tools | Quality, speed/method, sample rate, bitrate, output, parallel jobs, recursion, target re-encoding, source handling |
| Image/media tools | Quality, speed/method, video resolution, sample rate, bitrate, output, parallel jobs, recursion, target re-encoding, source handling |
| `justoptimize` | Web quality, output, replacement, parallel jobs, recursion |
| `justresize` | Maximum/width/height, crop, upscale, JPEG quality, output, replacement, jobs, recursion |
| `justcrop` | Bounds mode, alpha threshold, padding, output, replacement, jobs, recursion |
| `justjson` / `justsvg` | Formatting/optimization choices, output, recursion |
| `justpdf` | Operation, output, page range, rotation, recursion |
| `justlinks` | Text or CSV format, output, recursion, parallel jobs |
| `justip` | Address family, output format, and lookup timeout |
| `justpaste` | Output folder and playlist downloads; links are never saved |
| `justport` | Whether UDP endpoints are included |
| `justqr` | Output, format, size, correction level, margin, colors |
| `justrmbg` | Provider, output, and optional model path; pinned-dependency download permission is visible but one-run |
Expand Down
Loading
Loading