Claude Code on Linux: Terminal Workflow for Developers

Claude Code on Linux: Terminal Workflow for Developers
Claude Code is Anthropic's official CLI tool that brings AI-assisted development directly into your terminal. Unlike web-based interfaces, Claude Code understands your project structure, reads files, executes commands, and makes multi-file edits — all from within your existing shell workflow. This tutorial covers everything you need to get productive with it on Linux.
Installing Claude Code on Linux
Prerequisites
Claude Code requires Node.js 18 or higher. Verify your version before installing:
node --version
# Should output v18.x.x or higher
npm --version
# Should output 9.x.x or higherIf you need to upgrade Node.js, use nvm for the cleanest experience:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts
nvm use --ltsGlobal Installation via npm
npm install -g @anthropic-ai/claude-codeIf you hit permission errors on a system-wide npm install, avoid using sudo with npm. Instead, configure npm to use a user-level directory:
mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=$HOME/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
# Now install without sudo
npm install -g @anthropic-ai/claude-codeVerifying the Installation
which claude
# /home/youruser/.npm-global/bin/claude
claude --version
# claude-code 1.x.xInitial Setup: API Key and First Run
Obtaining and Configuring Your API Key
You need an Anthropic API key from console.anthropic.com. Claude Code uses the ANTHROPIC_API_KEY environment variable. Add it to your shell profile for persistence:
echo 'export ANTHROPIC_API_KEY="sk-ant-your-key-here"' >> ~/.bashrc
source ~/.bashrc
# Verify it's set
echo $ANTHROPIC_API_KEYFor better security, consider using a secrets manager or storing the key in a file with restricted permissions:
chmod 600 ~/.anthropic_key
echo 'export ANTHROPIC_API_KEY=$(cat ~/.anthropic_key)' >> ~/.bashrcFirst Run and Interface Overview
Navigate to a project directory and launch Claude Code:
cd ~/projects/my-app
claudeThe interface presents a prompt where you type naturally. Claude Code automatically reads your current directory structure on startup. You'll see a > prompt. The key things to understand about the interface:
- Context is per-session — Claude remembers everything within a session but starts fresh each time
- File edits are real — when Claude modifies a file, it's immediately written to disk
- Command execution requires confirmation — by default, Claude asks before running shell commands
- The token counter is visible in the interface and shows context consumption in real time
Project Setup with CLAUDE.md
What CLAUDE.md Does
The CLAUDE.md file lives in your project root and is automatically loaded into context at the start of every Claude Code session. It's your primary mechanism for shaping Claude's behavior per-project — defining conventions, constraints, architecture notes, and recurring context you'd otherwise have to re-explain.
Creating an Effective CLAUDE.md
touch CLAUDE.mdA well-structured CLAUDE.md for a Python web application might look like:
# Project: Inventory API
## Stack
- Python 3.11, FastAPI, PostgreSQL 15
- SQLAlchemy 2.0 with async support
- pytest for testing, ruff for linting
- Docker Compose for local dev
## Architecture
- `app/` — application code
- `app/routers/` — FastAPI route handlers, one file per resource
- `app/models/` — SQLAlchemy ORM models
- `app/schemas/` — Pydantic request/response schemas
- `tests/` — mirrors app/ structure
## Conventions
- All database queries go through repository classes in `app/repositories/`
- Never put business logic in routers; use service layer in `app/services/`
- Use `async def` for all route handlers and DB operations
- Error handling: raise HTTPException with appropriate status codes
- All new features need corresponding tests
## Commands
- `make dev` — start local stack
- `make test` — run full test suite
- `make lint` — run ruff
- `make migrate` — run alembic migrations
## Do Not
- Modify `alembic/env.py` without asking first
- Change database models without creating a migration
- Use synchronous SQLAlchemy in async contextsThe "Do Not" section is particularly valuable — it prevents Claude from making well-intentioned but disruptive changes to sensitive parts of your codebase.
Key Slash Commands
/help
Displays all available commands and current session status:
/helpRun this when you're unsure about available capabilities or want to see keyboard shortcut references.
/clear
Wipes the entire conversation history and resets context:
/clearUse this when you've finished one task and are starting something unrelated. Keeping stale context from a previous task wastes tokens and can confuse Claude's responses on the new task.
/compact
Compresses the conversation history to recover context space while preserving the essential thread:
/compactThis is invaluable on long sessions. Claude Code summarizes earlier parts of the conversation into a dense representation, freeing up tokens for continued work. Use it proactively when you see the context meter climbing past 50-60%.
/review
Asks Claude to review the changes made during the current session:
/reviewThis is effectively asking Claude to audit its own work — it will re-examine files it modified, check for consistency, look for bugs it introduced, and flag anything uncertain. Make this a habit before committing changes Claude helped write.
Working with Files
How Claude Sees Your Project
Claude Code uses the current working directory as its root context. It can read files on demand and will do so when asked or when it determines file content is needed to answer accurately. You can be explicit:
> Read the main application entry point and explain the startup sequence> Look at app/services/inventory.py and identify any N+1 query problemsReading Multiple Files
> Read all files in app/routers/ and check that error handling is consistent across endpointsEditing Files
Claude Code edits files in place. It shows you a diff before writing when making significant changes. You can be surgical:
> In app/models/product.py, add an `updated_at` column that auto-updates on modificationOr broader:
> Refactor the authentication middleware in app/middleware/auth.py to use the new JWT library we just installed. The current code uses PyJWT 1.x patterns and needs to be updated for 2.xCreating New Files
> Create a new router at app/routers/suppliers.py following the same pattern as app/routers/products.py. Implement CRUD endpoints for a Supplier model with fields: id, name, contact_email, activeShell Integration Tips
Running from Any Directory
Claude Code always operates relative to where you invoke it. Create a shell function to jump to a project and launch simultaneously:
# Add to ~/.bashrc
function ccode() {
local project_dir="${1:-$(pwd)}"
cd "$project_dir" && claude
}
# Usage
ccode ~/projects/my-apiUsing with Git
Claude Code integrates naturally with git workflows. Common patterns:
# Review staged changes before committing
git diff --staged | claude -p "Review these staged changes for bugs, style issues, and anything I might have missed"
# Generate a commit message from staged diff
git diff --staged | claude -p "Write a conventional commit message for these changes"
# Explain an unfamiliar commit
git show abc1234 | claude -p "Explain what this commit does and why the changes make sense together"The -p flag runs Claude Code in non-interactive "print" mode — it processes input and exits, which is ideal for pipeline use.
Piping Output Into Claude
# Analyze a log file
tail -n 200 /var/log/nginx/error.log | claude -p "Identify any patterns in these errors and suggest fixes"
# Explain compiler errors
make build 2>&1 | claude -p "Explain these build errors and tell me how to fix them"
# Analyze command output
df -h | claude -p "Which filesystems are getting full and what should I clean up first"Custom Workflows for Complex Multi-File Changes
Structuring Large Tasks
For changes that touch multiple files, give Claude an explicit plan before executing. This reduces errors and helps you catch misunderstandings before code is written:
> I need to add soft-delete functionality to the entire application. Before making any changes, outline your plan: which files you'll modify, what changes you'll make to each, and what order you'll do them in. Don't write any code yet.Review the plan, correct any misunderstandings, then proceed:
> The plan looks good except: don't modify the API response schemas, soft-deleted records should still be serializable. Now implement the changes in the order you described.Checkpointing with Git
Commit working state before large Claude-assisted changes so you have a clean rollback point:
git add -A && git commit -m "wip: checkpoint before claude refactor"
# Let Claude make changes
# Review with /review
git diff # inspect everything
git add -p # selectively stageMCP Server Integration
What MCP Is
Model Context Protocol (MCP) is an open standard that lets Claude connect to external data sources and tools. MCP servers extend Claude Code's capabilities beyond your local filesystem — connecting to GitHub, databases, documentation systems, and more.
Setting Up the Filesystem MCP Server
The filesystem MCP server gives Claude structured access to directories outside your current working path:
npm install -g @modelcontextprotocol/server-filesystemConfigure it in Claude Code's config file at ~/.claude/config.json:
{
"mcpServers": {
"filesystem": {
"command": "mcp-server-filesystem",
"args": ["/home/youruser/projects", "/etc/nginx"]
}
}
}Setting Up the GitHub MCP Server
npm install -g @modelcontextprotocol/server-github{
"mcpServers": {
"github": {
"command": "mcp-server-github",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
}
}
}With the GitHub MCP active, you can ask Claude to interact directly with repositories:
> List the open issues labeled "bug" in myorg/myrepo and prioritize them by potential impactPractical Example: Debugging a Bash Script
Here's a real debugging session. Suppose you have a deployment script that's silently failing:
cat deploy.sh#!/bin/bash
ENVIRONMENT=$1
DEPLOY_DIR="/var/www/$ENVIRONMENT"
rsync -av ./dist/ $DEPLOY_DIR/
systemctl restart app-$ENVIRONMENT
echo "Deployed to $ENVIRONMENT"./deploy.sh staging
# Output: Deployed to staging
# But the app isn't actually restarting...Start a Claude Code session in the same directory:
claude> Read deploy.sh. When I run it, it prints "Deployed to staging" but the systemctl restart doesn't seem to be taking effect. No error is shown. What's wrong?Claude will identify that systemctl failures are being silently swallowed because there's no error checking, and the script doesn't run with sufficient privileges. It will suggest a fix:
> Fix the script to: exit on any error, check that ENVIRONMENT was provided, verify the deploy directory exists, capture and report systemctl output, and exit with a non-zero code on failureClaude produces a corrected version and writes it. You verify:
cat deploy.sh#!/bin/bash
set -euo pipefail
if [[ -z "${1:-}" ]]; then
echo "Usage: $0 " >&2
exit 1
fi
ENVIRONMENT=$1
DEPLOY_DIR="/var/www/$ENVIRONMENT"
if [[ ! -d "$DEPLOY_DIR" ]]; then
echo "Error: Deploy directory $DEPLOY_DIR does not exist" >&2
exit 1
fi
echo "Deploying to $ENVIRONMENT..."
rsync -av ./dist/ "$DEPLOY_DIR/"
if ! systemctl restart "app-$ENVIRONMENT"; then
echo "Error: Failed to restart app-$ENVIRONMENT" >&2
systemctl status "app-$ENVIRONMENT" >&2
exit 1
fi
echo "Successfully deployed to $ENVIRONMENT" > Now write a test script that validates deploy.sh behaves correctly when given no arguments, a bad environment, and a valid environment using a temp directoryKeyboard Shortcuts and Productivity Tips
- Ctrl+C — interrupt Claude mid-response without exiting the session
- Ctrl+L — clear the terminal display (doesn't clear Claude's context)
- Up arrow — cycle through previous prompts in the session
- Ctrl+D — exit Claude Code cleanly
- Tab — autocomplete file paths in your prompt
Set up a shell alias for launching Claude Code with a project-specific flag:
alias cc='claude'
alias ccnew='claude --no-cache' # forces fresh context, useful when CLAUDE.md changesFor long-running sessions, use tmux or screen so you don't lose your session:
tmux new-session -s claude-work
# Work in Claude Code
# Detach with Ctrl+B, D
# Reattach later with:
tmux attach -t claude-workCommon Pitfalls and How to Avoid Them
Context Limit Exhaustion
Claude Code sessions have a finite context window. Symptoms include degraded response quality, Claude forgetting earlier instructions, or outright context limit errors. Mitigation strategies:
- Run
/compactproactively at natural task boundaries, not reactively when you're already in trouble - Break large tasks into discrete sessions rather than doing everything in one marathon session
- Use
CLAUDE.mdto offload standing context so you don't re-explain it in-session - Avoid pasting entire log files or large data sets directly — pipe them with targeted questions instead
Rate Limits
Anthropic's API has rate limits per tier. If you hit them, you'll see 429 errors. Handle this by:
- Checking your tier at console.anthropic.com and upgrading if necessary
- Batching your questions rather than sending rapid-fire short prompts
- Using
-pmode for scripted/automated use cases to avoid runaway sessions
Cost Awareness
Every token costs money. Common expensive mistakes:
# DON'T do this — sends your entire codebase into context
find . -name "*.py" -exec cat {} ; | claude -p "review everything"
# DO this instead — targeted, specific
claude -p "Review only the authentication logic" < app/middleware/auth.pyMonitor your usage at console.anthropic.com/usage and set billing alerts. For exploratory or learning use, prefer short focused sessions over leaving Claude Code running while you think.
Blind Trust in File Edits
Claude Code writes files directly. Never skip the review step:
# Always review diffs before accepting large changes
git diff
# Use git's patch mode for selective staging
git add -p
# For sensitive infrastructure files, review twice
git diff -- ansible/ terraform/ k8s/Missing CLAUDE.md for Shared Projects
If your team uses Claude Code, commit CLAUDE.md to version control. An absent or stale CLAUDE.md means every developer is re-establishing the same context manually, and Claude may make inconsistent architectural decisions across sessions. Treat CLAUDE.md like a living document — update it when conventions change, when new tooling is added, or when you discover a class of mistake Claude keeps making.
