快速、无状态的LLM命令行工具开源,直接提升开发者终端工作效率。
快速、无状态的基于 LLM 的 shell 助手:qq 回答问题;qa 运行命令
qqqa 是一个二合一的无状态 CLI 工具,为命令行带来 LLM 辅助,无需复杂设置。
两个二进制文件为:
qq - 提问单个问题,例如 "qq how can I recursively list all files in this directory"(qq 代表"quick question")
qa - 一个单步 AI 智能体,可选择使用工具完成任务:读取文件、写入文件或执行命令(需要确认)(qa 代表"quick agent")
qqqa 运行在 macOS、Linux 和 Windows 上。
默认情况下,该 repo 包含 OpenRouter(默认)、OpenAI、Groq、Gemini(API + CLI)、本地 Ollama 运行时、Codex CLI(搭载 ChatGPT)和 Claude Code CLI(复用你的 Claude 订阅)的 profiles。配置中存在 Anthropic profile stub 供未来扩展,但目前尚未启用。
qq 代表快速提问。qa 代表快速智能体。两者都易于在 QWERTY 键盘上快速输入,手指移动最少。这使得在实际工作中与 LLM 交互更快更自然。
qqqa 故意设计为无状态的。没有长时间运行的会话,工具也不存储隐藏的对话历史。每次运行基本独立且可重复。为了保持低调的连贯性,你可以在 config.json 中使用 "include_history": true(或在 qq --init 过程中选择使用历史记录)。
简单高效 - 应用 Unix 哲学到 LLM 工具。
Shell 友好 - 通过管道和文件组合,而不是交互式聊天。
默认安全 - qq 是只读的,没有工具访问权限。qa 以安全为核心设计,运行工具前需要确认。
工具可能包含你选择提供的临时上下文:
qq 可以将最后几个终端命令作为提示包含,如果存在管道输入也会包含。
qa 可以读取文件或运行特定命令,但每次调用只能一次,并进行安全检查。
OpenRouter 镜像 OpenAI Chat Completions API,提供丰富的社区托管模型,并保持 openai/gpt-4.1-nano 快速且廉价。qqqa 开箱即用地与 https://openrouter.ai/api/v1 通信,并从 OPENROUTER_API_KEY 读取 API 密钥,所以只要填入密钥,首次运行即可开始。
如果你需要更高的吞吐量,捆绑的 groq profile(针对 openai/gpt-oss-20b 和 openai/gpt-oss-120b)仍然可用,你也可以通过编辑 ~/.qq/config.json 或创建新 profile 来添加任何 OpenAI 兼容的提供商。
已经订阅 ChatGPT?选择 codex profile(在 qq --init 过程中、通过 qq --profile codex 或编辑 ~/.qq/config.json),qqqa 将调用 Codex CLI 而不是 HTTP 端点。这让你可以复用现有的 ChatGPT 订阅,边际成本几乎为零。
通过 ChatGPT 桌面应用(Settings → Labs → Codex)或 pip install codex-cli 安装 Codex CLI,然后确保 codex 在你的 PATH 中。
流式传输不可用;即使不使用 --no-stream,qqqa 也会缓冲 Codex 响应并一次性打印。
qa 仍然期望 JSON 工具调用。当你需要 read_file、write_file 或 execute_command 时,以与 OpenRouter 相同的方式使用 { "tool": string, "arguments": object } 响应。
如果二进制文件缺失或以错误退出,qqqa 会输出 stderr/stdout,以便你快速修复环境。
将 Codex 设为默认 profile 的 ~/.qq/config.json 示例片段:
{
"default_profile": "codex",
"profiles": {
"codex": {
"model_provider": "codex",
"model": "gpt-5",
"reasoning_effort": "low"
}
}
}
有 Claude 订阅?选择 claude_cli profile,qqqa 将使用 claude 二进制文件。如果你已经订阅 Claude for Desktop,这可以让使用成本实际上为零。
安装 Claude Code 使 claude 二进制文件在你的 PATH 中,然后运行一次 claude login。
Claude Code 以与基于 API 的 LLM 相同的方式流式传输响应。
需要指定不同的 Claude 桌面模型?在 ~/.qq/config.json 的 model_providers.claude_cli.cli 下添加 "model_override": "claude-haiku-4-5"。该 override 仅适用于 Claude CLI;qq -m/--model 在每次运行时仍有优先权。
最小配置片段:
{
"default_profile": "claude_cli",
"profiles": {
"claude_cli": {
"model_provider": "claude_cli",
"model": "claude-haiku-4-5"
}
},
"model_providers": {
"claude_cli": {
"cli": {
"model_override": "claude-haiku-4-5"
}
}
}
}
支持流式和非流式调用的 OpenAI 兼容 API 客户端。
无状态的一次性工作流,与管道和脚本配合良好。
使用 XML 标签进行丰富但简单的格式化,呈现为 ANSI 颜色。
配置驱动的提供商和 profiles,支持每个 profile 的模型 override。
文件访问和命令执行的护栏。
传统且严肃?可选的无表情符号模式通过 --no-fun 持久化 🥸
brew install qqqa
从 GitHub Releases 页面下载预构建的存档,解压它,并将 qq/qa 放在你的 PATH 中的某处(例如 /usr/local/bin)。
在 Arch Linux 上,/usr/bin/qq 可能已属于另一个包。将发布的二进制文件安装到自定义目录(例如 ~/bin)并根据需要重命名它们,或使用此 repo 的 cargo install。
从 Releases 下载 Windows 存档(选择与你的机器匹配的架构),解压 qq.exe 和 qa.exe,并将它们添加到你的 %PATH%。
首次运行时,qqqa 会创建一个具有安全权限的配置文件。默认路径是 ~/.qq/config.json。如果设置了 XDG_CONFIG_HOME 且不存在旧的 ~/.qq/config.json,配置改为存储在 $XDG_CONFIG_HOME/qq/config.json。
为了顺利的首次交互,运行初始化流程:
# Interactive setup (choose provider and set key)
qq --init
# or
qa --init
如果 ~/.qq/config.json 已存在,init 命令会保持它不变并说明如何在移动或删除文件后重新运行。
初始化工具让你选择默认提供商:
OpenRouter + openai/gpt-4.1-nano(默认,快速且廉价)
Groq + openai/gpt-oss-20b(更快,便宜的付费级)
OpenAI + gpt-5-mini(较慢,稍微智能一些)
Anthropic + claude-3-5-sonnet-20241022(占位符,直到他们的 Messages API 最终确定)
Ollama(本地运行,如需要调整端口)
Codex CLI + gpt-5(包装 codex exec 二进制文件,以便复用 ChatGPT 订阅;无需 API 密钥,仅缓冲输出)
Claude Code CLI + claude-haiku-4-5(包装 claude 二进制文件;qq 实时流式传输,qa 缓冲以便解析工具调用)
需要强制指定不同的桌面模型?在提供商的 cli 块下添加 "model_override"(Codex 和 Claude 都支持)。该 override 优先于 profile 默认值,但仍会让步于每次运行的 --model flag。
Gemini + gemini-3-flash-preview(Google 的 Gemini 通过 OpenAI 兼容 API)
Gemini CLI + gemini-3-flash-preview(包装 gemini 二进制文件;登录一次或设置 GEMINI_API_KEY;仅缓冲输出)
它还提供在配置中存储 API 密钥的选项(可选)。如果你偏好环境变量,留空并设置以下之一:
OPENROUTER_API_KEY - 用于 OpenRouter(默认)
GROQ_API_KEY - 用于 Groq
OPENAI_API_KEY - 用于 OpenAI
GEMINI_API_KEY - 用于 Gemini(Google AI Studio)
OLLAMA_API_KEY(可选;任何非空字符串都有效——甚至本地——因为 Authorization header 不能为空)
Codex 或 Claude CLI profiles 无需 API 密钥——它们的二进制文件处理认证(codex login / claude login)。Gemini CLI 接受 Google 登录或 GEMINI_API_KEY。
写入 ~/.qq/config.json 的默认值:
openrouter → 基础 URL https://openrouter.ai/api/v1,环境变量 OPENROUTER_API_KEY,默认请求头 HTTP-Referer=https://github.com/iagooar/qqqa 和 X-Title=qqqa
openai → 基础 URL https://api.openai.com/v1,环境变量 OPENAI_API_KEY
groq → 基础 URL https://api.groq.com/openai/v1,环境变量 GROQ_API_KEY
ollama → 基础 URL http://127.0.0.1:11434/v1,环境变量 OLLAMA_API_KEY(如果未设置,qqqa 会自动注入一个非空占位符)
anthropic → 基础 URL https://api.anthropic.com/v1,环境变量 ANTHROPIC_API_KEY(已在配置架构中声明,暂未支持)
gemini → 基础 URL https://generativelanguage.googleapis.com/v1beta/openai,环境变量 GEMINI_API_KEY
gemini_cli → 模式 cli,二进制命令 gemini(需安装 @google/gemini-cli;通过 Google 登录或 GEMINI_API_KEY 认证)
codex → 模式 cli,二进制命令 codex,基础参数为 exec(需安装 Codex CLI;认证由 codex login 处理)。cli 块中的可选 "model_override" 在 OpenAI 弃用默认模型时强制回退到 ChatGPT 模型。
claude_cli → 模式 cli,二进制命令 claude(需安装 @anthropic-ai/claude-code;认证由 claude login 处理)。可选的 "model_override" 固定 Claude Code 的 --model 标志,不影响你的配置文件模型设置。
openrouter → 模型 openai/gpt-4.1-nano(默认)
openai → 模型 gpt-5-mini
groq → 模型 openai/gpt-oss-20b
ollama → 模型 llama3.1
anthropic → 模型 claude-3-5-sonnet-20241022(不活跃的占位符,待 Anthropic 集成完成)
gemini → 模型 gemini-3-flash-preview
gemini_cli → 模型 gemini-3-flash-preview(传递给 gemini -m)
codex → 模型标签 gpt-5(仅用于显示;Codex CLI 选择底层的 ChatGPT 模型)
可选的 per-profile(按配置文件)或全局 prompt_suffix 文本会追加到内置系统提示(不会替换它)。适用于"假设工具已安装"或"更简洁的回复"这类规则。
可选的 per-profile reasoning_effort 用于 GPT-5 系列模型。如果不设置,qqqa 会为任何 gpt-5* 模型发送 "reasoning_effort": "minimal" 以保持快速响应。设置为 "low"、"medium" 或 "high" 来获取更深层推理。
(不推荐)可选的 per-profile temperature。大多数模型默认为 0.15,除非你在 ~/.qq/config.json 中设置或为单次运行通过 --temperature <value> 指定。GPT-5 模型忽略自定义温度;qqqa 强制它们为 1.0。
(不推荐)你可以修改超时时间,例如在 ~/.qq/config.json 中的模型配置下添加 "timeout": "240" 来提高单次请求的限制(qq 和 qa 默认为 180 秒 - 这很慢;更快的模型是更好的解决方案)。
~/.qq/config.json 中的覆盖示例:
{
"profiles": {
"openai": {
"model_provider": "openai",
"model": "gpt-5-mini",
"reasoning_effort": "medium"
}
}
}
可选标志:no_emoji(默认未设置)。通过 qq --no-fun 或 qa --no-fun 设置。
可选的自动复制:copy_first_command(默认未设置/false)。在 qq --init 期间启用,运行 qq --enable-auto-copy,或编辑 ~/.qq/config.json 让 qq 复制第一个 <cmd> 块到剪贴板。用 qq --disable-auto-copy 关闭。按运行覆盖 --copy-command/--cc 或 --no-copy-command/--ncc(也可用 -ncc)。
逐次运行控制:--no-stream 强制 qq 等待完整响应再打印;流式输出是默认行为。
终端历史默认关闭。在 qq --init / qa --init 期间你可以选择在每次请求中发送最后 10 条 qq/qa 命令。你仍可按运行覆盖 --history(强制开启)或 -n/--no-history(强制关闭)。只有首个 token 是 qq 或 qa 的命令才会被共享。
qq 默认流式输出响应,所以你能在 token 到达时立即看到。如果你倾向于经典的缓冲输出 —— 例如管道输入其他工具或一次性复制最终答案 —— 传递 --no-stream 来等待响应完成后再打印任何内容。
# 最简单的用法
qq "convert mp4 to mp3"
# 默认流式输出(格式化输出)
qq "how do I kill a process by name on macOS"
# 禁用流式输出,等待完整格式化响应
qq --no-stream "summarize today's git status"
# 为非 GPT-5 模型在单次运行中提高温度
qq --temperature 0.4 "draft a playful git commit message"
# 包含管道上下文
git status | qq "summarize what I should do next"
# 管道额外上下文并保留 CLI 问题
printf '%s\n' "This is a sample context. My code is 4242" | qq "What is my code"
# 管道问题本身
printf '%s\n' "Show me the full contents of this directory" | qq
# 原始文本(无 ANSI 格式化)
qq -r "explain sed vs awk"
# 本次运行包含终端历史
qq --history "find large files in the last day"
# 从响应中禁用表情符号(持久化)
qq --no-fun "summarize this"
# 自动复制第一个 `<cmd>` 块以快速粘贴(别名:--cc)
qq --copy-command "list docker images"
# 即使配置中已启用,也暂时禁用自动复制(别名:--ncc / -ncc)
qq --no-copy-command "print working directory"
# 为所有未来 qq 运行启用自动复制
qq --enable-auto-copy
# 持久化禁用自动复制
qq --disable-auto-copy
注意:可以不加引号运行 qq,大多数情况下效果与加引号相同。
# 最简单的用法
qq convert mp4 to mp3
你想从 YouTube 视频中提取音频,但不记得确切的标志。
qq "how do I use ffmpeg to extract audio from a YouTube video into mp3"
典型的回答会建议安装工具,然后使用 yt-dlp 获取音频,ffmpeg 转换为 mp3:
# macOS
brew install yt-dlp ffmpeg
# Debian 或 Ubuntu
sudo apt-get update && sudo apt-get install -y yt-dlp ffmpeg
# 使用 ffmpeg 从 YouTube 下载并提取音频到 MP3
yt-dlp -x --audio-format mp3 "https://www.youtube.com/watch?v=VIDEO_ID"
用 qa 为你执行:
qa "download audio as mp3 from https://www.youtube.com/watch?v=VIDEO_ID"
智能体会提议一个安全命令如 yt-dlp -x --audio-format mp3 URL,显示确认,然后运行它。你可以传递 -y 自动批准。
qa 可以用纯文本回答或请求一个 JSON 工具调用。支持的工具:
read_file,参数 { "path": string }
write_file,参数 { "path": string, "content": string }
execute_command,参数 { "command": string, "cwd?": string }
# 安全地读取文件
qa "read src/bin/qq.rs and tell me what main does"
# 写文件
qa "create a README snippet at notes/intro.md with a short summary"
# 通过确认运行命令
qa "list Rust files under src sorted by size"
# 管道任务本身
printf '%s\n' "Show me the full contents of this directory" | qa
# 为非交互脚本自动批准工具执行
qa -y "count lines across *.rs"
# 仅为本次运行包含最近的 qq/qa 命令
qa --history "trace which git commands I ran recently"
# 为本次运行提高温度(仅非 GPT-5 模型)
qa --temperature 0.3 "brainstorm fun git aliases"
# 从响应中禁用表情符号(持久化)
qa --no-fun "format and lint the repo"
# 非交互模式运行 qa,确认已授予
qa -y "count lines across *.rs"
当 qa 在 stdout 是终端的情况下运行命令时,输出实时流式传输;结构化的 [tool:execute_command] 摘要仍在之后打印,以便轻松复制。
execute_command 会打印拟执行的命令并请求确认。如果工作目录位于你的主目录之外,它会发出警告。在可信的工作流中,可使用 -y 自动批准。
运行器会强制执行默认的允许列表(例如 ls、grep、find、rg、awk 等),并拒绝管道、重定向及其他高风险结构。当命令被阻止时,qa 会提示你将其添加到 ~/.qq/config.json 中的 command_allowlist;批准一次后,该选择会被持久化,并应用于后续运行。在 Windows 上,它会自动适配当前活动环境,因此 dir 或 Get-ChildItem 等内置命令无需额外参数即可正常工作。
一些兼容 OpenAI 的网关(LiteLLM、本地企业代理等)会使用自签名 CA 终止 TLS。为相应提供商添加独立的 tls 配置块,使 qqqa 在信任默认 Rustls 证书包的同时,也信任该 CA:
{
"model_providers": {
"litellm": {
"name": "LiteLLM",
"base_url": "https://proxy.local/v1",
"env_key": "LITELLM_API_KEY",
"tls": {
"ca_bundle_path": "certs/litellm-ca.pem",
"ca_bundle_env": "SSL_CERTFILE_PATH"
}
}
}
}
ca_bundle_path 接受 PEM 或 DER 文件。相对路径会基于 ~/.qq/ 解析,因此你可以将证书与配置文件放在一起。
ca_bundle_env 是可选项;如果设置,qqqa 会从该环境变量中读取证书包路径,并在该变量未设置时回退到 ca_bundle_path。这与公开 SSL_CERTFILE_PATH 或类似配置项的代理保持一致。
同一文件中可以包含多个证书(将多个 PEM 条目拼接起来即可)。qqqa 会将它们追加到现有的 Rustls 信任存储中,因此标准公共 CA 仍可继续使用。
通过此配置,任何提供商——LiteLLM、通过 HTTPS 访问的 Ollama、你所在公司的网关或其他代理——都能使用其自定义 CA 完成身份验证,而无需禁用 TLS 验证。
选择内置的 ollama 配置(或创建自己的配置)以连接本地运行时。当服务暴露在不同的主机或端口上时,可以覆盖 API 基础地址:
qq --profile ollama --api-base http://127.0.0.1:11435/v1 "summarize build failures"
qa --profile ollama --api-base http://192.168.1.50:9000/v1 "apply the diff" -y
qa --init 会将 Ollama 作为一个选项提供,并跳过 API 密钥警告;qqqa 仍会发送一个占位的 Bearer Token,以确保兼容 OpenAI 的中间件能够继续工作。如果你跳过初始化流程并手动编辑 config.json,请在 ollama 提供商配置下设置 "api_key": "local",或导出 OLLAMA_API_KEY=local,以确保 Authorization 请求头不为空。
本地配置示例:在配备 M4/32 GB 的 MacBook Air 上,通过 macOS 版 LM Studio 驱动 ollama run meta-llama-3.1-8b-instruct-hf (Q4_K_M) 可以正常工作,只是速度比托管的 OpenRouter/Groq 配置更慢。请相应调整 ollama 配置中的模型标签。
你仍然可以在运行时覆盖配置:
# choose profile
qq -p groq "what is ripgrep"
# override model for a single call
qq -m openai/gpt-oss-20b "explain this awk one-liner"
文件工具要求路径位于你的主目录或当前目录内。读取大小上限为 1 MiB,并会阻止通过目录遍历或符号链接逃逸。
命令执行采用默认允许列表(例如 ls、grep、rg、find)以及你自定义的 command_allowlist 条目。破坏性模式(rm -rf /、sudo、mkfs 等)始终会被阻止;即使使用 --yes,包含管道、重定向或换行符的命令仍会要求确认。
命令执行的超时时间为 120 秒,并且智能体最多只执行一个工具步骤——不存在循环。
配置文件会以安全权限创建。除非你明确将密钥添加到配置中,否则 API 密钥均来自环境变量。
OPENROUTER_API_KEY:用于 OpenRouter 提供商(默认)
GROQ_API_KEY:用于 Groq 提供商
OPENAI_API_KEY:用于 OpenAI 提供商
src/bin/qq.rs 和 src/bin/qa.rs:入口点
src/ 中的核心模块:ai.rs、config.rs、prompt.rs、history.rs、perms.rs、formatting.rs
src/tools/ 中的工具:read_file.rs、write_file.rs、execute_command.rs
tests/ 中的集成测试
有关报告问题、发起拉取请求、从源代码构建以及发布流程的指南,请参阅 CONTRIBUTING.md。
提示缺少密钥的 API 错误:运行 qq --init 完成设置,或导出相关的环境变量,例如 export OPENROUTER_API_KEY=....。
流式传输期间没有输出:尝试使用 -d 查看调试日志,或使用 --no-stream 重新运行以回退到缓冲输出(在某些边缘场景下,这种方式可能效果更好)。
未检测到管道输入:请确保你将输入通过管道传给 qq,而不是在会吞掉标准输入的子 Shell 中运行它。