Add AI to Your CLI Tool with 20 Lines of Code
AI-powered CLI tools are the next evolution of developer tooling. Instead of rigid commands with fixed logic, your tool can understand natural language queries, generate code, summarize data, and make intelligent suggestions. And with modern AI APIs, adding this takes surprisingly little code.
This article shows how to integrate OpenAI, Anthropic, or local models into any Node.js CLI tool — from basic completions to streaming output and tool use.
The Simplest Integration: 20 Lines
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
export async function askAI(prompt: string, context?: string): Promise<string> {
const messages = [];
if (context) {
messages.push({ role: 'user', content: context });
messages.push({ role: 'assistant', content: 'I understand the context. What would you like to know?' });
}
messages.push({ role: 'user', content: prompt });
const response = await client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages,
});
return response.content[0].text;
}
That's it. Your CLI can now answer questions, analyze data, and generate content.
Use Case 1: Smart Error Explanations
When your tool encounters an error, explain it in plain English:
program
.command('check <file>')
.option('--explain', 'Use AI to explain errors')
.action(async (file, options) => {
const errors = await runCheck(file);
for (const error of errors) {
console.log(chalk.red(` ✗ ${error.message}`));
if (options.explain) {
const explanation = await askAI(
`Explain this error in plain English and suggest a fix: ${error.message}`,
`File: ${file}, Line: ${error.line}, Code: ${error.code}`
);
console.log(chalk.gray(` ${explanation}\n`));
}
}
});
Use Case 2: Natural Language Queries
Let users ask questions about their data:
program
.command('ask <question>')
.description('Ask a natural language question about your project')
.action(async (question) => {
// Gather context
const pkg = JSON.parse(await readFile('package.json', 'utf-8'));
const deps = Object.keys(pkg.dependencies || {});
const context = `
Project: ${pkg.name} v${pkg.version}
Dependencies: ${deps.join(', ')}
Scripts: ${Object.keys(pkg.scripts || {}).join(', ')}
`;
const answer = await askAI(question, context);
console.log(answer);
});
mytool ask "what testing framework does this project use?"
# → Based on the dependencies, this project uses Vitest for testing...
mytool ask "how do I run the development server?"
# → Run `npm run dev` which starts the development server...
Use Case 3: Streaming Output
For long responses, stream tokens as they arrive:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
async function streamAI(prompt: string): Promise<void> {
const stream = client.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 2048,
messages: [{ role: 'user', content: prompt }],
});
for await (const event of stream) {
if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
process.stdout.write(event.delta.text);
}
}
console.log(); // Final newline
}
Use Case 4: Code Generation
program
.command('generate <description>')
.description('Generate code from a natural language description')
.option('-l, --language <lang>', 'Target language', 'typescript')
.action(async (description, options) => {
const prompt = `Generate ${options.language} code for: ${description}
Rules:
- Only output the code, no explanations
- Include necessary imports
- Add brief inline comments
- Make it production-ready`;
console.log(chalk.gray(' Generating...\n'));
await streamAI(prompt);
});
mytool generate "a function that retries a fetch request with exponential backoff"
Use Case 5: AI-Powered Data Analysis
program
.command('analyze <file>')
.description('AI-powered analysis of a data file')
.action(async (file) => {
const content = await readFile(file, 'utf-8');
// Truncate if too large
const sample = content.length > 10000
? content.slice(0, 10000) + '\n... (truncated)'
: content;
const analysis = await askAI(
`Analyze this data and provide key insights, anomalies, and recommendations:\n\n${sample}`,
);
console.log(chalk.bold('\n AI Analysis:\n'));
console.log(` ${analysis.replace(/\n/g, '\n ')}\n`);
});
Cost Management
AI API calls cost money. Be smart about it:
// Cache responses for identical queries
const cache = new Map<string, { response: string; timestamp: number }>();
async function cachedAskAI(prompt: string, ttlMs = 3600000): Promise<string> {
const key = createHash('md5').update(prompt).digest('hex');
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < ttlMs) {
return cached.response;
}
const response = await askAI(prompt);
cache.set(key, { response, timestamp: Date.now() });
return response;
}
Also:
- Use smaller models for simple tasks (
haikufor classification,sonnetfor generation) - Truncate input data to what's needed
- Make AI features opt-in (
--explain,--ai,--smart) - Show cost estimates for expensive operations
API Key Management
function getApiKey(): string {
// 1. Environment variable
const key = process.env.ANTHROPIC_API_KEY;
if (key) return key;
// 2. Stored credential
const stored = loadCredential('anthropic');
if (stored) return stored;
// 3. Prompt
console.error(chalk.yellow(' AI features require an API key'));
console.error(chalk.gray(' Set ANTHROPIC_API_KEY or run: mytool config set api-key <key>'));
process.exit(2);
}
When to Add AI
Add AI when:
- Error explanation — AI can contextualize errors better than static messages
- Data analysis — patterns in logs, metrics, or configs
- Code generation — boilerplate, configs, migrations
- Natural language queries — "what's wrong with my setup?"
Don't add AI when:
- Deterministic logic — sorting, filtering, formatting
- Performance-critical paths — API calls add latency
- Simple transformations — regex, string ops, math
Conclusion
AI in CLI tools isn't about replacing logic — it's about augmenting it. Keep your core tool deterministic and fast. Add AI as opt-in features that make the tool smarter when users want intelligence. Twenty lines of code, and your CLI goes from good to remarkable.
Wilson Xu builds AI-powered developer tools. Find his 16+ npm packages at npmjs.com/~chengyixu.
Top comments (0)