Claude AI Tutorial #3: Claude Code CLI — Installation, Setup, and First Commands

Claude Code is a terminal-native AI coding assistant. It lives in your terminal, reads your codebase, edits files, and runs commands. No IDE plugin needed. No browser tab. Just your terminal. This is Article 3 in the Claude AI — From Zero to Power User series. If you are new to Claude, start with Article 1: What is Claude?. By the end of this article, you will have Claude Code installed, configured, and ready to use on your projects. ...

May 21, 2026 · 8 min

Claude AI Tutorial #2: Getting Started — API Key, First API Call, SDKs

You want to build something with Claude. Great. In this article, you will create an Anthropic account, get an API key, install the SDK, and make your first API call — in both Python and TypeScript. This is Article 2 in the Claude AI — From Zero to Power User series. If you are new to Claude, start with Article 1: What is Claude?. By the end of this article, you will have a working Claude API setup and understand how tokens, pricing, and error handling work. ...

May 20, 2026 · 7 min

Claude AI Tutorial #1: What is Claude? AI Models, Capabilities, and Use Cases

Claude is an AI assistant built by Anthropic. It can write code, analyze documents, reason through complex problems, and use tools. Many developers now use Claude as their primary AI coding tool. But what exactly is Claude? How is it different from ChatGPT or Gemini? And why should you care as a developer? This article answers those questions. It is the first article in our Claude AI — From Zero to Power User tutorial series. By the end of this series, you will know how to use Claude’s API, build agents, and work with advanced features like tool use and the Model Context Protocol (MCP). ...

May 18, 2026 · 8 min

Claude AI Tutorial #27: Claude + Next.js — Build a Web App with Vercel AI SDK

The Vercel AI SDK is the most popular way to use Claude in web applications. It handles streaming, tool use, and UI state — all with a few lines of code. In this article, you will build a complete chat application with Claude, Next.js, and the Vercel AI SDK. This is Article 27 in the Claude AI — From Zero to Power User series. This is the final article in the series. You should know the Messages API and Tool Use before this article. ...

May 16, 2026 · 8 min

Claude AI Tutorial #26: Claude Cheat Sheet — All APIs, Models, and Tips in One Page

Everything you need to use Claude in one page. Bookmark this. Come back whenever you need a quick reference for models, APIs, pricing, or code snippets. This is Article 26 in the Claude AI — From Zero to Power User series. Models (March 2026) Model ID Context Max Output Input (per 1M) Output (per 1M) Opus 4.6 claude-opus-4-6 200K 32K $5.00 $25.00 Sonnet 4.6 claude-sonnet-4-6 200K 16K $3.00 $15.00 Haiku 4.5 claude-haiku-4-5 200K 8K $1.00 $5.00 1M Context (Beta): Available for Opus 4.6 and Sonnet 4.6 on Tier 4+ accounts. Requires header: anthropic-beta: interleaved-thinking-2025-05-14. Premium pricing applies above 200K tokens. ...

May 15, 2026 · 6 min

Claude AI Tutorial #25: Cost Optimization — Batches, Caching, and Model Selection

Claude API costs add up fast if you are not careful. A simple change like enabling prompt caching can cut your bill by 90%. Using the Batch API saves 50%. Stack them together and you save up to 95%. This is Article 25 in the Claude AI — From Zero to Power User series. You should know Understanding Models and Extended Thinking before this article. The Cost Equation Your Claude API cost is determined by three factors: ...

May 13, 2026 · 8 min

Claude AI Tutorial #24: Claude in CI/CD — Automated Code Review in GitHub Actions

Manual code reviews are slow. Pull requests wait hours or days for feedback. In this article, you will set up Claude to automatically review every PR in your GitHub repository, post comments on issues it finds, and approve clean code — all inside GitHub Actions. This is Article 24 in the Claude AI — From Zero to Power User series. You should know Build a Code Review Bot before this article. ...

May 12, 2026 · 7 min

Claude AI Tutorial #23: Build an AI-Powered Blog Writer

Writing blog posts takes hours. Research, outline, drafting, editing — it adds up. In this article, you will build an AI-powered blog writer that automates the process. Give it a topic, and it researches, outlines, and writes a complete article. This is Article 23 in the Claude AI — From Zero to Power User series. You should know Tool Use and Structured Output before this article. Architecture The blog writer follows a five-step pipeline: ...

May 11, 2026 · 8 min

Claude AI Tutorial #21: Build a Code Review Bot with Claude API

