Use AI to quickly find commands within the terminal.
English | 简体中文
Features • Install • Usage • Configuration • Development • Troubleshooting
howto is a TypeScript CLI that turns a natural-language question into up to three executable command candidates. It never runs AI output directly: you choose a command in the terminal, fill any placeholders, review the final command, and confirm before execution.
Important
howto is an assistant for generating shell commands, not a sandbox. Review every command before running it, especially commands that modify files, install packages, change permissions, or use elevated privileges.
- Natural language to commands - ask for a task and get concise shell command candidates.
- Tool-constrained mode - use
howto use <command>to require candidates around a specific CLI tool. - Interactive review flow - select a candidate, resolve placeholders, and confirm the final command before execution.
- Non-interactive print mode - use
--printto output candidates without TTY interaction or command execution. - OpenAI and Gemini support - configure either provider from CLI flags, environment variables, or
~/.howto/config.json. - Local validation first - AI JSON output, placeholder references,
use <command>candidates, and obvious dangerous commands are checked locally.
Install the CLI package globally:
npm install -g @unscientificjszhai/howtoOr run it from a cloned repository:
npm install
npm run build
npm linkYou can then call the executable as howto.
Initialize your AI provider configuration:
howto --initThe initializer writes a user-level config file at ~/.howto/config.json.
Note
OpenAI API keys may be empty for local OpenAI-compatible services. Gemini requires a non-empty API key.
Ask for a command:
howto "find files modified in the last 7 days" .Limit candidates to a specific tool:
howto use git "show commits from last week"Print command candidates without entering the interactive UI:
howto --print "list the largest files" /var/loghowto [options] [use <command>] <question> [<argument>...]
howto --init
Examples:
howto "find package.json under the current directory"
howto use find "find a filename" package.json
howto "explain this option" -- --force
howto --ai-provider openai --print "show listening ports"Options:
--init- start interactive provider setup and save~/.howto/config.json.--print- print validated command candidates and exit without executing.--ai-provider <openai|gemini>- select the AI provider.--gemini-api-key <key>- provide a Gemini API key.--gemini-model <model>- override the Gemini model.--openai-api-url <url>- use a custom OpenAI-compatible base URL.--openai-api-key <key>- provide an OpenAI API key.--openai-model <model>- override the OpenAI model.
question is one shell argument. Quote it when it contains spaces:
howto "find recently changed files" /tmpEverything after the question is passed to the AI as argument[]. Use -- when an argument starts with --:
howto "explain this flag" -- --forceConfiguration is resolved in this order:
- CLI options
- Environment variables
~/.howto/config.json- Built-in defaults
For each setting, the first configured source in that order wins:
--ai-provider/HOWTO_AI_PROVIDER/aiProvider-openaiorgemini; no default.--gemini-api-key/HOWTO_GEMINI_API_KEY/geminiApiKey- Gemini API key; required for Gemini.--gemini-model/HOWTO_GEMINI_MODEL/geminiModel- Gemini model; defaultgemini-3.1-flash-lite.--openai-api-url/HOWTO_OPENAI_API_URL/openaiApiUrl- OpenAI-compatible base URL; defaults to the OpenAI SDK default.--openai-api-key/HOWTO_OPENAI_API_KEY/openaiApiKey- OpenAI API key; defaults to an empty string for local services.--openai-model/HOWTO_OPENAI_MODEL/openaiModel- OpenAI model; defaultgpt-5.4-mini.
Example:
HOWTO_AI_PROVIDER=openai \
HOWTO_OPENAI_MODEL=gpt-5.4-mini \
howto --print "show current branch"howto treats AI output as untrusted data. Before anything reaches execution, the CLI checks that:
- the AI response is valid JSON matching the required command schema;
- the response contains between one and three candidates;
- all placeholders use
{{name}}syntax and are declared consistently; use <command>candidates clearly start with the requested tool after conservative prefix handling;- obvious dangerous patterns require typing
EXECUTEbefore they can run.
Dangerous-command detection currently covers high-risk patterns such as recursive destructive rm, disk and filesystem operations, broad recursive permission changes, downloaded scripts piped into a shell, high-impact package manager operations, and service changes.
Warning
A command not flagged as dangerous is not guaranteed to be safe. The local checks add friction for known high-risk patterns; they do not prove command safety.
This project is built with TypeScript, React, Ink, OpenAI SDK, Gemini GenAI SDK, and Node's built-in test runner.
npm install
npm run build
npm test
npm run lint
npm run format:checkUseful paths:
src/index.tsx- CLI orchestration and execution flow.src/cli.ts- argument parsing.src/config.ts- config merging and provider validation.src/prompt.ts- prompt and AI output contract.src/validation/- AI response and command-tool validation.src/safety/- dangerous command rules.src/ui/- Ink-based terminal UI.tests/unit/- unit tests for CLI, config, validation, execution, UI, and safety logic.
Run:
howto --initFor --print, initialization is intentionally skipped. Configure the provider first or pass the relevant CLI flags/environment variables.
The default mode needs an interactive TTY for selection and confirmation. Use --print in scripts or CI:
howto --print "show disk usage"Gemini cannot run without an API key. Set HOWTO_GEMINI_API_KEY, pass --gemini-api-key, or rerun howto --init.