zam 0.8.1

Enhanced shell history manager with sensitive data redaction
Documentation
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Zam is a modern, fast, and secure command-line history manager written in Rust. It provides enhanced shell history management with automatic sensitive data redaction, multi-shell support, and dual storage backends (file-based and SQLite database).

Key features:
- Automatic sensitive data redaction (passwords, tokens, API keys)
- SQLite database backend with multi-host and session tracking
- Token storage and retrieval for redacted values
- Multi-shell support (Zsh, Bash, Fish)
- Advanced search with fuzzy matching and regex support
- Shell integration scripts

## Development Commands

### Building and Running
```bash
# Build the project
cargo build

# Build release version
cargo build --release

# Run the binary
cargo run -- <command>

# Install locally
cargo install --path .
```

### Testing
```bash
# Run all tests
cargo test

# Run tests with output visible
cargo test -- --nocapture

# Run a specific test module
cargo test redaction::tests

# Run tests for a specific file
cargo test --test history
```

### Code Quality
```bash
# Check for errors without building
cargo check

# Run clippy for linting
cargo clippy

# Format code
cargo fmt

# Check formatting without modifying
cargo fmt -- --check
```

## Architecture

### Dual Backend System

Zam supports two storage backends that share a common interface:

1. **File-based backend** (`history.rs`): Structured log format
2. **Database backend** (`history_db.rs`): SQLite with advanced features

Backend selection logic (in `cli/mod.rs:114-138`):
- Explicitly via `--use-db` or `--use-file` flags
- Auto-detection: uses database if `.mhist.db` exists, otherwise file-based
- `HistoryBackend` enum unifies the two implementations

### Core Module Structure

**CLI Layer** (`cli/` directory):
- `args.rs`: Command-line argument definitions using clap
- `mod.rs`: Main CLI app structure with backend dispatch
- `handlers/`: Separate handler modules for each command category:
  - `basic.rs`: log, search, recent, frequent, validate
  - `config.rs`: configuration management
  - `database.rs`: migrate, merge, tokens, hosts, sessions
  - `import_export.rs`: import/export functionality
  - `shell_integration.rs`: shell integration script generation
  - `tui_handler.rs`: interactive TUI entity browser
  - `alias.rs`: alias management

**Core Library** (`src/` root):
- `history.rs`: File-based history manager (`HistoryManager`)
- `history_db.rs`: Database-backed history manager (`HistoryManagerDb`)
- `database.rs`: Low-level SQLite operations, schema, and queries
- `tui.rs`: Interactive TUI with tabbed entity browser (Local, Top 50, History, Aliases, Hosts, Sessions, Tokens)
- `redaction.rs`: Sensitive data detection and redaction engine
- `search.rs`: Search functionality with fuzzy matching and regex
- `config.rs`: Configuration loading and management
- `error.rs`: Error types and Result alias
- `types.rs`: Type-safe newtype wrappers for IDs (CommandId, HostId, SessionId)
- `prelude.rs`: Common imports and re-exports

### Database Schema

SQLite schema (in `database.rs:100-180`):

**hosts**: Tracks different machines
- id, hostname, created_at

**sessions**: Shell session tracking
- id (UUID), host_id, started_at, ended_at

**commands**: Command history entries
- id, session_id, command, timestamp, directory, redacted, exit_code

**tokens**: Extracted redacted values for retrieval
- id, command_id, token_type, placeholder, original_value, created_at

Foreign key relationships: sessions → hosts, commands → sessions, tokens → commands

### Redaction Engine

The `RedactionEngine` (`redaction.rs`) provides:
- Built-in patterns for common secrets (passwords, API keys, tokens, connection strings, SSH keys, AWS credentials, GitHub tokens)
- Custom pattern support via regex
- Exclude patterns to prevent false positives
- Environment variable redaction
- Token extraction for later retrieval (database backend only)

