Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.4.0] - 2026-03-13

### Added

- **Multi-provider API key support**: Configure separate API keys for different providers
- `CEREBRAS_API_KEY` / `cerebras-api-key` — direct Cerebras inference (fastest path)
- `OPENROUTER_API_KEY` / `openrouter-api-key` — OpenRouter multi-provider access
- `RAYPASTE_API_KEY` / `api-key` — reserved for future Raypaste backend
- **Smart provider routing**: Automatically routes requests to the best available provider
- Cerebras models with a Cerebras key go direct (eliminates OpenRouter hop)
- Falls back to OpenRouter when no direct key is available
- Legacy `api_key` with `sk-or-` prefix is treated as OpenRouter key with migration notice
- **Direct provider model IDs**: Models now carry a `DirectID` field for provider-native model identifiers (e.g., `llama-3.1-8b-instruct` for Cerebras direct vs `meta-llama/llama-3.1-8b-instruct` for OpenRouter)
- **New config commands**: `raypaste config set cerebras-api-key` and `raypaste config set openrouter-api-key`
- **Comprehensive tests**: Table-driven tests for `ResolveProviderKey`, `HasAnyAPIKey`, provider-specific getters, and `BuildRequest` with direct provider routing

### Changed

- **`NewClient` signature**: Now takes `(provider, apiKey)` instead of just `(apiKey)` — routes to the correct base URL and sets provider-appropriate headers
- **`BuildRequest` signature**: Now takes a `provider` parameter to select the correct model ID (OpenRouter ID vs direct provider ID)
- **API key validation**: `initConfig` now checks `HasAnyAPIKey()` instead of a single `GetAPIKey()`, with improved error messaging listing all key options
- **Updated help text and documentation**: CLI help, README, and config command descriptions reflect the new multi-provider setup

## [0.3.1] - 2026-03-05

### Changed
Expand Down Expand Up @@ -229,6 +252,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Flexible Configuration**: Multiple configuration methods
- **Model Flexibility**: Use built-in aliases or any OpenRouter model ID

[0.4.0]: https://github.com/raypaste/raypaste-cli/releases/tag/v0.4.0
[0.3.1]: https://github.com/raypaste/raypaste-cli/releases/tag/v0.3.1
[0.3.0]: https://github.com/raypaste/raypaste-cli/releases/tag/v0.3.0
[0.2.7]: https://github.com/raypaste/raypaste-cli/releases/tag/v0.2.7
[0.2.2]: https://github.com/raypaste/raypaste-cli/releases/tag/v0.2.2
Expand Down
94 changes: 94 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,100 @@

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

Review this plan thoroughly before making any code changes. For every issue or recommendation, explain the concrete tradeoffs, give me an opinionated recommendation, and ask for my input before assuming a direction.

My engineering preferences (use these to guide your recommendations):

DRY is important—flag repetition aggressively.

Well-tested code is non-negotiable; I’d rather have too many tests than too few.

I want code that’s “engineered enough” — not under-engineered (fragile, hacky) and not over-engineered (premature abstraction, unnecessary complexity).

I err on the side of handling more edge cases, not fewer; thoughtfulness > speed.

Bias toward explicit over clever.

1. Architecture review

Evaluate:

Overall system design and component boundaries.

Dependency graph and coupling concerns.

Data flow patterns and potential bottlenecks.

Scaling characteristics and single points of failure.

Security architecture (auth, data access, API boundaries).

2. Code quality review

Evaluate:

Code organization and module structure.

DRY violations—be aggressive here.

Error handling patterns and missing edge cases (call these out explicitly).

Technical debt hotspots.

Areas that are over-engineered or under-engineered relative to my preferences.

3. Test review

Evaluate:

Test coverage gaps (unit, integration, e2e).

Test quality and assertion strength.

Missing edge case coverage—be thorough.

Untested failure modes and error paths.

4. Performance review

Evaluate:

N+1 queries and database access patterns.

Memory-usage concerns.

Caching opportunities.

Slow or high-complexity code paths.

For each issue you find (for every specific issue (bug, smell, design concern, or risk)):

Describe the problem concretely, with file and line references.

Present 2–3 options, including “do nothing” where that’s reasonable.

For each option, specify: implementation effort, risk, impact on other code, and maintenance burden.

Give me your recommended option and why, mapped to my preferences above.

Then explicitly ask whether I agree or want to choose a different direction before proceeding.

Workflow and interaction

Do not assume my priorities on timeline or scale.

After each section, pause and ask for my feedback before moving on.

BEFORE YOU START:

Ask if I want one of two options:

1/ BIG CHANGE: Work through this interactively, one section at a time (Architecture → Code Quality → Tests → Performance) with at most 4 top issues in each section.

2/ SMALL CHANGE: Work through interactively ONE question per review section.

