# ClaudeBase CLI

Command-line tool for managing Claude Code plugins from the ClaudeBase catalog.

**Version:** 1.0.0

## Documentation

- [Plugin Installation](./docs/plugin-install.md) - How plugins are installed
- [Offline Mode](./docs/offline-mode.md) - Working without network
- [Security Model](./docs/security-model.md) - Trust boundaries and guarantees
- [Limitations](./docs/limitations.md) - Intentional constraints

## Installation

```bash
npm install -g claudebase
```

## Quick Start

```bash
# Refresh the plugin catalog (required before first install)
claudebase catalog refresh

# Install a plugin
claudebase plugin add demo-plugin

# List installed plugins
claudebase plugin list
```

## Catalog Discovery Model

The CLI uses a **predictable, safe, and transparent** catalog discovery model:

### Key Principles

1. **Infinite TTL** - The catalog cache never expires automatically
2. **Explicit Refresh** - Network calls only on explicit user action or bounded one-shot miss
3. **Offline First** - All operations work offline if cache exists
4. **Fail Closed** - Unknown schema versions or fields cause immediate failure

### Plugin Discovery Flow

```
claudebase plugin add <name>
├── Check local cache for plugin
├── If found → proceed to install
├── If NOT found AND not --offline:
│   ├── Fetch index.json (one attempt)
│   ├── If new snapshot hash → fetch and validate
│   ├── Retry lookup once
│   └── If still not found → fail with message
└── If NOT found AND --offline → fail immediately
```

## Commands

### Catalog Commands

#### `claudebase catalog refresh`

Fetch the latest catalog from the ClaudeBase dashboard.

```bash
claudebase catalog refresh
claudebase catalog refresh --catalog-url https://custom.api.com/api/catalog
```

**Options:**
- `--catalog-url <url>` - Custom catalog URL (default: `CLAUDEBASE_CATALOG_URL` env var or `https://api.claudebase.com/api/catalog`)

#### `claudebase catalog status`

Show catalog cache status.

```bash
claudebase catalog status
```

#### `claudebase catalog clear`

Clear the catalog cache.

```bash
claudebase catalog clear
```

#### `claudebase catalog list`

List all public plugins in the catalog.

```bash
claudebase catalog list
```

### Plugin Commands

#### `claudebase plugin add <name>`

Install a plugin from the catalog.

```bash
claudebase plugin add demo-plugin
claudebase plugin add demo-plugin --allow-unlisted
claudebase plugin add demo-plugin --offline
claudebase plugin add demo-plugin --refresh-catalog
```

**Options:**
- `--allow-unlisted` - Allow installing unlisted plugins
- `--allow-downgrade` - Allow downgrading to an older version
- `--refresh-catalog` - Force refresh catalog before lookup (conflicts with --offline)
- `--offline` - Enforce offline mode (no network calls)
- `--force` - Force reinstall even if same version is installed

**One-Shot Miss Behavior:**
When a plugin is not found in the cached catalog and `--offline` is not set:
1. CLI fetches `index.json` once
2. If new snapshot hash, fetches and validates new snapshot
3. Retries lookup exactly once
4. If still not found, fails with deterministic message

#### `claudebase plugin remove <name>`

Remove an installed plugin.

```bash
claudebase plugin remove demo-plugin
```

#### `claudebase plugin list`

List installed plugins.

```bash
claudebase plugin list
```

#### `claudebase plugin verify [name]`

Verify installed plugin(s) integrity.

```bash
claudebase plugin verify           # Verify all plugins
claudebase plugin verify demo-plugin  # Verify specific plugin
```

#### `claudebase plugin info <name>`

Show detailed information about a plugin.

```bash
claudebase plugin info demo-plugin
```

### Cache Commands

#### `claudebase cache status`

Show package cache status.

```bash
claudebase cache status
```

#### `claudebase cache clear`

Clear the package cache.

```bash
claudebase cache clear
```

## Network Boundaries

The CLI enforces **strict network boundaries** per command:

### Commands That MAY Hit Network

| Command | Network Condition |
|---------|-------------------|
| `catalog refresh` | Always (unless `--offline`) |
| `plugin add` | One-shot miss refresh OR `--refresh-catalog` OR npm tarball fetch |

### Commands That NEVER Hit Network

| Command | Network |
|---------|---------|
| `catalog status` | Never |
| `catalog clear` | Never |
| `catalog list` | Never |
| `plugin list` | Never |
| `plugin remove` | Never |
| `plugin verify` | Never |
| `plugin info` | Never |
| `cache status` | Never |
| `cache clear` | Never |

### Offline Mode (`--offline`)

