diff --git a/plugins/deepseek/README.md b/plugins/deepseek/README.md new file mode 100644 index 000000000..f86783231 --- /dev/null +++ b/plugins/deepseek/README.md @@ -0,0 +1,60 @@ +# deepseek + +This plugin adds the `ds` command, which turns natural language queries into +shell commands using the DeepSeek API. The generated command is echoed to the +terminal, pushed onto the next prompt line (ready to execute or edit), and +copied to the system clipboard. + +To use it, add `deepseek` to the plugins array in your `.zshrc` file: + +```zsh +plugins=(... deepseek) +``` + +## Requirements + +- [curl](https://curl.se/) +- [jq](https://jqlang.github.io/jq/) +- A [DeepSeek API key](https://platform.deepseek.com/api_keys) + +## Configuration + +Set your API key as an environment variable (e.g. in `.zshrc` or `.zprofile`): + +```zsh +export DEEPSEEK_API_KEY="sk-..." +``` + +## Usage + +```zsh +# Ask for a command in plain English (or any language) +ds find the 10 largest files in the current directory + +# The output looks like: +# find . -type f -exec du -h {} + | sort -rh | head -10 +# $ █ +# +# The command is: +# 1. Printed to the terminal for review +# 2. Copied to the system clipboard +# 3. Pre-filled on the next prompt line — press Enter to run it, +# or edit it first +``` + +The system prompt instructs the model to respond with **only** the shell command +or code — no explanations, no markdown formatting. + +## Commands + +| Command | Description | +| ------- | ---------------------------------------- | +| `ds` | Query DeepSeek for a shell command | + +## Cross-platform clipboard + +| Platform | Clipboard tool | +| ------------- | ----------------------- | +| macOS | `pbcopy` | +| Linux (X11) | `xclip` | +| Linux (Wayland)| `wl-copy` | diff --git a/plugins/deepseek/deepseek.plugin.zsh b/plugins/deepseek/deepseek.plugin.zsh new file mode 100644 index 000000000..046a34832 --- /dev/null +++ b/plugins/deepseek/deepseek.plugin.zsh @@ -0,0 +1,83 @@ +function ds() { + # Preflight checks + (( $+commands[curl] )) || { + echo "ds: curl must be installed." >&2 + return 1 + } + (( $+commands[jq] )) || { + echo "ds: jq must be installed." >&2 + return 1 + } + [[ -n "$DEEPSEEK_API_KEY" ]] || { + echo "ds: DEEPSEEK_API_KEY is not set." >&2 + return 1 + } + (( $# )) || { + echo "Usage: ds " >&2 + return 1 + } + + # System prompt + local sys_prompt="You're an in-line zsh assistant running on ${OSTYPE}. \ +Your task is to answer the questions without any commentation at all, \ +providing only the code to run in terminal. \ +You can assume that the user understands that they need to fill in placeholders like . \ +You're not allowed to explain anything and you're not a chatbot. \ +You only provide shell commands or code. \ +Keep the responses to one-liner answers as much as possible. \ +Do not decorate the answer with tickmarks." + + # Build JSON payload safely with jq + local payload + payload=$(command jq -n \ + --arg system "$sys_prompt" \ + --arg user "$*" \ + '{ + model: "deepseek-v4-flash", + messages: [ + {role: "system", content: $system}, + {role: "user", content: $user} + ], + stream: false + }') || { + echo "ds: failed to build JSON payload." >&2 + return 1 + } + + # Call DeepSeek API + local response + response=$(command curl https://api.deepseek.com/chat/completions -s \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \ + -d "$payload" 2>&1) || { + echo "ds: API request failed (network error)." >&2 + return 1 + } + + # Extract result + local result + result=$(command jq -r '.choices[0].message.content // empty' <<< "$response" 2>/dev/null) + + if [[ -z "$result" ]]; then + local err_msg + err_msg=$(command jq -r '.error.message // "unknown error"' <<< "$response" 2>/dev/null) + echo "ds: ${err_msg}" >&2 + return 1 + fi + + # Copy to system clipboard (cross-platform) + if [[ "$OSTYPE" == darwin* ]]; then + print -r -- "$result" | command pbcopy + elif command -v wl-copy &>/dev/null; then + print -r -- "$result" | command wl-copy + elif command -v xclip &>/dev/null; then + print -r -- "$result" | command xclip -selection clipboard + fi + + # Echo result to terminal for visibility + echo "$result" + + # Push into ZLE buffer so it sits on the next prompt line + # User can edit it or press Enter to execute immediately. + print -z "$result" +}