Metadata-Version: 2.5
Name: lex-the-hacker
Version: 0.1.0
Summary: An AI CLI that writes shell commands for you — and never runs them.
Requires-Python: >=3.13
Requires-Dist: click>=8.5.0
Requires-Dist: pydantic-ai-slim[openai]>=2.35.0
Requires-Dist: pyperclip>=1.11.0
Requires-Dist: questionary>=2.1.1
Requires-Dist: rich>=15.0.0
Requires-Dist: shellingham>=1.5.4
Description-Content-Type: text/markdown

# lex the hacker

> *I prefer to be called a hacker.*

![It's a UNIX system! I know this!](docs/images/lex.jpeg)

Describe what you want in plain English, and `lex` writes the shell command for you.

```
$ lex "search the dir for 'xyz'"
```

```
$ grep -rn 'xyz' .
```

While `lex` thinks, you get a spinner. Then it shows the command with a short
explanation of how it works, and offers it to you — pick it (just press Enter)
to copy it to your clipboard:

```
╭──────────────────────────────────────────────────╮
│ grep -rn 'xyz' .                                 │
│                                                  │
│ Searches every file under the current directory  │
│ for the text "xyz", printing each match with its │
│ file name and line number.                       │
╰──────────────────────────────────────────────────╯
? copy to clipboard? (Use arrow keys)
 » grep -rn 'xyz' .
   skip

✓ copied to clipboard
```

Either way, the command also lands on your command line, ready to run.

It **never executes anything itself**. You always read the command and press
Enter (or edit it, or throw it away). Nothing runs without you.

> **On typing.** Putting text on your prompt uses the `TIOCSTI` ioctl, which
> current Linux kernels disable by default (`dev.tty.legacy_tiocsti = 0`)
> because it was a privilege-escalation vector. When it's unavailable — a
> hardened kernel, no terminal, a pipe — or when the command spans more than
> one line, the command simply doesn't land on your prompt. That's a normal
> outcome, not an error: it's still right there in the panel, and on your
> clipboard. Either way, `lex` never presses Enter for you.

## Install

```
pip install lex-the-hacker
```

This gives you the `lex` command.

## Configuration

`lex` talks to any OpenAI-compatible chat API — hosted OpenAI, or a local
[Ollama](https://ollama.com) server. Point it at one with three environment
variables:

| Variable | Required | What it is |
| --- | --- | --- |
| `LEX_MODEL` | yes | The model name to request, e.g. `gpt-4o-mini` or `llama3.1`. |
| `LEX_API_KEY` | yes | The API key. Ollama ignores it, but the client still requires a non-empty value — `ollama` works fine. |
| `LEX_BASE_URL` | no | Base URL of the endpoint. Defaults to OpenAI's hosted API. |

Hosted OpenAI:

```
export LEX_MODEL=gpt-4o-mini
export LEX_API_KEY=sk-...
```

A local Ollama server:

```
export LEX_MODEL=llama3.1
export LEX_API_KEY=ollama
export LEX_BASE_URL=http://localhost:11434/v1
```

`lex` also tells the model which shell you're in, so the command it writes
matches your shell's syntax. Run `lex shell` to see what it detected.

> **Clipboard on Linux.** Copying first tries your system clipboard via
> [pyperclip](https://pypi.org/project/pyperclip/), which on Linux needs one of
> `xclip`, `xsel`, or `wl-clipboard` installed. Without one, `lex` falls back
> to OSC 52 — asking your terminal itself to set the clipboard, no install
> needed — which modern terminals
> (VS Code, kitty, alacritty, WezTerm, iTerm2, foot, …) support, even over
> SSH. If neither route works, the copy is skipped quietly.

## Usage

Call `lex` with a description of what you want to do, in quotes:

```
$ lex "find every python file changed in the last week"
```

`lex` puts its best guess on your prompt:

```
$ find . -name '*.py' -mtime -7
```

From there it's your command like any other — run it, tweak it, or clear the line and try a different description.

More examples:

```
$ lex "undo my last git commit but keep the changes"
$ git reset --soft HEAD~1

$ lex "compress this folder into a tar.gz"
$ tar -czf folder.tar.gz folder/

$ lex "show what's listening on port 8080"
$ lsof -i :8080
```

## Why you're always safe

`lex` only ever *writes* a command to your shell. It doesn't run it, and it can't run it — executing is up to you. So if a suggestion looks wrong, you'll see it before anything happens.
