MCPcopy Index your code
hub / github.com/amterp/rad

github.com/amterp/rad @v0.11.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.11.0 ↗ · + Follow
3,157 symbols 11,982 edges 289 files 1,302 documented · 41%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

🤙 Rad

Latest Release Docs Go Report Card License

Bash is powerful but painful. Rad gives you Python-like scripting with CLI essentials built-in.

Write maintainable scripts with declarative argument parsing, built-in JSON processing, HTTP requests, and interactive user prompts - all in a familiar, readable syntax.

The Problem with Bash

bash-example.png

What you actually want:

vsc-example.png

You get this for free:

> ./greet --help
Greets someone by name, potentially a lot of times!

Usage:
  greet <name> [times] [shout] [greeting]

Script args:
      --name str          Name of the person to greet.
      --times int         How many times to greet them. Range: (0, 10] (default 1)
  -s, --shout             Enable to shout at them!
      --greeting str      How to greet the person. Valid values: [Hi, Hello, Hey]. (default Hi)
> ./greet bob 3 -s
HI, BOB!
HI, BOB!
HI, BOB!

Why Rad? 🚀

  • CLI-first design → Args, validation, and --help are part of the language
  • Familiar syntax → Python-like, readable, no Bash footguns
  • Declarative arguments → Automatic --help, type checking, validation, and parsing
  • JSON made easy → Simple paths for extraction and tabular output
  • HTTP built-in → Query APIs, process results, and render tables in a few lines
  • Interactive promptspick(), input(), etc, for user input & selection menus
  • Shell when you want it → Run commands and capture output

Real-World Example: API to Table

Fetch and display GitHub commits in one, minimal script:

#!/usr/bin/env rad
args:
    repo str        # The repo to query. Format: user/project
    limit int = 20  # Max commits to return

url = "https://api.github.com/repos/{repo}/commits?per_page={limit}"

Time = json[].commit.author.date
Author = json[].commit.author.name
SHA = json[].sha

rad url:
    fields Time, Author, SHA

Put this commits script on your PATH, and invoke:

> commits spf13/cobra 3
Querying url: https://api.github.com/repos/spf13/cobra/commits?per_page=3
Time                  Author          SHA
2025-03-07T14:53:22Z  styee           4f9ef8cdbbc88c5302be95e0e67fd78ebbfa9dd2
2025-02-21T12:46:14Z  Fraser Waters   1995054b003053cc1e404bccfbf6d168e8731509
2025-02-17T19:16:17Z  Yedaya Katsman  f98cf4216d3cb5235e6e0cd00ee00959deb1dc65

No curl | jq | awk gymnastics. No argparse boilerplate. Just readable code that does what you want.

Explaining the above script:

  1. The script takes two args: a repo string and an optional limit (defaults to 20).
    • The # comments are read by Rad and used to generate helpful docs / usage strings for the script.
  2. It uses string interpolation to build the url we will query, based on the supplied args.
  3. It defines the fields to extract from the JSON response.
  4. It executes the query, extracting the specified fields from the response, and displays the resulting data as a table.
    • The rad url: syntax fetches JSON from the URL, extracts data into the defined fields, and displays the result as a table.

This example is kept somewhat minimal - there are Rad features we could use to further improve this.

Some alternative valid invocations for this example:

  • > commits amterp/rad
  • > commits --repo amterp/rad --limit 5
  • > commits --limit 5 --repo amterp/rad
  • > commits amterp/rad --limit 5

Quick Comparison 📊

Feature Bash Python Rad
Syntax familiarity Archaic, hard to remember Familiar Familiar (Python-like)
Argument parsing Verbose, manual argparse or libraries Built-in; declarative
Type checking None Manual or library Built-in
--help generation Manual Dependencies handle it Built in; auto from comments
Validation/constraints Manual Manual or library schemas Built-in (range, enum, etc)
JSON processing Pipe to jq JSON module + manual handling Built-in path syntax
String interpolation "${var}" (pitfalls) f-strings "{var}"
HTTP requests curl + pipes Import requests Built-in; first-class support
Dependencies None, but limited Likely need libraries None - batteries included
Lines of code Many Moderate Minimal

Python note: Libraries like typer and click make CLI tools easier, but Rad goes further. CLI is designed into the language syntax itself, allowing us to do things and achieve ergonomics that Python libraries simply can't. Plus, no dependency management needed.

Installation 🛠️

macOS (Homebrew)

brew install rad

Go (from source, all platforms)