FOR EACH STAGE OF REVIEW: output the explanation and pros and cons of each stage’s questions AND your opinionated recommendation and why, and then use AskUserQuestion. Also NUMBER issues and then give LETTERS for options and when using AskUserQuestion make sure each option clearly labels the issue NUMBER and option LETTER so the user doesn’t get confused. Make the recommended option always the 1st option.

## Commands

```bash
Expand Down
99 changes: 66 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

### Open-source ultra-fast AI completions right in your terminal.

A lightning fast Go CLI for generating meta-prompts and AI completions quickly via [OpenRouter](https://openrouter.ai/), with fast model routing, configurable output lengths, customizable prompts, and an interactive mode.
A lightning fast Go CLI for generating meta-prompts and AI completions quickly, with fast model routing, configurable output lengths, customizable prompts, and an interactive mode. Supports direct [Cerebras](https://www.cerebras.ai/) inference and multi-provider access via [OpenRouter](https://openrouter.ai/).

- **Responses in Milliseconds**: Generate text completions in ~100-900ms using open-source models running on
Cerebras chips.
- **Interactive Mode**: Run raypaste in interactive mode with streaming output and slash commands
- **Project Context Awareness**: Automatically loads context from `CLAUDE.md`, `AGENTS.md`, or `.cursor/rules/` files to inform prompt generation
- **Custom Prompts**: Create and use your own prompts
- **Flexible Configuration**: Configure via YAML, environment variables, or CLI flags
- **OpenRouter Integration**: Raypaste can be used with many different LLM providers and models through OpenRouter's API
- **Direct Provider Access**: Connect directly to Cerebras for the fastest possible inference, or use OpenRouter for multi-provider access
- **OpenRouter Integration**: Raypaste can also be used with many different LLM providers and models through OpenRouter's API

## Installation

Expand Down Expand Up @@ -45,33 +46,42 @@ sudo mv raypaste /usr/local/bin/

## Quick Start

1. **Get an OpenRouter API key** from [openrouter.ai/keys](https://openrouter.ai/keys)
1. **Get an API key** (choose one or both):

1a. (Recommended): Get a **Cerebras** key from [cerebras.ai](https://www.cerebras.ai) to set up in _OpenRouter > Settings > BYOK (bring your own key) > Cerebras API key_.
- **Cerebras (Recommended for speed)**: Get a key from [cloud.cerebras.ai](https://cloud.cerebras.ai/) for direct, ultra-fast inference
- **OpenRouter (Multi-provider)**: Get a key from [openrouter.ai/keys](https://openrouter.ai/keys) for access to many providers/models

2. **Set your API key for Raypaste** (choose one method):
2. **Set your API key(s)** (choose one method):

**Option A: Config Command (Recommended)**

```bash
raypaste config set api-key <your_api_key_here>
# For direct Cerebras access (fastest)
raypaste config set cerebras-api-key <your_cerebras_key>

# For OpenRouter multi-provider access
raypaste config set openrouter-api-key <your_openrouter_key>

# You can set both — Cerebras models will go direct, others via OpenRouter
```

**Option B: Environment Variable**
**Option B: Environment Variables**

```bash
export RAYPASTE_API_KEY=your_api_key_here
export CEREBRAS_API_KEY=your_cerebras_key
# and/or
export OPENROUTER_API_KEY=your_openrouter_key
```

To make it permanent, add to your shell config:

```bash
# For zsh (macOS default)
echo 'export RAYPASTE_API_KEY=your_api_key_here' >> ~/.zshrc
echo 'export CEREBRAS_API_KEY=your_cerebras_key' >> ~/.zshrc
source ~/.zshrc

# For bash
echo 'export RAYPASTE_API_KEY=your_api_key_here' >> ~/.bashrc
echo 'export CEREBRAS_API_KEY=your_cerebras_key' >> ~/.bashrc
source ~/.bashrc
```

Expand All @@ -80,12 +90,17 @@ sudo mv raypaste /usr/local/bin/
```bash
mkdir -p ~/.raypaste
cp config.yaml.example ~/.raypaste/config.yaml
# Edit ~/.raypaste/config.yaml and add your API key
# Edit ~/.raypaste/config.yaml and add your API key(s)
nano ~/.raypaste/config.yaml
```

**Note**: The `.env` file in the project directory is for reference only. Go programs don't automatically load `.env` files. You must either export the environment variable or use the config file at `~/.raypaste/config.yaml`.

**API Key Resolution**: When you select a model, raypaste picks the best available route:
1. If the model's provider has a direct key (e.g., Cerebras model + `CEREBRAS_API_KEY`), it goes direct
2. Otherwise, it falls back to OpenRouter if `OPENROUTER_API_KEY` is set
3. Legacy `RAYPASTE_API_KEY` / `api-key` with an `sk-or-` prefix is treated as an OpenRouter key (with a migration notice)

3. **Generate your first prompt**:

```bash
Expand Down Expand Up @@ -127,15 +142,19 @@ raypaste "optimize this code" -m cerebras-gpt-oss-120b
Manage configuration settings via the CLI:

