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
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,74 @@ Learn more about the SDK [here](https://www.npmjs.com/package/@codebuff/sdk).

**SDK**: Build Codebuff into your applications. Create custom tools, integrate with CI/CD, or embed coding assistance into your products.

## Advanced Usage

### Custom Agent Workflows

Create your own agents with specialized workflows using the `/init` command:

```bash
codebuff
/init
```

This creates a custom agent structure in `.agents/` that you can customize.

### Using Different Models

Codebuff supports any model on OpenRouter. Override the default model per task:

```typescript
const result = await client.run({
agent: 'editor',
prompt: 'Refactor this function',
model: 'deepseek/deepseek-chat', // Use DeepSeek for this task
})
```

### Multi-Agent Orchestration

Codebuff's strength is coordinating multiple specialized agents:

```typescript
const result = await client.run({
agent: 'commander', // The orchestrator agent
prompt: 'Add authentication to the API - use file-picker to find relevant files, planner to plan changes, editor to make edits, and reviewer to validate',
})
```

### CI/CD Integration

Integrate Codebuff into your CI pipeline for automated code reviews:

```bash
# In your CI script
codebuff "Review the changes in this PR for security issues"
```

### Environment Variables

Configure Codebuff behavior via environment variables:

```bash
# Use a specific OpenRouter API key
export OPENROUTER_API_KEY=sk-or-v1-xxxx

# Set default model
export CODEBUFF_MODEL=anthropic/claude-3.5-sonnet

# Enable debug mode
export DEBUG=codebuff*
```

### Keyboard Shortcuts (Interactive Mode)

- `Ctrl+C` - Cancel current operation
- `Ctrl+L` - Clear screen
- `Ctrl+U` - Clear current input
- `Ctrl+P/N` - Navigate command history
- `Tab` - Autocomplete

## Contributing to Codebuff

We ❤️ contributions from the community - whether you're fixing bugs, tweaking our agents, or improving documentation.
Expand Down
3 changes: 2 additions & 1 deletion common/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { clientEnvSchema, clientProcessEnv } from './env-schema'

const parsedEnv = clientEnvSchema.safeParse(clientProcessEnv)
if (!parsedEnv.success) {
throw parsedEnv.error
console.error('Environment validation failed:', parsedEnv.error.errors)
throw new Error(`Invalid environment configuration: ${parsedEnv.error.message}`)
}

export const env = parsedEnv.data
Expand Down
13 changes: 11 additions & 2 deletions common/src/util/array.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { compact, flattenDeep, isEqual } from 'lodash'
// Native implementations replace lodash imports to reduce bundle size
// isEqual is kept from lodash for deep equality comparison

import isEqual from 'lodash/isEqual'

export function filterDefined<T>(array: (T | null | undefined)[]) {
return array.filter((item) => item !== null && item !== undefined) as T[]
Expand All @@ -8,7 +11,13 @@ type Falsey = false | undefined | null | 0 | ''
type FalseyValueArray<T> = T | Falsey | FalseyValueArray<T>[]

export function buildArray<T>(...params: FalseyValueArray<T>[]) {
return compact(flattenDeep(params)) as T[]
// Native implementation replaces lodash compact + flattenDeep
const flatten = <T>(arr: unknown): T[] => {
return Array.isArray(arr)
? arr.flatMap((item) => flatten<T>(item))
: [arr] as T[]
}
return flatten<T>(params).filter((item) => item != null) as T[]
}

export function groupConsecutive<T, U>(xs: T[], key: (x: T) => U) {
Expand Down
18 changes: 13 additions & 5 deletions common/src/util/object.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { isEqual, mapValues, union } from 'lodash'
import isEqual from 'lodash/isEqual'

// Using native implementations instead of lodash to reduce bundle size
// isEqual is kept from lodash as it handles deep equality complex cases

type RemoveUndefined<T extends object> = {
[K in keyof T as T[K] extends undefined ? never : K]: Exclude<T[K], undefined>
Expand Down Expand Up @@ -41,7 +44,8 @@ export const addObjects = <T extends { [key: string]: number }>(
obj1: T,
obj2: T,
): T => {
const keys = union(Object.keys(obj1), Object.keys(obj2))
// Native implementation replaces lodash union
const keys = [...new Set([...Object.keys(obj1), ...Object.keys(obj2)])]
const newObj: { [key: string]: number } = {}

for (const key of keys) {
Expand All @@ -55,7 +59,8 @@ export const subtractObjects = <T extends { [key: string]: number }>(
obj1: T,
obj2: T,
): T => {
const keys = union(Object.keys(obj1), Object.keys(obj2))
// Native implementation replaces lodash union
const keys = [...new Set([...Object.keys(obj1), ...Object.keys(obj2)])]
const newObj: { [key: string]: number } = {}

for (const key of keys) {
Expand All @@ -66,8 +71,11 @@ export const subtractObjects = <T extends { [key: string]: number }>(
}

export const hasChanges = <T extends object>(obj: T, partial: Partial<T>) => {
const currValues = mapValues(partial, (_, key: keyof T) => obj[key])
return !isEqual(currValues, partial)
// Native implementation replaces lodash mapValues
const currValues = Object.fromEntries(
Object.keys(partial).map((key) => [key, obj[key as keyof T]])
)
return JSON.stringify(currValues) !== JSON.stringify(partial)
}

export const hasSignificantDeepChanges = <T extends object>(
Expand Down
9 changes: 7 additions & 2 deletions common/src/util/string.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { sumBy } from 'lodash'
// Native implementation replaces lodash sumBy to reduce bundle size

export const truncateString = (str: string, maxLength: number) => {
if (str.length <= maxLength) {
Expand Down Expand Up @@ -46,7 +46,12 @@ export const truncateStringWithMessage = ({
export const isWhitespace = (character: string) => /\s/.test(character)

export const randBoolFromStr = (str: string) => {
return sumBy(str.split(''), (char) => char.charCodeAt(0)) % 2 === 0
// Native implementation replaces lodash sumBy
let sum = 0
for (const char of str.split('')) {
sum += char.charCodeAt(0)
}
return sum % 2 === 0
}

// Irregular plurals that cannot be derived from rules
Expand Down