Code reviews take time. An AI code review bot can catch bugs, security issues, and common mistakes before a human reviewer even looks at the code. In this article, you will build a bot that reads git diffs and generates structured review comments. This is Article 21 in the Claude AI — From Zero to Power User series. You should know Tool Use and Code Generation Best Practices before this article. What We Are Building A code review bot that: ...

May 7, 2026 · 7 min

Claude AI Tutorial #20: Build a CLI Chatbot with Claude API

Time to build something real. In this article, you will create a CLI chatbot that streams responses, keeps conversation history, and supports slash commands. It is a complete, working application in about 150 lines of code. What We Are Building A terminal chatbot with these features: Streaming responses (character by character) Conversation history (multi-turn) Customizable system prompt Slash commands: /clear, /model, /system, /tokens, /export Token usage tracking Graceful error handling Python Implementation Setup pip install anthropic rich Full Code #!/usr/bin/env python3 """CLI chatbot with Claude API — streaming, history, and slash commands.""" import anthropic import json import sys from datetime import datetime from rich.console import Console console = Console() client = anthropic.Anthropic() # Configuration config = { "model": "claude-sonnet-4-6", "system": "You are a helpful assistant. Be concise and direct.", "max_tokens": 4096, } # Conversation state messages: list[dict] = [] total_input_tokens = 0 total_output_tokens = 0 def stream_response(user_input: str) -> str: """Send a message and stream the response.""" global total_input_tokens, total_output_tokens messages.append({"role": "user", "content": user_input}) full_response = "" with client.messages.stream( model=config["model"], max_tokens=config["max_tokens"], system=config["system"], messages=messages, ) as stream: for text in stream.text_stream: console.print(text, end="", style="green") full_response += text # Get final message for token counts final = stream.get_final_message() total_input_tokens += final.usage.input_tokens total_output_tokens += final.usage.output_tokens console.print() # New line after response messages.append({"role": "assistant", "content": full_response}) return full_response def handle_command(command: str) -> bool: """Handle slash commands. Returns True if command was handled.""" parts = command.strip().split(maxsplit=1) cmd = parts[0].lower() arg = parts[1] if len(parts) > 1 else "" if cmd == "/clear": messages.clear() console.print("[yellow]Conversation cleared.[/yellow]") return True elif cmd == "/model": if arg: config["model"] = arg console.print(f"[yellow]Model set to: {arg}[/yellow]") else: console.print(f"[yellow]Current model: {config['model']}[/yellow]") return True elif cmd == "/system": if arg: config["system"] = arg console.print(f"[yellow]System prompt updated.[/yellow]") else: console.print(f"[yellow]Current system prompt: {config['system']}[/yellow]") return True elif cmd == "/tokens": console.print(f"[yellow]Input tokens: {total_input_tokens:,}[/yellow]") console.print(f"[yellow]Output tokens: {total_output_tokens:,}[/yellow]") # Estimate cost (Sonnet 4.6 pricing) cost = (total_input_tokens * 3 + total_output_tokens * 15) / 1_000_000 console.print(f"[yellow]Estimated cost: ${cost:.4f}[/yellow]") return True elif cmd == "/export": filename = arg or f"chat_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(filename, "w") as f: json.dump( { "model": config["model"], "system": config["system"], "messages": messages, "tokens": { "input": total_input_tokens, "output": total_output_tokens, }, }, f, indent=2, ) console.print(f"[yellow]Conversation exported to {filename}[/yellow]") return True elif cmd == "/help": console.print("[yellow]Commands:[/yellow]") console.print(" /clear — Clear conversation history") console.print(" /model [name] — View or change model") console.print(" /system [prompt] — View or change system prompt") console.print(" /tokens — Show token usage and cost") console.print(" /export [file] — Export conversation to JSON") console.print(" /help — Show this help") console.print(" /quit — Exit") return True elif cmd in ("/quit", "/exit", "/q"): console.print("[yellow]Goodbye![/yellow]") sys.exit(0) return False def main(): """Main chat loop.""" console.print("[bold blue]Claude CLI Chatbot[/bold blue]") console.print(f"Model: {config['model']} | Type /help for commands\n") while True: try: user_input = console.input("[bold cyan]You:[/bold cyan] ").strip() if not user_input: continue if user_input.startswith("/"): if handle_command(user_input): continue console.print("[bold green]Claude:[/bold green] ", end="") stream_response(user_input) console.print() except KeyboardInterrupt: console.print("\n[yellow]Use /quit to exit.[/yellow]") except anthropic.APIError as e: console.print(f"\n[red]API Error: {e.message}[/red]") except anthropic.RateLimitError: console.print("\n[red]Rate limit hit. Wait a moment and try again.[/red]") if __name__ == "__main__": main() TypeScript Implementation Setup npm init -y npm install @anthropic-ai/sdk @clack/prompts Full Code // chatbot.ts import Anthropic from "@anthropic-ai/sdk"; import * as p from "@clack/prompts"; import { writeFileSync } from "fs"; const client = new Anthropic(); // Configuration const config = { model: "claude-sonnet-4-6", system: "You are a helpful assistant. Be concise and direct.", maxTokens: 4096, }; // Conversation state const messages: Anthropic.MessageParam[] = []; let totalInputTokens = 0; let totalOutputTokens = 0; async function streamResponse(userInput: string): Promise<string> { messages.push({ role: "user", content: userInput }); let fullResponse = ""; const stream = await client.messages.stream({ model: config.model, max_tokens: config.maxTokens, system: config.system, messages, }); for await (const event of stream) { if ( event.type === "content_block_delta" && event.delta.type === "text_delta" ) { process.stdout.write(event.delta.text); fullResponse += event.delta.text; } } const finalMessage = await stream.finalMessage(); totalInputTokens += finalMessage.usage.input_tokens; totalOutputTokens += finalMessage.usage.output_tokens; console.log(); // New line after response messages.push({ role: "assistant", content: fullResponse }); return fullResponse; } function handleCommand(command: string): boolean { const [cmd, ...args] = command.trim().split(" "); const arg = args.join(" "); switch (cmd.toLowerCase()) { case "/clear": messages.length = 0; console.log("\x1b[33mConversation cleared.\x1b[0m"); return true; case "/model": if (arg) { config.model = arg; console.log(`\x1b[33mModel set to: ${arg}\x1b[0m`); } else { console.log(`\x1b[33mCurrent model: ${config.model}\x1b[0m`); } return true; case "/system": if (arg) { config.system = arg; console.log("\x1b[33mSystem prompt updated.\x1b[0m"); } else { console.log(`\x1b[33mCurrent system prompt: ${config.system}\x1b[0m`); } return true; case "/tokens": { console.log(`\x1b[33mInput tokens: ${totalInputTokens.toLocaleString()}\x1b[0m`); console.log(`\x1b[33mOutput tokens: ${totalOutputTokens.toLocaleString()}\x1b[0m`); const cost = (totalInputTokens * 3 + totalOutputTokens * 15) / 1_000_000; console.log(`\x1b[33mEstimated cost: $${cost.toFixed(4)}\x1b[0m`); return true; } case "/export": { const filename = arg || `chat_${new Date().toISOString().replace(/[:.]/g, "-")}.json`; writeFileSync( filename, JSON.stringify( { model: config.model, system: config.system, messages, tokens: { input: totalInputTokens, output: totalOutputTokens }, }, null, 2 ) ); console.log(`\x1b[33mConversation exported to ${filename}\x1b[0m`); return true; } case "/help": console.log("\x1b[33mCommands:\x1b[0m"); console.log(" /clear — Clear conversation history"); console.log(" /model [name] — View or change model"); console.log(" /system [prompt] — View or change system prompt"); console.log(" /tokens — Show token usage and cost"); console.log(" /export [file] — Export conversation to JSON"); console.log(" /help — Show this help"); console.log(" /quit — Exit"); return true; case "/quit": case "/exit": case "/q": console.log("\x1b[33mGoodbye!\x1b[0m"); process.exit(0); default: return false; } } async function main(): Promise<void> { p.intro("Claude CLI Chatbot"); console.log(`Model: ${config.model} | Type /help for commands\n`); while (true) { const userInput = await p.text({ message: "You:", placeholder: "Type your message...", }); if (p.isCancel(userInput)) { console.log("\x1b[33mUse /quit to exit.\x1b[0m"); continue; } const input = (userInput as string).trim(); if (!input) continue; if (input.startsWith("/")) { if (handleCommand(input)) continue; } try { process.stdout.write("\x1b[32mClaude:\x1b[0m "); await streamResponse(input); console.log(); } catch (error) { if (error instanceof Anthropic.APIError) { console.error(`\x1b[31mAPI Error: ${error.message}\x1b[0m`); } else { console.error(`\x1b[31mError: ${error}\x1b[0m`); } } } } main(); How It Works Conversation History The messages array stores the entire conversation. Each user message and each assistant response is added to the array. On every new request, Claude sees the full history. ...

May 6, 2026 · 8 min