go install github.com/amterp/rad@latest
go install github.com/amterp/rad/radls@latest

The first command installs rad (the interpreter). The second installs radls (the language server for editor support).

Note: You will need to run go install yourself to upgrade Rad as new versions are released. For automated updates, use one of the supported package managers that allow it.

Binary Downloads

Pre-built binaries for macOS, Linux, and Windows: releases page

Each release archive includes both rad and radls.

Editor Support

VS Code Extension provides syntax highlighting and real-time diagnostics via the Rad Language Server (radls).

The extension requires radls to be on your PATH (installed automatically via Homebrew or go install).

Documentation 📚

Getting Started Guide | Full Documentation

Once installed, rad docs gives you the full documentation right in your terminal - no browser needed:

rad docs                 # list all topics
rad docs guide/basics    # read a specific page
rad docs len             # look up a built-in function
rad docs RAD20003        # explain an error code

Project Status 🚧

Rad is in early development but useful today for real scripts.

What this means:

  • ✅ Core features work well
  • ✅ Actively maintained and improving
  • ⚠️ Breaking changes between versions
  • ⚠️ Rough edges and missing features

The upside: Your feedback directly shapes the language. Feature requests and bug reports are not just welcomed - they're invaluable!

Give it a try and let me know what you think!

Why not Rad? 🤔

Rad is optimized for CLI scripting, so if you find yourself building any of the following, a general-purpose language (Python, Go, Rust, etc) may be more appropriate:

  • Enterprise applications
  • High-performance computations
  • Projects requiring specialized libraries

Why I Built This

I love Bash for quick scripts. But every time I need to parse arguments properly, validate input, or work with JSON, I end up writing the same painful boilerplate.

Python is great, but for a simple CLI tool, you shouldn't need argparse, dependencies, and subprocess.run() before you even start solving your actual problem.

Rad is the language I wish existed when I started writing scripts. It takes the best parts of modern languages and adds purpose-built features for CLI scripting.


Try Rad for your next script. I think you'll like it. 🤙

Installation | Docs | Contributing

Extension points exported contracts — how you extend this code

Doc (Interface)
Doc is the sealed document IR. Every node kind implements isDoc. Construct formatters assemble a Doc tree; render.go tur [13 …
rts/radfmt/doc.go
TypingT (Interface)
TypingT is the representation of a Rad type annotation. Each implementation provides three things: Name() [22 implementers]
rts/rl/typing.go
InteractiveDriver (Interface)
InteractiveDriver runs a radish prompt Model to completion. Production wraps the real terminal; tests inject a scripted [7 …
core/interactive.go
Block (Interface)
Block is one structural element of a parsed doc. [5 implementers]
tools/docir/block.go
SignalSource (Interface)
SignalSource is the seam between the SignalManager and the OS signal machinery. The production implementation wraps os/s [2 …
core/signals.go
ArgPrompter (Interface)
ArgPrompter abstracts the prompt shapes the --interactive walk needs, so the walk logic is unit-testable with a fake. Th [2 …
core/interactive_args.go
Printer (Interface)
todo make global instance, rather than passing into everything For all output to the user, except perhaps pflag-handled [1 …
core/printer.go
ReplSession (Interface)
Core REPL contracts and interfaces following maintainability-first design ReplSession represents the main REPL session c [1 …
core/repl_session.go

Core symbols most depended-on inside this repo

Name
called by 214
rts/rl/typing.go
Return
called by 167
core/funcs.go
setupAndRunCode
called by 149
core/testing/test_helpers.go
Plain
called by 148
core/type_string.go
assertNoErrors
called by 139
core/testing/test_helpers.go
Contains
called by 123
core/type_list.go
String
called by 107
core/diagnostic.go
Join
called by 101
core/type_list.go

Shape

Function 1,653
Method 1,121
Struct 333
TypeAlias 31
Interface 16
FuncType 3

Languages

Go100%
Python1%
TypeScript1%

Modules by API surface

rts/rl/ast_types.go212 symbols
rts/check/type_check.go127 symbols
rts/rl/typing.go115 symbols
rts/check/type_check_test.go106 symbols
core/args.go92 symbols
rts/converter.go80 symbols
core/interpreter.go62 symbols
rts/converter_test.go58 symbols
rts/rl/ast_children.go46 symbols
core/type_rad_value.go44 symbols
core/interactive_args.go44 symbols
radls/lsp/text_doc.go43 symbols

For agents

$ claude mcp add rad \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact