Skip to content

yoavf/jst

Repository files navigation

jst

Run shell commands from natural-language requests:

jst find all files bigger than 500 mb in ~/downloads

Install

Homebrew

brew install yoavf/tap/jst

Manual

Each GitHub release includes builds for:

  • macOS (signed and notarized universal binary for Apple Silicon and Intel)
  • Linux x86-64
  • Windows x86-64

Download the archive for your platform and put jst (or jst.exe on Windows) somewhere on your PATH. For example, on macOS or Linux:

install -m 755 jst-*/jst ~/.local/bin/jst

For WSL, use the Linux archive and install it inside your WSL distribution. Use the Windows archive when running jst from native Command Prompt or PowerShell.

SHA-256 checksums are published beside every release artifact.

Use

JST prints the generated command and immediately executes it. Commands that match the local destructive-command denylist, or whose model-described effects indicate deletion, privilege use, process changes, software installation, remote changes, or downloaded-code execution, require confirmation.

→ find /Users/me/downloads -type f -size +500M

Use --yolo to skip all safety confirmations:

jst --yolo remove all stopped docker containers

Use --dry to print a generated command and exit without running it:

jst --dry show the current directory

Review and refine

Use -i or --interactive to inspect and refine a command before anything runs:

$ jst -i show me the 10 largest files in this folder

→ du -ah . | sort -hr | head -n 10

Run it?  [y]es  [n]o  [w]hy  [a]sk AI  [e]dit  › w

  du -ah .      measure every entry (“files in this folder”)
  | sort -hr    order sizes largest first (“largest”)
  | head -n 10  keep the first ten results (“show me the 10”)

  Effects: reads local data.

Run it?  [y]es  [n]o  [w]hy  [a]sk AI  [e]dit  › a

✦ What should AI change? files only, not directories

→ find . -type f -exec du -h {} + | sort -hr | head -n 10

Run it?  [y]es  [n]o  [w]hy  [a]sk AI  [e]dit  ›

Each change is translated again with the original request and current command as context, and its effects are recalculated before the revised command is shown. Choose e to edit the current command inline, prefilled with the cursor at the end. Arrow keys, Home, End, Delete, and Backspace work normally. Enter approves the edited command for execution. Manual edits stay entirely local and never call AI. If an edit matches JST's local destructive-command denylist, JST shows the warning and asks again instead of running silently.

Pressing Escape while entering an AI change or editing the command discards that draft and returns to the action menu. Empty input, n, and q abort safely.

Interactive mode asks the model for detailed explanation metadata up front, so choosing w does not require another request. --interactive and --dry cannot be combined with --yolo.

If a server does not support structured explanations, JST falls back to the standalone prose explanation.

Server status

Use --status to check the configured JST server without calling the model:

$ jst --status
Server: ok
Primary model: provider/primary-model
Fallback model: provider/fallback-model
Calls today: 123
Calls all time: 4567

The usage totals are anonymous aggregates and display as unavailable when the server's stats store is disabled or temporarily unreachable.

Server

By default, the CLI sends translation requests to the hosted JST server. The proxy keeps provider credentials out of the distributed binary and lets JST change models, prompts, and provider settings without requiring users to install a new CLI release. The generated command is still checked locally before execution. The complete proxy source lives in crates/server; JST is open source end to end.

The hosted server currently applies these safeguards:

  • 1,000 translations per anonymous installation in a fixed 30-day window.
  • 20 translations per minute per client IP at the Fly proxy.
  • 100 translations per client IP and 5,000 globally per fixed 24-hour window.
  • A 256-request concurrency cap, 512-byte prompts and revision instructions, 8 KiB request bodies, bounded model outputs, and a five-second timeout for each primary or fallback model attempt.
  • Strict OS and shell metadata validation, with provider details hidden from clients and provider outages identified separately from JST server errors.
  • Rate-limit response headers for each active quota.

The CLI creates a random installation ID in its config directory and sends it with translation requests. The server stores only a hash of that ID; older clients fall back to a Fly-provided IP address. When UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are set, quota counters are atomically enforced in the shared Redis store across every server instance. Without Upstash, the server falls back to per-process in-memory counters that reset when the process restarts. This is a best-effort spending brake, not identity: deleting the installation ID bypasses it.

You do not have to use the hosted proxy. The bundled server works with any OpenAI-compatible chat-completions API. For example, using OpenRouter:

LLM_API_URL=https://openrouter.ai/api/v1/chat/completions \
LLM_API_KEY=... \
LLM_MODEL=google/gemma-4-26b-a4b-it \
LLM_FALLBACK_MODEL=microsoft/phi-4 \
cargo run --release -p jst-server

Then point the CLI at it:

JST_API_URL=http://127.0.0.1:8080/translate jst find large files

jst --status derives the sibling /status endpoint from JST_API_URL. Set JST_STATUS_URL when a custom deployment exposes status at a different URL.

The server listens on PORT (default 8080). MAX_CONCURRENT_TRANSLATIONS optionally limits simultaneous provider calls. MONTHLY_REQUEST_LIMIT controls the 30-day quota; set it to 0 to disable anonymous usage tracking on your own server. REQUESTS_PER_MINUTE, DAILY_REQUESTS_PER_IP, and GLOBAL_DAILY_REQUEST_LIMIT control the short-term, daily client-IP, and global daily limits. Each accepts 0 to disable it. The bundled implementation trusts Fly's Fly-Client-IP header; self-hosters should only enable IP limits behind a proxy that overwrites that header rather than accepting it from clients. Configure UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN to share both rate-limit counters and aggregate usage statistics across server instances. LLM_API_KEY is optional for local APIs that do not require authentication. LLM_FALLBACK_MODEL optionally selects a model to try when LLM_MODEL fails. Alternatively, JST_API_URL can point directly to any service implementing JST's /translate JSON contract.

Development

GitHub Actions runs formatting, build, tests, and Clippy on every pull request and push to main.

cargo test --workspace
cargo build --workspace

The reusable model benchmark compares command generation, effect classification, parse reliability, and latency directly against an OpenAI-compatible provider without touching hosted JST usage statistics.

About

jst — shell commands from plain English

Topics

Resources

Stars

Watchers

Forks

Releases

Contributors

Languages