# Tanagram

A lightweight Go CLI that enforces policies from `AGENTS.md` files on your local git changes.

## Quick Start

Run `tanagram` before committing to catch policy violations locally:

```bash
$ tanagram

✗ Found 1 policy violation(s):

webui/src/Button.tsx:42 - [No hardcoded colors] Don't use hard-coded color values; use theme colors instead
  > background: "#FF5733"
```

## Installation

### Via npm (Recommended)

```bash
npm install -g @tanagram/cli
tanagram --help
```

**Requirements:**
- Node.js >= 14.0.0
- **Anthropic API Key** (required for LLM-based policy extraction)

The CLI is written in Go but distributed via npm for easier installation and version management. During installation, npm automatically downloads the Go compiler and builds the binary for your platform (no manual setup needed!).

### API Key Setup

Tanagram uses Claude AI (via Anthropic API) to extract policies from your instruction files. You need to bring your own API key:

```bash
# Set your Anthropic API key
export ANTHROPIC_API_KEY="sk-ant-..."

# Or add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc
```

**Get an API key:**
1. Sign up at [https://console.anthropic.com](https://console.anthropic.com)
2. Create an API key in the dashboard
3. Set the `ANTHROPIC_API_KEY` environment variable

### Local Development

```bash
cd cli
npm install  # Builds the Go binary
./bin/tanagram
```

### Install Locally for Testing

Install globally from the local directory to test as if it were published:

```bash
cd /Users/molinar/tanagram/cli
npm install -g .
```

Then run from anywhere:
```bash
tanagram
```

## Usage

```bash
# Check all changes (unstaged + staged) - automatically syncs if policies changed
tanagram
# or explicitly:
tanagram run

# Manually sync instruction files to cache
tanagram sync

# View all cached policies
tanagram list

# Show help
tanagram help
```

**Smart Caching:** Policies are cached and automatically resynced when instruction files change (detected via MD5 hash).

### Commands

- **`run`** (default) - Check git changes against policies with auto-sync
- **`sync`** - Manually sync all instruction files to cache
- **`list`** - View all cached policies (shows enforceable vs unenforceable)
- **`help`** - Show usage information

### Claude Code Hook
You can install the CLI as a Claude Code [hook](https://code.claude.com/docs/en/hooks) to have Claude automatically iterate on Tanagram's output. Add the following to your `~/.claude/settings.json` (user settings) or `.claude/settings.json` (project settings):

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "tanagram"
          }
        ]
      }
    ]
  }
}
```

If you have existing hooks, you can merge this hook into your existing config.


## How It Works

1. **Finds instruction files** - Searches for `AGENTS.md`, `POLICIES.md`, `CLAUDE.md`, `BUGBOT.md`, and `.cursor/rules/*.mdc` in your git repository
2. **Checks cache** - Loads cached policies and MD5 hashes from `.tanagram/`
3. **Auto-syncs** - Detects file changes via MD5 and automatically resyncs if needed
4. **LLM extraction** - Uses Claude AI to extract ALL policies from instruction files
5. **Gets git diff** - Analyzes all your changes (unstaged + staged)
6. **LLM detection** - Checks violations using intelligent semantic analysis
7. **Reports results** - Terminal output with detailed reasoning for each violation

### Cache Location

Policies are cached in `.tanagram/cache.gob` at your git repository root. Add this to your `.gitignore`:

```gitignore
.tanagram/
```

## Fully LLM-Based Architecture

Tanagram uses **100% LLM-powered** policy extraction and enforcement:

### Extraction Phase
Claude AI extracts **ALL** policies from instruction files:
- No classification needed (no MUST_NOT_USE, MUST_USE, etc.)
- No regex pattern generation
- Simple: Just extract policy names and descriptions
- Fast: Simpler prompts = faster responses

### Detection Phase
Claude AI analyzes code changes against all policies:
- **Semantic understanding** - Not just pattern matching
- **Context-aware** - Understands code intent and structure
- **Language-agnostic** - Works with any programming language
- **Detailed reasoning** - Explains why code violates each policy

### What Can Be Enforced

**Everything!** Because the LLM reads and understands code like a human:

**Simple patterns:**
- "Don't use hard-coded colors" → Detects `#FF5733`, `rgb()`, etc.
- "Use ruff format, not black" → Detects `black` usage
- "Always use === instead of ==" → Detects `==` operators

**Complex guidelines:**
- "Break down code into modular functions" → Analyzes function length and complexity
- "Don't deeply layer code" → Detects excessive nesting
- "Ensure no code smells" → Identifies common anti-patterns
- "Use structured logging with request IDs" → Checks logging patterns
- "Prefer async/await for I/O" → Understands async patterns

**Language-specific idioms:**
- Knows Go uses PascalCase for exports (not Python's snake_case)
- Won't flag Go code for missing Python type hints
- Understands JavaScript !== Python !== Go

## Exit Codes

- `0` - No violations found
- `2` - Violations found (triggers Claude Code automatic fix behavior)

## Example

Create an `AGENTS.md` in your repo with policies:

```markdown
# Development Policies

- Don't use hard-coded color values; use theme colors instead
- Use ruff format for Python formatting, not black
- Always use async/await for database operations
```

Or use Cursor rules files in `.cursor/rules/`:

```markdown
---
description: TypeScript coding standards
globs: ["*.ts", "*.tsx"]
---

# TypeScript Standards

- Use strict type checking
- Avoid using 'any' type
- Prefer interfaces over type aliases
```

Then run `tanagram` to enforce them locally!

**Note:** For `.mdc` files, Tanagram extracts policies from the markdown content only (YAML frontmatter is used by Cursor and ignored during policy extraction).

---

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Setup

```bash
# Clone the repository
git clone https://github.com/tanagram/cli.git
cd cli

# Install dependencies and build
npm install

# Run tests
npm test

# Build manually
go build -o bin/tanagram .
```

### Publishing a Release

To publish a new version:

```bash
# 1. Update version in package.json
npm version patch  # or minor, or major

# 2. Commit and tag
git add package.json package-lock.json
git commit -m "Bump version to $(node -p "require('./package.json').version")"
git tag v$(node -p "require('./package.json').version")
git push && git push origin --tags

# 3. Publish to npm
npm publish
```

**Note:** The Go compiler is automatically downloaded and used during `npm install` via the `go-bin` package, so no pre-built binaries needed!

## License

MIT
