How It Works

A .md file goes in. Working automation comes out. Here's what happens in between.

Anatomy of a .md file

There are three parts. Only the shebang and the prompt are required.

example.md
#!/usr/bin/env think        ← shebang
---
model: claude-haiku-4-5-20251001      ← frontmatter (optional)
max_tokens: 4096
---

Your natural language prompt      ← prompt
goes here. As long or short
as you need.
Shebang

#!/usr/bin/env think tells your shell to run the file through the think interpreter.

Frontmatter

Optional YAML between --- fences. Set the model, max tokens, and other config here.

Prompt

Everything after the frontmatter. Plain English instructions for what you want done.

The agent loop

When you run a .md file, the interpreter kicks off a loop. The LLM reads your prompt, decides which tools to call, and keeps going until the job is done.

Parse

Script → frontmatter + prompt

Configure

Env vars → frontmatter → config → defaults

Send

Prompt → LLM with tool descriptions

Execute

LLM calls tools, you approve, results loop back

Done

LLM stops calling tools, script exits

The tools

The LLM has five tools. That's it. Small, focused, composable.

write_stdout

Write text to stdout. The only way to produce output.

No approval
run_command

Execute a shell command.

Requires approval
read_stdin

Read piped input data.

No approval
read_env

Read an environment variable.

Requires approval
set_argument

Register a named value for pattern matching.

Requires approval

The approval system

Every sensitive action shows you exactly what's happening and asks before proceeding.

Approval prompt
 run_command(weather.md)

  $ curl https://api.weather.gov/points/37.7749,-122.4194

 Yes
  Always
  No
Yes
Approve once

Allow this action for this run only.

Always
Remember it

Auto-approve across runs. Invalidated if the script changes.

No
Deny

Reject the action. The LLM adapts and tries another approach.

Pattern-based approval

This is where it gets interesting. When a command contains a named argument, you get a fourth option.

Approval prompt
 run_command(weather.md)

  $ curl https://api.weather.gov/points/37.7749,-122.4194

 Yes
  Always
  Always similar (curl {Location})   ← 🤯
  No

Approve the pattern once, and future runs with different locations auto-match. Pretty cool right?

stdout is sacred

This is the key design principle. Only write_stdout writes to stdout. Everything else (debug output, approval prompts, status) goes to stderr. This makes scripts composable.

Terminal
$ cat data.csv | think process.md | think format.md > output.json

This means you can compose scripts like any other Unix tool.

Terminal
$ cat raw-data.csv \
    | think clean.md \
    | think analyze.md \
    | think format-report.md > report.md

Install them all and it gets even cleaner.

Terminal
$ cat raw-data.csv | clean | analyze | format-report > report.md

Pipes, redirects, shebangs — it all works. .md files are first-class citizens in your pipeline.

Configuration

Config is resolved in order of precedence. Higher wins.

Environment variables THINKINGSCRIPT__MODEL, THINKINGSCRIPT__MAX_TOKENS, etc.
Script frontmatter YAML in the script itself
Config file ~/.thinkingscript/config.yaml
Defaults Built into the binary

You'll need an Anthropic API key set as ANTHROPIC_API_KEY in your environment.

Two binaries

think

The interpreter. Runs .md scripts.

thought

Management tool. Build, install, cache, and inspect scripts.

Install scripts to your PATH

Use thought install to copy a built script to ~/.thinkingscript/thoughts/. Add that directory to your PATH and you can run any installed script by name.

Terminal
$ thought install weather.md
$ weather "San Francisco"
San Francisco, CA
62°F, partly cloudy. Wind: 12 mph W. Humidity: 68%.