Skip to content
Back to skills

Skill

ASecurity

url "https://api.example.com/posts" POST log response.[0].status # status of the GET above log response.[1].body # body of the POST ```

  • 3 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 26, 2026
developmenttypescriptbashexpressapi

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add pjflanagan/bell --skill skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pjflanagan-skill/badge)](https://www.skillsdirectory.com/skills/pjflanagan-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.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
```

Files in this skill

  • bell-skill.md6.6 KB
  • bellSkill.ts161 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.