Skip to content

Getting Started ​

Crush is awesome! You should use it.

It's by charm.land.

Crush's installation instructions are easy to follow.

Do that first.

Crush's Configuration Explained ​

Charm is great. Sadly, they did not do a good job explaining to me how to configure json.

They said:

json
{
  "this-setting": { "this": "that" },
  "that-setting": ["ceci", "cela"]
}

Many words, few instructions.

The point is that the config is mad flexible, but... ... it doesn't say what the default expectations are.

LSP ​

I don't know how the LSPs work, still :3

MCPs ​

I played with this a little more.

The example Charm gives is:

json
{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "filesystem": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/mcp-server.js"],
      "timeout": 120,
      "disabled": false,
      "env": {
        "NODE_ENV": "production"
      }
    },
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "timeout": 120,
      "disabled": false,
      "headers": {
        "Authorization": "Bearer $GH_PAT"
      }
    },
    "streaming-service": {
      "type": "sse",
      "url": "https://example.com/mcp/sse",
      "timeout": 120,
      "disabled": false,
      "headers": {
        "API-Key": "$(echo $API_KEY)"
      }
    }
  }
}

This is a good start, but it doesn't totally explain the big ideas here.

A crush.json isn't complete just by adding an mcp field - you want to add some others, too.

I run NixOS.

Sorry pal, I get that you run Arch, very cool, but I run NixOS.

I am not a computer genius so I have no earthly idea how to use environment variables.

Typically, they go onto your PATH, a config somewhere on your puter that your terminal consumes.

Nix doesn't do that.

If you know how to deal with ENV vars in NixOS, that's very cool.

I just paste my keys into the crush.json files and add them to .gitignore.

Working Example ​

Here's an example that worked for me:

json
{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "context7": {
      "type": "http",
      "url": "https://mcp.context7.com/mcp",
      "timeout": 120,
      "disabled": false,
      "headers": {
        "CONTEXT7_API_KEY": "~"
      }
    }
  },
  "tools": {
    "ls": { "max_items": 1000 }
  },
  "permissions": {
    "allowed_tools": [
      "view",
      "ls",
      "grep",
      "mcp_context7_get-library-doc",
      "mcp_context7_resolve-library-id"
    ]
  }
}

Crush couldn't see the mcp until I added this seemingly unrelated tools object.

Permissions ​

The Permissions key in the example:

json
{
  "$schema": "https://charm.land/crush.json",
  "mcp": {
    "context7": {
      "type": "http",
      "url": "https://mcp.context7.com/mcp",
      "timeout": 120,
      "disabled": false,
      "headers": {
        "CONTEXT7_API_KEY": "~"
      }
    }
  },
  "tools": {
    "ls": { "max_items": 1000 }
  },
  "permissions": {
    "allowed_tools": [
      "view",
      "ls",
      "grep",
      "mcp_context7_get-library-doc",
      "mcp_context7_resolve-library-id"
    ]
  }
}

Basically turns those specific commands into yolo-mode. They run without your input.

In this case, we've enabled:

  • view (reading files)
  • ls (listing directory children)
  • grep (search)
  • mcp_context7_get-library-doc (like view but through context7)
  • mcp_context7_resolve-library-id (like search but for context7)

WARNING

I strongly recommend not including edit, write, and bash in the allowed tools unless you're running a benchmark.

INFO

Why?

I'm not a computer genius, idk if you are or aren't, but for me, agentic coding agents f*ck up like... all the time.

Every single edit or write command an AI agent has literally ever written in front of me was broken somehow.

These errors compound.

I notice this when I'm not even a computer genius. Maybe I prompt badly. Maybe my architectures are naive. Maybe LLMs just have a sub 100% error rate like any other intelligence ever and aren't perfect.

Maybe agentic coding is just a scam invented by Big AI to sell more tokens.

Regardless - it's way harder to unf*ck a repo after a half hour of broken writes that to unfuck it as you go.

bash lets these commands compound even faster. That's how you get:

bash
# I need to resolve the failing test. Let's start from fresh.
rm -rf *