Detailed changes
@@ -43,17 +43,17 @@ curl -fsSL https://raw.githubusercontent.com/charmbracelet/crush/refs/heads/main
### Using Homebrew (macOS and Linux)
```bash
-brew install opencode-ai/tap/opencode
+brew install crush-ai/tap/crush
```
### Using AUR (Arch Linux)
```bash
# Using yay
-yay -S opencode-ai-bin
+yay -S crush-ai-bin
# Using paru
-paru -S opencode-ai-bin
+paru -S crush-ai-bin
```
### Using Go
@@ -66,9 +66,9 @@ go install github.com/charmbracelet/crush@latest
OpenCode looks for configuration in the following locations:
-- `$HOME/.opencode.json`
-- `$XDG_CONFIG_HOME/opencode/.opencode.json`
-- `./.opencode.json` (local directory)
+- `$HOME/.crush.json`
+- `$XDG_CONFIG_HOME/crush/.crush.json`
+- `./.crush.json` (local directory)
### Auto Compact Feature
@@ -130,7 +130,7 @@ This is useful if you want to use a different shell than your default system she
```json
{
"data": {
- "directory": ".opencode"
+ "directory": ".crush"
},
"providers": {
"openai": {
@@ -248,13 +248,13 @@ OpenCode supports a variety of AI models from different providers:
```bash
# Start OpenCode
-opencode
+crush
# Start with debug logging
-opencode -d
+crush -d
# Start with a specific working directory
-opencode -c /path/to/project
+crush -c /path/to/project
```
## Non-interactive Prompt Mode
@@ -263,13 +263,13 @@ You can run OpenCode in non-interactive mode by passing a prompt directly as a c
```bash
# Run a single prompt and print the AI's response to the terminal
-opencode -p "Explain the use of context in Go"
+crush -p "Explain the use of context in Go"
# Get response in JSON format
-opencode -p "Explain the use of context in Go" -f json
+crush -p "Explain the use of context in Go" -f json
# Run without showing the spinner (useful for scripts)
-opencode -p "Explain the use of context in Go" -q
+crush -p "Explain the use of context in Go" -q
```
In this mode, OpenCode will process your prompt, print the result to standard output, and then exit. All permissions are auto-approved for the session.
@@ -419,26 +419,26 @@ Custom commands are predefined prompts stored as Markdown files in one of three
1. **User Commands** (prefixed with `user:`):
```
- $XDG_CONFIG_HOME/opencode/commands/
+ $XDG_CONFIG_HOME/crush/commands/
```
- (typically `~/.config/opencode/commands/` on Linux/macOS)
+ (typically `~/.config/crush/commands/` on Linux/macOS)
or
```
- $HOME/.opencode/commands/
+ $HOME/.crush/commands/
```
2. **Project Commands** (prefixed with `project:`):
```
- <PROJECT DIR>/.opencode/commands/
+ <PROJECT DIR>/.crush/commands/
```
Each `.md` file in these directories becomes a custom command. The file name (without extension) becomes the command ID.
-For example, creating a file at `~/.config/opencode/commands/prime-context.md` with content:
+For example, creating a file at `~/.config/crush/commands/prime-context.md` with content:
```markdown
RUN git ls-files
@@ -472,7 +472,7 @@ When you run a command with arguments, OpenCode will prompt you to enter values
You can organize commands in subdirectories:
```
-~/.config/opencode/commands/git/commit.md
+~/.config/crush/commands/git/commit.md
```
This creates a command with ID `user:git:commit`.
@@ -614,13 +614,13 @@ You can also configure a self-hosted model in the configuration file under the `
```bash
# Clone the repository
git clone https://github.com/charmbracelet/crush.git
-cd opencode
+cd crush
# Build
-go build -o opencode
+go build -o crush
# Run
-./opencode
+./crush
```
## Acknowledgments
@@ -21,29 +21,29 @@ import (
)
var rootCmd = &cobra.Command{
- Use: "opencode",
+ Use: "crush",
Short: "Terminal-based AI assistant for software development",
Long: `OpenCode is a powerful terminal-based AI assistant that helps with software development tasks.
It provides an interactive chat interface with AI capabilities, code analysis, and LSP integration
to assist developers in writing, debugging, and understanding code directly from the terminal.`,
Example: `
# Run in interactive mode
- opencode
+ crush
# Run with debug logging
- opencode -d
+ crush -d
# Run with debug logging in a specific directory
- opencode -d -c /path/to/project
+ crush -d -c /path/to/project
# Print version
- opencode -v
+ crush -v
# Run a single non-interactive prompt
- opencode -p "Explain the use of context in Go"
+ crush -p "Explain the use of context in Go"
# Run a single non-interactive prompt with JSON output format
- opencode -p "Explain the use of context in Go" -f json
+ crush -p "Explain the use of context in Go" -f json
`,
RunE: func(cmd *cobra.Command, args []string) error {
// If the help flag is set, show the help message
@@ -5,7 +5,7 @@ This tool generates a JSON Schema for the OpenCode configuration file. The schem
## Usage
```bash
-go run cmd/schema/main.go > opencode-schema.json
+go run cmd/schema/main.go > crush-schema.json
```
This will generate a JSON Schema file that can be used to validate configuration files.
@@ -24,7 +24,7 @@ The generated schema includes:
You can use the generated schema in several ways:
-1. **Editor Integration**: Many editors (VS Code, JetBrains IDEs, etc.) support JSON Schema for validation and autocompletion. You can configure your editor to use the generated schema for `.opencode.json` files.
+1. **Editor Integration**: Many editors (VS Code, JetBrains IDEs, etc.) support JSON Schema for validation and autocompletion. You can configure your editor to use the generated schema for `.crush.json` files.
2. **Validation Tools**: You can use tools like [jsonschema](https://github.com/Julian/jsonschema) to validate your configuration files against the schema.
@@ -37,7 +37,7 @@ Here's an example configuration that conforms to the schema:
```json
{
"data": {
- "directory": ".opencode"
+ "directory": ".crush"
},
"debug": false,
"providers": {
@@ -52,7 +52,7 @@ func generateSchema() map[string]any {
"directory": map[string]any{
"type": "string",
"description": "Directory where application data is stored",
- "default": ".opencode",
+ "default": ".crush",
},
},
"required": []string{"directory"},
@@ -89,8 +89,8 @@ func generateSchema() map[string]any {
".cursor/rules/",
"CLAUDE.md",
"CLAUDE.local.md",
- "opencode.md",
- "opencode.local.md",
+ "crush.md",
+ "crush.local.md",
"OpenCode.md",
"OpenCode.local.md",
"OPENCODE.md",
@@ -105,9 +105,9 @@ func generateSchema() map[string]any {
"theme": map[string]any{
"type": "string",
"description": "TUI theme name",
- "default": "opencode",
+ "default": "crush",
"enum": []string{
- "opencode",
+ "crush",
"catppuccin",
"dracula",
"flexoki",
@@ -1 +1 @@
-{"flagWords":[],"language":"en","words":["opencode","charmbracelet","lipgloss","bubbletea","textinput","Focusable","lsps","Sourcegraph","filepicker","imageorient","rasterx","oksvg","termenv","trashhalo","lucasb","nfnt","srwiley","Lanczos"],"version":"0.2"}
+{"flagWords":[],"language":"en","words":["crush","charmbracelet","lipgloss","bubbletea","textinput","Focusable","lsps","Sourcegraph","filepicker","imageorient","rasterx","oksvg","termenv","trashhalo","lucasb","nfnt","srwiley","Lanczos"],"version":"0.2"}
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
-APP=opencode
+APP=crush
RED='\033[0;31m'
GREEN='\033[0;32m'
@@ -36,7 +36,7 @@ case "$filename" in
;;
esac
-INSTALL_DIR=$HOME/.opencode/bin
+INSTALL_DIR=$HOME/.crush/bin
mkdir -p "$INSTALL_DIR"
if [ -z "$requested_version" ]; then
@@ -67,12 +67,12 @@ print_message() {
}
check_version() {
- if command -v opencode >/dev/null 2>&1; then
- opencode_path=$(which opencode)
+ if command -v crush >/dev/null 2>&1; then
+ crush_path=$(which crush)
## TODO: check if version is installed
- # installed_version=$(opencode version)
+ # installed_version=$(crush version)
installed_version="0.0.1"
installed_version=$(echo $installed_version | awk '{print $2}')
@@ -86,11 +86,11 @@ check_version() {
}
download_and_install() {
- print_message info "Downloading ${ORANGE}opencode ${GREEN}version: ${YELLOW}$specific_version ${GREEN}..."
- mkdir -p opencodetmp && cd opencodetmp
+ print_message info "Downloading ${ORANGE}crush ${GREEN}version: ${YELLOW}$specific_version ${GREEN}..."
+ mkdir -p crushtmp && cd crushtmp
curl -# -L $url | tar xz
- mv opencode $INSTALL_DIR
- cd .. && rm -rf opencodetmp
+ mv crush $INSTALL_DIR
+ cd .. && rm -rf crushtmp
}
check_version
@@ -102,9 +102,9 @@ add_to_path() {
local command=$2
if [[ -w $config_file ]]; then
- echo -e "\n# opencode" >> "$config_file"
+ echo -e "\n# crush" >> "$config_file"
echo "$command" >> "$config_file"
- print_message info "Successfully added ${ORANGE}opencode ${GREEN}to \$PATH in $config_file"
+ print_message info "Successfully added ${ORANGE}crush ${GREEN}to \$PATH in $config_file"
else
print_message warning "Manually add the directory to $config_file (or similar):"
print_message info " $command"
@@ -97,9 +97,9 @@ type Config struct {
// Application constants
const (
- defaultDataDirectory = ".opencode"
+ defaultDataDirectory = ".crush"
defaultLogLevel = "info"
- appName = "opencode"
+ appName = "crush"
MaxTokensFallbackDefault = 4096
)
@@ -110,8 +110,8 @@ var defaultContextPaths = []string{
".cursor/rules/",
"CLAUDE.md",
"CLAUDE.local.md",
- "opencode.md",
- "opencode.local.md",
+ "crush.md",
+ "crush.local.md",
"OpenCode.md",
"OpenCode.local.md",
"OPENCODE.md",
@@ -221,7 +221,7 @@ func configureViper() {
func setDefaults(debug bool) {
viper.SetDefault("data.directory", defaultDataDirectory)
viper.SetDefault("contextPaths", defaultContextPaths)
- viper.SetDefault("tui.theme", "opencode")
+ viper.SetDefault("tui.theme", "crush")
viper.SetDefault("autoCompact", true)
// Set default shell from environment or fallback to /bin/bash
@@ -23,7 +23,7 @@ func Connect() (*sql.DB, error) {
if err := os.MkdirAll(dataDir, 0o700); err != nil {
return nil, fmt.Errorf("failed to create data directory: %w", err)
}
- dbPath := filepath.Join(dataDir, "opencode.db")
+ dbPath := filepath.Join(dataDir, "crush.db")
// Open the SQLite database
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
@@ -67,7 +67,7 @@ func SkipHidden(path string) bool {
}
commonIgnoredDirs := map[string]bool{
- ".opencode": true,
+ ".crush": true,
"node_modules": true,
"vendor": true,
"dist": true,
@@ -64,7 +64,7 @@ var CommonIgnorePatterns = []string{
".fseventsd",
// OpenCode
- ".opencode",
+ ".crush",
}
type DirectoryLister struct {
@@ -33,7 +33,7 @@ You can:
- Apply patches, run commands, and manage user approvals based on policy.
- Work inside a sandboxed, git-backed workspace with rollback support.
- Log telemetry so sessions can be replayed or inspected later.
-- More details on your functionality are available at "opencode --help"
+- More details on your functionality are available at "crush --help"
You are an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved. If you are not sure about file content or codebase structure pertaining to the user's request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.
@@ -156,7 +156,7 @@ The user will primarily request you perform software engineering tasks. This inc
1. Use the available search tools to understand the codebase and the user's query.
2. Implement the solution using all tools available to you
3. Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.
-4. VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to opencode.md so that you will know to run it next time.
+4. VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask the user for the command to run and if they supply it, proactively suggest writing it to crush.md so that you will know to run it next time.
NEVER commit changes unless the user explicitly asks you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise the user will feel that you are being too proactive.
@@ -130,7 +130,7 @@ func NewProvider(providerName models.ModelProvider, opts ...ProviderClientOption
clientOptions.openaiOptions = append(clientOptions.openaiOptions,
WithOpenAIBaseURL("https://openrouter.ai/api/v1"),
WithOpenAIExtraHeaders(map[string]string{
- "HTTP-Referer": "opencode.ai",
+ "HTTP-Referer": "crush.ai",
"X-Title": "OpenCode",
}),
)
@@ -122,16 +122,16 @@ When the user asks you to create a new git commit, follow these steps carefully:
</commit_analysis>
4. Create the commit with a message ending with:
-🤖 Generated with opencode
-Co-Authored-By: opencode <noreply@opencode.ai>
+🤖 Generated with crush
+Co-Authored-By: crush <noreply@crush.ai>
- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:
<example>
git commit -m "$(cat <<'EOF'
Commit message here.
- 🤖 Generated with opencode
- Co-Authored-By: opencode <noreply@opencode.ai>
+ 🤖 Generated with crush
+ Co-Authored-By: crush <noreply@crush.ai>
EOF
)"
</example>
@@ -193,7 +193,7 @@ gh pr create --title "the pr title" --body "$(cat <<'EOF'
## Test plan
[Checklist of TODOs for testing the pull request...]
-🤖 Generated with opencode
+🤖 Generated with crush
EOF
)"
</example>
@@ -152,7 +152,7 @@ func (t *fetchTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error
return ToolResponse{}, fmt.Errorf("failed to create request: %w", err)
}
- req.Header.Set("User-Agent", "opencode/1.0")
+ req.Header.Set("User-Agent", "crush/1.0")
resp, err := client.Do(req)
if err != nil {
@@ -149,10 +149,10 @@ func (s *PersistentShell) execCommand(command string, timeout time.Duration, ctx
}
tempDir := os.TempDir()
- stdoutFile := filepath.Join(tempDir, fmt.Sprintf("opencode-stdout-%d", time.Now().UnixNano()))
- stderrFile := filepath.Join(tempDir, fmt.Sprintf("opencode-stderr-%d", time.Now().UnixNano()))
- statusFile := filepath.Join(tempDir, fmt.Sprintf("opencode-status-%d", time.Now().UnixNano()))
- cwdFile := filepath.Join(tempDir, fmt.Sprintf("opencode-cwd-%d", time.Now().UnixNano()))
+ stdoutFile := filepath.Join(tempDir, fmt.Sprintf("crush-stdout-%d", time.Now().UnixNano()))
+ stderrFile := filepath.Join(tempDir, fmt.Sprintf("crush-stderr-%d", time.Now().UnixNano()))
+ statusFile := filepath.Join(tempDir, fmt.Sprintf("crush-status-%d", time.Now().UnixNano()))
+ cwdFile := filepath.Join(tempDir, fmt.Sprintf("crush-cwd-%d", time.Now().UnixNano()))
defer func() {
os.Remove(stdoutFile)
@@ -218,7 +218,7 @@ func (t *sourcegraphTool) Run(ctx context.Context, call ToolCall) (ToolResponse,
}
req.Header.Set("Content-Type", "application/json")
- req.Header.Set("User-Agent", "opencode/1.0")
+ req.Header.Set("User-Agent", "crush/1.0")
resp, err := client.Do(req)
if err != nil {
@@ -54,7 +54,7 @@ func RecoverPanic(name string, cleanup func()) {
// Create a timestamped panic log file
timestamp := time.Now().Format("20060102-150405")
- filename := fmt.Sprintf("opencode-panic-%s-%s.log", name, timestamp)
+ filename := fmt.Sprintf("crush-panic-%s-%s.log", name, timestamp)
file, err := os.Create(filename)
if err != nil {
@@ -233,7 +233,7 @@ func (c *commandDialogCmp) defaultCommands() []Command {
2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
- If there's already a opencode.md, improve it.
+ If there's already a crush.md, improve it.
If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them.`
return tea.Batch(
util.CmdHandler(chat.SendMsg{
@@ -56,7 +56,7 @@ func buildCommandSources(cfg *config.Config) []commandSource {
// Home directory
if home, err := os.UserHomeDir(); err == nil {
sources = append(sources, commandSource{
- path: filepath.Join(home, ".opencode", "commands"),
+ path: filepath.Join(home, ".crush", "commands"),
prefix: UserCommandPrefix,
})
}
@@ -78,7 +78,7 @@ func getXDGCommandsDir() string {
}
}
if xdgHome != "" {
- return filepath.Join(xdgHome, "opencode", "commands")
+ return filepath.Join(xdgHome, "crush", "commands")
}
return ""
}
@@ -216,8 +216,8 @@
".cursor/rules/",
"CLAUDE.md",
"CLAUDE.local.md",
- "opencode.md",
- "opencode.local.md",
+ "crush.md",
+ "crush.local.md",
"OpenCode.md",
"OpenCode.local.md",
"OPENCODE.md",
@@ -233,7 +233,7 @@
"description": "Storage configuration",
"properties": {
"directory": {
- "default": ".opencode",
+ "default": ".crush",
"description": "Directory where application data is stored",
"type": "string"
}
@@ -374,10 +374,10 @@
"description": "Terminal User Interface configuration",
"properties": {
"theme": {
- "default": "opencode",
+ "default": "crush",
"description": "TUI theme name",
"enum": [
- "opencode",
+ "crush",
"catppuccin",
"dracula",
"flexoki",