Pattern types detected (see `BUILTIN_PATTERNS` in `redaction.rs:12-63`):
- Password/credential patterns
- API keys and tokens
- Connection strings (postgresql://, mysql://, mongodb://)
- Bearer tokens
- SSH/private keys
- AWS credentials
- GitHub tokens (ghp_, gho_, etc.)

### Configuration System

Configuration is JSON-based (`~/.zam.json`), with sections:
- `redaction`: Redaction behavior and custom patterns
- `import`: Shell history import settings
- `search`: Search behavior defaults
- `shell_integration`: Auto-logging and exclusion rules
- `logging`: Output preferences

Configuration hierarchy:
1. Explicit `--config` flag
2. Default location (`~/.zam.json`)
3. Built-in defaults (`Config::default()`)

### Interactive TUI (`tui.rs`)

The `zam tui` command provides a tabbed interface for browsing all database entities. Built with `ratatui` and `crossterm`.

**Tabs**: Local (cwd commands), Top 50 (frequent commands), History (all commands, paginated), Aliases, Hosts, Sessions, Tokens

**Key design details**:
- Renders to `/dev/tty` directly so it works inside `$()` command substitution
- Uses crossterm `use-dev-tty` feature for input when stdin is captured
- Enter on Local/Frequent tabs returns the selected command string via `Option<String>`
- Supports filtering (`/`), deletion (`d`), alias editing (`e`), and help overlay (`?`)

**Shell integration** (`shell_integration.rs`):
- Zsh: `precmd`/`preexec` hooks log only successful commands (exit code 0)
- `Ctrl+R` bound to `zam-widget` which runs `zam tui`, sets `BUFFER`, and calls `zle accept-line`
- Aliases loaded via `eval "$(zam alias list --shell)"`

### Search Engine

The `SearchEngine` (`search.rs`) supports:
- Fuzzy matching (configurable threshold)
- Regex patterns
- Case-sensitive/insensitive search
- Directory filtering
- Time range filtering
- Redacted-only filtering
- Result limiting
- Match highlighting

## Working with the Codebase

### Adding a New Command

1. Define args struct in `cli/args.rs`
2. Add variant to `Commands` enum in `cli/mod.rs`
3. Create handler function in appropriate `cli/handlers/` module
4. Add match arm in `CliApp::run()` to dispatch to handler
5. Handler can access both backends via pattern matching on `app.backend`

### Adding a New Redaction Pattern

Built-in patterns: Add to `BUILTIN_PATTERNS` in `redaction.rs`
Custom patterns: Users add via configuration

### Testing Approach

Tests are embedded in source files using `#[cfg(test)]` modules. Major test coverage exists in:
- `config.rs`: Configuration loading and defaults
- `redaction.rs`: Redaction pattern matching
- `search.rs`: Search functionality
- `history.rs`: File operations
- `database.rs`: Database operations
- `history_db.rs`: Database backend integration

Use `tempfile` crate for test isolation (see `dev-dependencies` in `Cargo.toml`).

### Database Migrations

If modifying schema:
1. Update `initialize_schema()` in `database.rs`
2. Existing databases auto-initialize missing tables/columns
3. Consider adding migration command if breaking changes are needed

### Backend Implementation Parity

When adding features, consider:
- Does it work with both backends?
- Should it be database-only? (sessions, tokens, hosts, merge)
- File-only features are deprecated in favor of database

Return appropriate errors for unsupported operations (e.g., token retrieval requires database backend).

## Rust Best Practices Implemented

This codebase follows modern Rust idioms and best practices:

### Type Safety with Newtypes
- **Type-safe ID wrappers** (`types.rs`): `CommandId`, `HostId`, `SessionId` prevent ID type confusion
- All ID types implement `From`, `Into`, `Display`, `ToSql`, `FromSql`, and `Serialize`/`Deserialize`
- Compile-time prevention of passing wrong ID types to functions

Example:
```rust
// This won't compile - type safety!
let host_id: HostId = HostId::new(1);
db.get_tokens_for_command(host_id); // Error: expected CommandId, found HostId
```

### Clean Conversions with From Trait
- Use `impl From<CommandEntry> for HistoryEntry` instead of manual struct construction
- Prefer `.map(Into::into)` over verbose mapping closures

Example:
```rust
// Good
mgr.get_all_commands()?.into_iter().map(Into::into).collect()

// Avoid
mgr.get_all_commands()?.into_iter().map(|cmd| HistoryEntry {
    command: cmd.command,
    timestamp: cmd.timestamp,
    // ...
}).collect()
```

### Must-Use Annotations
- Important functions marked with `#[must_use]` to catch unused Results
- Applied to: constructors, query methods, redaction functions

### Observability with Tracing
- Structured logging via `tracing` crate instead of custom verbose_println
- Control log levels with `RUST_LOG` environment variable (e.g., `RUST_LOG=debug`)
- Use `debug!()`, `info!()`, `warn!()`, `error!()` macros for logging

Example:
```bash
# Run with debug logging
RUST_LOG=debug zam status

# Run with info logging
RUST_LOG=info zam import zsh
```

### Prelude Pattern
- Common imports available via `use zam::prelude::*`
- Includes: `Error`, `Result`, `Config`, and ID types

## Development Guidelines

### Commit Messages
- Do not include "Generated with Claude Code" or similar branding
- Use conventional commit format: `feat:`, `fix:`, `refactor:`, `docs:`, etc.
- Keep commit messages concise and focused on what changed, not benefits

### Code Style
- Use `From` trait implementations for type conversions
- Prefer iterator chains over manual loops
- Add `#[must_use]` to functions returning important Results
- Use `tracing` macros for all logging (never `println!` or `eprintln!` except for user output)