AI Skill
Bell ships with a language reference designed to be fed directly to AI assistants so they can write correct .bel files.
Download or Copy
Or grab it from the CLI and pipe it wherever you need:
bash
bell skill # print to stdout
bell skill | pbcopy # macOS: copy to clipboard
bell skill | xclip # Linux: copy to clipboard
bell skill > bell-skill.md # save to a fileInstall as a Claude Code Slash Command
Install the skill as a project-level Claude Code slash command:
bash
bell skill --installThis writes the reference to .claude/commands/bell.md in your current directory. After that, type /bell in any Claude Code conversation in that project to load the full Bell language reference.
To install globally (available in all your Claude Code projects):
bash
bell skill --install --globalSkill Content
md
You are working with Bell, a DSL for describing and executing HTTP API requests.
Bell files use the `.bel` extension.
## Variables
Assign strings, numbers, or booleans to variables. Use `{varName}` to interpolate into strings.
```bel
apiKey = "my-secret-token"
userId = 42
active = true
url "https://api.example.com/users/{userId}"
header "Authorization" "Bearer {apiKey}"
GET
```
## Request Building
Build a request with these keywords before dispatching it with an HTTP method:
- `url "..."` — full base URL
- `path "..."` — appended to the base URL (use with environments)
- `param "key" value` — query parameter; or `param varName` to use a variable as both key and value
- `header "Key" "value"` — individual request header
- `headers { "Key": "value", ... }` — set all headers at once
- `body { ... }` — JSON request body (set with POST, PUT, PATCH)
## HTTP Methods
Write a method keyword to dispatch the currently built request:
```bel
url "https://api.example.com"
path "/users"
GET
path "/users"
body { "name": "Jane" }
POST
path "/users/42"
body { "name": "Jane Doe" }
PUT
path "/users/42"
body { "name": "Jane D." }
PATCH
path "/users/42"
DELETE
```
## Response
After a request, `response` is set. Bell keeps a history of all responses.
```bel
url "https://api.example.com/users"
GET
log response.status # HTTP status code
log response.body # full response body
log response.body.data.id # nested property
log response.headers # response headers
# Multiple requests: index past responses with response.[n]
url "https://api.example.com/posts"
POST
log response.[0].status # status of the GET above
log response.[1].body # body of the POST
```
## Logging
```bel
log response.body
log url
count = 42
log count
```
## User Interaction
`input("prompt")` — prompts the user at runtime; use as expression or inline:
```bel
id = input("Enter user ID")
param "id" id
url "https://api.example.com/posts"
body {
"title": input("Post title"),
"body": input("Post body")
}
POST
```
`warn` — asks for confirmation before continuing (stops execution if declined):
```bel
# As expression: returns the value if confirmed
prodUrl = warn "api.example.com"
url "https://{prodUrl}/users"
GET
# As statement: shows a message and waits
warn "You are about to delete a user. Proceed?"
url "https://api.example.com/users/42"
DELETE
```
## Guards and Assertions
`require expr` — pre-condition guard; stops before the request if falsy:
```bel
require token
require id
url "https://api.example.com/posts/{id}"
header "Authorization" "Bearer {token}"
DELETE
```
`expect expr` — checks a condition after a request, logs pass/fail, continues:
```bel
url "https://api.example.com/users"
GET
expect response.status === 200
expect response.body.data !== null
```
`assert expr` — like `expect`, but stops execution immediately if the check fails:
```bel
url "https://api.example.com/users"
GET
assert response.status === 200
assert response.body.id !== null
```
## Imports
```bel
# Named import from JSON
import requestBody from "./request-body.json"
# Named imports from TypeScript (types, schemas)
import { UserRequest, UserResponse } from "./types.ts"
# Anonymous import — loads an environment config or .env file
import "./env-config.json"
import "./.env"
```
## .env Files
Bell can load `.env` files. The special key `BELL_URL` sets the base URL.
```bash
# .env
BELL_URL=https://api.example.com
API_KEY=my-secret
```
```bel
import "./.env"
path "/users"
header "Authorization" "Bearer {API_KEY}"
GET
```
## Environments
Define environments in a JSON config:
```json
{
"dev": { "url": "https://dev.api.example.com", "version": "v1" },
"prod": { "url": "https://api.example.com", "version": "v2" }
}
```
```bel
import "./env-config.json"
env "dev" | "prod" # prompts the user to choose
# or: env "prod" # sets without prompting
path "/{version}/users"
GET
```
## Runtime Validation
`validate expr as TypeName` — checks that a value matches a TypeScript type at runtime:
```bel
import requestBody from "./request-body.json"
import { UserRequest, UserResponse } from "./types.ts"
validate requestBody as UserRequest
url "https://api.example.com/users"
body requestBody
POST
validate response.body as UserResponse
```
## Multi-file Workflows
`run "file.bel"` — runs another Bell file inline; exported variables become available:
```bel
# login.POST.bel
url "https://api.example.com/login"
body { "username": "user", "password": "pass" }
POST
token = response.body.token
export token
```
```bel
# main.bel
run "./login.POST.bel"
# token is now available from the sub-file
url "https://api.example.com/posts"
header "Authorization" "Bearer {token}"
GET
```
`export varName` or `export a, b, c` — marks variables to share with callers.
## Comments
```bel
# Single-line comment
#
# Multi-line comment block
#
```
## File Naming Convention
Files are conventionally named `<name>.<METHOD>.bel` (e.g. `login.POST.bel`, `users.GET.bel`).
This is conventional, not enforced by the runtime.
## CLI Quick Reference
```bash
bell run <file.bel> # run a file
bell run <file.bel> -e prod # run with environment
bell run <file.bel> --dry-run # validate without sending requests
bell run <file.bel> --retry 3 # retry failed requests up to 3 times
bell run <file.bel> --proxy http://proxy:8080 # route through a proxy
bell run <file.bel> --insecure # skip TLS verification
bell run <file.bel> --json # print last response body as JSON
bell run <file.bel> --output response.json # save last response body to file
bell <file.bel> # shorthand (no subcommand needed)
bell test # run all .bel files as test suite
bell test tests/ --reporter junit # JUnit XML output for CI
bell test tests/ --bail # stop on first failure
bell check <file.bel> # static analysis (JSON diagnostics)
bell init # create a starter bell/ folder
bell format <file.bel> # format a file
bell postman <collection.json> # convert Postman collection
bell openapi <spec.json|yaml> # convert OpenAPI 3.x spec to Bell files
bell curl '<curl command>' # convert a curl command to Bell
bell har <file.har> # convert a HAR export to Bell files
bell config # show merged Bell config
bell skill # print this skill reference
bell skill --install # install as Claude Code slash command
```