From e9232db8bc0c8992589a3e048fa7375ec6afb3ae Mon Sep 17 00:00:00 2001 From: sandofree Date: Mon, 11 May 2026 12:18:38 +0800 Subject: [PATCH 1/2] deepseek plugin to help user write shell command --- plugins/deepseek/README.md | 60 +++++++++++++++++++++ plugins/deepseek/deepseek.plugin.zsh | 80 ++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 plugins/deepseek/README.md create mode 100644 plugins/deepseek/deepseek.plugin.zsh 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..1a0c0a844 --- /dev/null +++ b/plugins/deepseek/deepseek.plugin.zsh @@ -0,0 +1,80 @@ +#!/bin/zsh + +ds() { + # --- preflight checks --- + if [[ ! $+commands[curl] ]]; then + echo "ds: curl must be installed." >&2 + return 1 + fi + if [[ ! $+commands[jq] ]]; then + echo "ds: jq must be installed." >&2 + return 1 + fi + if [[ -z "$DEEPSEEK_API_KEY" ]]; then + echo "ds: DEEPSEEK_API_KEY is not set." >&2 + return 1 + fi + if [[ $# -eq 0 ]]; then + echo "ds: usage — ds " >&2 + return 1 + fi + + # --- 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=$(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=$(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=$(jq -r '.choices[0].message.content // empty' <<< "$response" 2>/dev/null) + + if [[ -z "$result" ]]; then + local err_msg + err_msg=$(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" | pbcopy + elif command -v wl-copy &>/dev/null; then + print -r -- "$result" | wl-copy + elif command -v xclip &>/dev/null; then + print -r -- "$result" | 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" +} + From 13bcaf81db9fda1f45d19dfde195737dd4bedadb Mon Sep 17 00:00:00 2001 From: sandofree Date: Mon, 11 May 2026 13:35:49 +0800 Subject: [PATCH 2/2] code style --- plugins/deepseek/deepseek.plugin.zsh | 65 +++++++++++++++------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/plugins/deepseek/deepseek.plugin.zsh b/plugins/deepseek/deepseek.plugin.zsh index 1a0c0a844..046a34832 100644 --- a/plugins/deepseek/deepseek.plugin.zsh +++ b/plugins/deepseek/deepseek.plugin.zsh @@ -1,31 +1,35 @@ -#!/bin/zsh - -ds() { - # --- preflight checks --- - if [[ ! $+commands[curl] ]]; then +function ds() { + # Preflight checks + (( $+commands[curl] )) || { echo "ds: curl must be installed." >&2 return 1 - fi - if [[ ! $+commands[jq] ]]; then + } + (( $+commands[jq] )) || { echo "ds: jq must be installed." >&2 return 1 - fi - if [[ -z "$DEEPSEEK_API_KEY" ]]; then + } + [[ -n "$DEEPSEEK_API_KEY" ]] || { echo "ds: DEEPSEEK_API_KEY is not set." >&2 return 1 - fi - if [[ $# -eq 0 ]]; then - echo "ds: usage — ds " >&2 + } + (( $# )) || { + echo "Usage: ds " >&2 return 1 - fi + } - # --- 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." + # 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 --- + # Build JSON payload safely with jq local payload - payload=$(jq -n \ + payload=$(command jq -n \ --arg system "$sys_prompt" \ --arg user "$*" \ '{ @@ -40,9 +44,9 @@ You only provide shell commands or code. Keep the responses to one-liner answers return 1 } - # --- call DeepSeek API --- + # Call DeepSeek API local response - response=$(curl https://api.deepseek.com/chat/completions -s \ + 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) || { @@ -50,31 +54,30 @@ You only provide shell commands or code. Keep the responses to one-liner answers return 1 } - # --- extract result --- + # Extract result local result - result=$(jq -r '.choices[0].message.content // empty' <<< "$response" 2>/dev/null) + result=$(command jq -r '.choices[0].message.content // empty' <<< "$response" 2>/dev/null) if [[ -z "$result" ]]; then local err_msg - err_msg=$(jq -r '.error.message // "unknown error"' <<< "$response" 2>/dev/null) + 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) --- + # Copy to system clipboard (cross-platform) if [[ "$OSTYPE" == darwin* ]]; then - print -r -- "$result" | pbcopy + print -r -- "$result" | command pbcopy elif command -v wl-copy &>/dev/null; then - print -r -- "$result" | wl-copy + print -r -- "$result" | command wl-copy elif command -v xclip &>/dev/null; then - print -r -- "$result" | xclip -selection clipboard + print -r -- "$result" | command xclip -selection clipboard fi - # --- echo result to terminal for visibility --- + # 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. + # 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" } -