When `--offline` is set:
- **Zero network calls** - Any network attempt fails immediately
- Works with cached catalog and cached tarballs only
- Deterministic error messages for missing data

```bash
# Install only if everything is cached
claudebase plugin add demo-plugin --offline

# This will fail - refresh requires network
claudebase catalog refresh --offline  # Error!
```

### Force Refresh

```bash
# Force catalog refresh before plugin lookup
claudebase plugin add demo-plugin --refresh-catalog
```

**Note:** `--refresh-catalog` and `--offline` conflict and cannot be used together.

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `CLAUDEBASE_CATALOG_URL` | Catalog API base URL | `https://api.claudebase.com/api/catalog` |

## Error Codes

The CLI uses deterministic error codes for scripting:

### Catalog Errors
- `CATALOG_FETCH_FAILED` - Network error fetching catalog
- `CATALOG_INVALID_JSON` - Catalog response is not valid JSON
- `CATALOG_UNKNOWN_SCHEMA_VERSION` - Unsupported catalog schema version (exit code 3)
- `CATALOG_UNKNOWN_FIELD` - Unknown field in catalog (fail-closed)
- `CATALOG_HASH_MISMATCH` - Snapshot hash doesn't match index
- `CATALOG_CACHE_CORRUPTED` - Local cache is corrupted
- `CATALOG_DOWNGRADE_DETECTED` - Index points to older snapshot

### Plugin Errors
- `PLUGIN_NOT_FOUND` - Plugin not in catalog (exit code 2)
- `PLUGIN_REVOKED` - Plugin has been revoked
- `PLUGIN_UNLISTED` - Plugin is unlisted (use `--allow-unlisted`)
- `PLUGIN_NAME_MISMATCH` - Name doesn't match across sources

### Install Errors
- `INSTALL_TARBALL_SYMLINK` - Tarball contains symlinks (blocked)
- `INSTALL_TARBALL_PATH_TRAVERSAL` - Tarball contains path traversal
- `INSTALL_TARBALL_FORBIDDEN_FILE` - Tarball contains forbidden files
- `INSTALL_LIFECYCLE_SCRIPTS` - package.json has lifecycle scripts
- `INSTALL_INTEGRITY_MISMATCH` - File hashes don't match integrity.json
- `INSTALL_MISSING_PLUGIN_JSON` - Missing .claude-plugin/plugin.json

### Network Policy Errors
- `OFFLINE_MODE_VIOLATION` - Network access attempted in offline mode (exit code 4)

### Version Errors
- `VERSION_DOWNGRADE_FORBIDDEN` - Downgrade not allowed (use `--allow-downgrade`)

### Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Network failure |
| 2 | Plugin not found |
| 3 | Schema version unsupported |
| 4 | Offline mode violation |
| 5 | General catalog error |

## Security

The CLI enforces strict security measures:

1. **Allowlist enforcement** - Only public plugins from the catalog are installable
2. **No lifecycle scripts** - Packages with npm lifecycle scripts are rejected
3. **No symlinks** - Tarballs containing symlinks are rejected
4. **Path traversal protection** - Paths like `../` are rejected
5. **Integrity verification** - All files verified against integrity.json
6. **Scope enforcement** - Only `@claudebase/*` packages accepted
7. **Fail closed** - Unknown schema versions or fields cause immediate failure
8. **Hash verification** - Snapshot content must match index hash
9. **Downgrade detection** - Older snapshots are rejected automatically
10. **Audit logging** - All catalog operations logged locally (no telemetry)

### Downgrade Attack Protection

The CLI tracks the "latest seen" snapshot timestamp monotonically:
- If `index.json` points to an older snapshot, refresh is blocked
- Warning message explains the situation
- User must explicitly act to use an older snapshot

### Catalog Poisoning Defense

- Index hash must match snapshot content hash
- Unknown fields in catalog entries cause failure
- Schema version must be in supported set

## Cache Locations

| OS | Catalog Cache | Tarball Cache |
|----|---------------|---------------|
| macOS/Linux | `~/.claudebase/cache/catalog/` | `~/.claudebase/cache/tarballs/` |
| Windows | `%LOCALAPPDATA%\claudebase\cache\catalog\` | `%LOCALAPPDATA%\claudebase\cache\tarballs\` |

## Plugin Installation Location

Plugins are installed to Claude Code's expected location:

```
~/.claude/plugins/<plugin-name>/
├── package.json
├── integrity.json
├── .claude-plugin/
│   └── plugin.json
├── skills/           (if plugin has skills)
│   └── *.json
└── .mcp.json         (if plugin has MCP servers)
```

## License

MIT
