Skip to main content

Turn natural language into shell commands via the DeepSeek API, with a confirm-before-run step.

Project description

nlsh

Describe what you want to do in plain language; nlsh asks the DeepSeek API for the matching shell command, shows it with a short explanation, and waits for your confirmation before running it.

$ nlsh find the 5 largest files under this directory
╭─ proposed command ───────────────────────────────────────╮
│ $ du -ah . | sort -rh | head -n 5                         │
│                                                           │
│ Lists files by size and shows the five largest.          │
╰───────────────────────────────────────────────────────────╯
Run it? [y/n/e] (n):

y runs it, n cancels, e opens the command in your $EDITOR first.

Install

Once published to PyPI, install it as a standalone tool (the package is nlsh-cli; the command it installs is nlsh):

uv tool install nlsh-cli     # or: pipx install nlsh-cli

From source

One command sets up the virtual environment and all dependencies from the lockfile:

uv sync

This creates .venv/ and installs nlsh. Run it with uv run nlsh ..., or activate the env first (source .venv/bin/activate) and just call nlsh.

Plain pip (no uv) works too:

python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
pip install -e .

Configure

Easiest — store the key interactively (written to ~/.config/nlsh/config.toml, mode 0600):

nlsh config set-key
nlsh config set-model deepseek-v4-pro   # optional, change default model
nlsh config show                        # show resolved config (key masked)

Or via environment variable:

export DEEPSEEK_API_KEY=sk-...

or edit ~/.config/nlsh/config.toml directly:

api_key  = "sk-..."
model    = "deepseek-v4-flash"        # optional (also: deepseek-v4-pro)
base_url = "https://api.deepseek.com" # optional

Resolution order for each setting is: environment variable → config file → default.

Usage

nlsh <natural language request>

  -y, --yes        run without confirmation (dangerous commands still prompt)
  -n, --dry-run    only print the command, never run it
      --pro        use the stronger model (deepseek-v4-pro) for this request
  -m, --model ID   override the model id for this request
      --no-stream  wait for the full response instead of streaming it
      --version    show version

The command streams in live as the model generates it (on a terminal); use --no-stream to disable.

config and explain are reserved subcommand names. If your request happens to start with one of them, put -- first to force translate mode:

nlsh -- explain why my disk keeps filling up

At the confirmation prompt: y runs, n cancels, e edits first, c copies the command to the clipboard without running it. Commands that match risky patterns (rm -rf, dd of=/dev/…, mkfs, fork bombs, curl … | sh, sudo, …) are flagged in red and require typing the full word yes before they run — even under --yes. Multi-stage commands (pipes, &&) are shown with a per-step breakdown.

Explain a command (reverse mode)

Paste a command you don't understand and get a stage-by-stage breakdown:

nlsh explain git log --oneline --graph --decorate

Clipboard copy uses an OSC 52 terminal escape by default, so it reaches your local clipboard even over SSH. When there is no terminal it falls back to pbcopy/wl-copy/xclip/xsel/clip.exe.

Development

uv sync                 # installs deps + dev tools (pytest, ruff)
uv run pytest -q        # run the test suite
uv run ruff check .     # lint

CI (GitHub Actions) runs ruff + pytest across Python 3.9–3.13 and checks the lockfile on every push and PR.

Releasing

The version is derived from the git tag by hatch-vcs, so a release is just a tag:

git tag v0.1.0
git push origin v0.1.0

The Publish workflow builds the sdist/wheel and uploads them to PyPI via Trusted Publishing (configure a pypi environment on the repo and register the workflow as a trusted publisher — no API token stored).

How it works

nlsh sends your request plus context (OS, shell, current directory) to the DeepSeek chat API constrained to JSON output, parses {command, explanation}, and runs the chosen command through your $SHELL so aliases and the working directory behave as expected.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nlsh_cli-0.2.1.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nlsh_cli-0.2.1-py3-none-any.whl (15.3 kB view details)

Uploaded Python 3

File details

Details for the file nlsh_cli-0.2.1.tar.gz.

File metadata

  • Download URL: nlsh_cli-0.2.1.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for nlsh_cli-0.2.1.tar.gz
Algorithm Hash digest
SHA256 a97cc538668eb0fd7e87da4db3a1bb3296ea7a24bb5052524f4fd0185d27f5e8
MD5 7f77feb862f426ae45c7ad17fa1677bb
BLAKE2b-256 e9a529e81c6e915159d5004f3afcfdf5a943bd0a7cf45ecaa26b752541671ec0

See more details on using hashes here.

File details

Details for the file nlsh_cli-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: nlsh_cli-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 15.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for nlsh_cli-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b1e2c8ad5a257b96cf338368c196e8f92c5b640d959c2550cdd61fb6b8dbbb7d
MD5 c3686c1e5255433d35fdcf3723d2fa10
BLAKE2b-256 ab0ef0c8f64e2dc87554dbd3cee1f2caaad1268f3d1a4fd35127c7d884d40e16

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page