```bash
# Set values
raypaste config set api-key sk-or-v1-...
# Set API keys
raypaste config set cerebras-api-key csk-... # Direct Cerebras access
raypaste config set openrouter-api-key sk-or-v1-... # OpenRouter access

# Set other values
raypaste config set default-model cerebras-llama-8b
raypaste config set default-length short
raypaste config set disable-copy true
raypaste config set temperature 0.8

# Get current values
raypaste config get api-key
raypaste config get cerebras-api-key
raypaste config get openrouter-api-key
raypaste config get default-model
raypaste config get default-length

Expand All @@ -148,13 +167,15 @@ raypaste config prompt remove my-prompt # Remove a custom prompt

**Available config keys:**

| Key | Description | Type |
| ---------------- | --------------------------------------------------- | ------- |
| `api-key` | OpenRouter API key | string |
| `default-model` | Default model alias or OpenRouter ID | string |
| `default-length` | Default output length: `short`, `medium`, or `long` | string |
| `disable-copy` | Disable auto-copy to clipboard | boolean |
| `temperature` | Sampling temperature (0.0 to 2.0) | float |
| Key | Description | Type |
| -------------------- | --------------------------------------------------- | ------- |
| `openrouter-api-key` | OpenRouter API key | string |
| `cerebras-api-key` | Cerebras API key (direct provider access) | string |
| `api-key` | Raypaste API key (reserved for future backend) | string |
| `default-model` | Default model alias or OpenRouter ID | string |
| `default-length` | Default output length: `short`, `medium`, or `long` | string |
| `disable-copy` | Disable auto-copy to clipboard | boolean |
| `temperature` | Sampling temperature (0.0 to 2.0) | float |

**Config prompt command:**

Expand Down Expand Up @@ -212,16 +233,17 @@ Configuration is loaded in the following order (later sources override earlier o

1. Default values
2. Config file (`~/.raypaste/config.yaml`)
3. Environment variables (`RAYPASTE_*`)
3. Environment variables (`OPENROUTER_API_KEY`, `CEREBRAS_API_KEY`, `RAYPASTE_*`)
4. CLI flags

### Config Command

The easiest way to manage configuration is via the `config` command:

```bash
# Set your API key
raypaste config set api-key sk-or-v1-...
# Set your API key(s)
raypaste config set cerebras-api-key csk-...
raypaste config set openrouter-api-key sk-or-v1-...

# Set default model
raypaste config set default-model cerebras-llama-8b
Expand All @@ -230,7 +252,7 @@ raypaste config set default-model cerebras-llama-8b
raypaste config set default-length medium

# View current settings
raypaste config get api-key
raypaste config get cerebras-api-key
raypaste config get default-model
```

Expand Down Expand Up @@ -515,22 +537,32 @@ cat requirements.txt | raypaste "analyze these dependencies" -l medium
### API Key Not Found

```
Error: API key not found. Set RAYPASTE_API_KEY environment variable or add to config.yaml
Error: No API key configured. Set one of:
CEREBRAS_API_KEY - for direct Cerebras inference
OPENROUTER_API_KEY - for OpenRouter multi-provider access
Or run: raypaste config set cerebras-api-key <key>
```

**Solution**: The CLI looks for your API key in two places:
**Solution**: The CLI looks for API keys in these places:

1. **Environment Variable**: `RAYPASTE_API_KEY` must be exported in your current shell session
1. **Environment Variables**: `CEREBRAS_API_KEY` and/or `OPENROUTER_API_KEY`

```bash
export RAYPASTE_API_KEY=your_api_key_here
export CEREBRAS_API_KEY=your_cerebras_key
# or
export OPENROUTER_API_KEY=your_openrouter_key
```

2. **Config File**: `~/.raypaste/config.yaml` (note: this is in your home directory, not the project directory)
2. **Config Command** (recommended):

```bash
mkdir -p ~/.raypaste
cp config.yaml.example ~/.raypaste/config.yaml
# Edit the file and add your API key
raypaste config set cerebras-api-key your_key
```

3. **Config File**: `~/.raypaste/config.yaml` (note: this is in your home directory, not the project directory)
```yaml
cerebras_api_key: "your_key"
openrouter_api_key: "your_key"
```

**Common Issues**:
Expand All @@ -539,6 +571,7 @@ Error: API key not found. Set RAYPASTE_API_KEY environment variable or add to co
- Having `config.yaml` in the project directory won't work - the CLI looks in `~/.raypaste/config.yaml`
- Setting the variable without `export` won't work - it must be exported to be visible to the program
- You don't need to rebuild the executable after setting the API key
- If you previously used `RAYPASTE_API_KEY` with an OpenRouter key (`sk-or-*` prefix), it will still work but you'll see a migration notice

### Clipboard Not Working

Expand Down
Loading
Loading