Skip to content

Latest commit

 

History

History
777 lines (600 loc) · 15.1 KB

File metadata and controls

777 lines (600 loc) · 15.1 KB

Stim API Reference

Complete reference for Stim syntax, functions, and features.

Table of Contents

  1. Declarations
  2. Agent Metadata
  3. Prose
  4. Variables
  5. Control Flow
  6. Built-in Functions
  7. Tasks and Parallelism
  8. Operators
  9. Comments
  10. Targets
  11. Compilation Output

Declarations

Every Stim file contains exactly one top-level declaration. There are two kinds: command and agent.

Command Declaration

Interactive workflow invoked by the user.

command name {
  // Command body
}

Rules:

  • Names must be valid identifiers (letters, numbers, underscore)
  • Names cannot start with numbers
  • Compiles to /name (Claude Code slash command) by default
command hello { }           // Valid: /hello
command deploy_app { }      // Valid: /deploy_app
command 123invalid { }      // Invalid: starts with number

Agent Declaration

Static persona with metadata, invoked by the AI tool itself.

agent name {
  description "..."
  tools [A, B, C]
  model "..."

  "Prose line one."
  "Prose line two."
}

Rules:

  • Same naming rules as commands
  • Compiles to @name (Claude Code agent) by default
  • Metadata fields (description, tools, model) must come before other statements

See Agents for the full deep-dive.

Body

The body of either declaration contains zero or more statements:

command example {
  statement1()
  statement2()
}

agent example {
  description "..."
  "Prose statement."
  if (condition) {
    "Conditional prose."
  }
}

Agent Metadata

Only valid inside agent declarations. All fields are optional; each may appear at most once; all must come before non-metadata statements.

Field Type Purpose
description string One-line summary of the agent's role
tools array of identifiers Tools the agent is allowed to call (Claude-specific)
model string Preferred model (opus, sonnet, haiku) — Claude-specific
agent reviewer {
  description "Reviews PRs for security issues"
  tools [Read, Grep, Bash]
  model "sonnet"

  "You are a security engineer."
}

Fields a target doesn't understand are warn-and-dropped. See Targets.

Prose

Bare string literals on a line become prose statements — they compile to plain text in the output.

agent x {
  description "..."
  "First paragraph."
  "Second paragraph."
}

Prose can appear inside control flow:

agent adaptive {
  description "..."
  if (expert_mode) {
    "Use precise technical language."
  } else {
    "Define terms the first time you use them."
  }
}

Variables

Variable Declaration

Variables are declared using assignment syntax:

variable_name = value

Variable Types

Strings

name = "John Doe"
message = 'Hello world'
empty_string = ""

Numbers

Numbers are currently treated as strings:

port = "3000"
timeout = "30"

Booleans

is_active = true
is_complete = false

Arrays

items = ["item1", "item2", "item3"]
numbers = ["1", "2", "3"]
mixed = ["string", "123", "true"]

Variable Usage

Variables can be used in:

  • Function arguments: ask(variable_name)
  • String concatenation: "Hello " + name
  • Conditions: if (is_active)
  • Array access: for item in items

Variable Scoping

Variables are scoped to the command and persist throughout execution:

command scope_example {
  name = "initial"
  
  if (true) {
    name = "modified"     // Modifies the existing variable
    local_var = "temp"    // Creates new variable
  }
  
  ask(name)              // "modified"
  ask(local_var)         // "temp" - available here too
}

Control Flow

Conditional Statements

If Statements

if (condition) {
  // Statements executed if condition is true
}

If-Else Statements

if (condition) {
  // Statements for true condition
} else {
  // Statements for false condition
}

Loops

For Loops

Iterate over array elements:

for variable_name in array_name {
  // Statements executed for each element
  // variable_name contains the current element
}

Example:

languages = ["JavaScript", "Python", "Rust"]
for lang in languages {
  ask("Do you use " + lang + "?")
}

While Loops

Execute while condition is true:

while (condition) {
  // Statements executed while condition is true
}

Example:

count = 0
while (count < 3) {
  ask("Iteration " + count)
  count = count + 1
}

Loop Control

Break Statement

Exit the current loop:

for item in items {
  if (item == "stop") {
    break
  }
  ask(item)
}

Built-in Functions

User Interaction

ask(question)

Ask the user a question and display it in Claude Code.

Parameters:

  • question (string | variable): The question to ask

Examples:

ask("What is your name?")
ask(stored_question)
ask("Hello " + user_name + ", how are you?")

Compiled Output:

  • String literal: Ask the user: "What is your name?"
  • Variable: Ask the user the question from variable: stored_question

confirm(message)

Ask for yes/no confirmation from the user.

Parameters:

  • message (string | variable): The confirmation message

Examples:

if (confirm("Are you ready to proceed?")) {
  ask("Great! Let's continue.")
}

Compiled Output:

Ask for confirmation: "Are you ready to proceed?"

wait_for_response()

Explicitly wait for user response before continuing.

Parameters: None

Example:

ask("Please describe your requirements")
wait_for_response()
ask("Thank you for the details!")

Compiled Output:

Wait for user response before continuing.

File Operations

create_file(filename, content)

Create a file with specified content.

Parameters:

  • filename (string): The name of the file to create
  • content (string | variable): The content to write to the file

Examples:

create_file("README.md", "project_readme")
create_file("config.json", config_template)
create_file("output.txt", "Hello, world!")

Compiled Output:

Create file "README.md" with content: project_readme

System Functions

These are placeholders for functions that would be implemented by the runtime:

Git Operations

git_init()
git_commit("commit message")
git_push()
git_status()

GitHub Operations

github_create_repo()
github_create_pr()
github_create_issue("title", "body")

File System Operations

read_file("path/to/file")
append_file("path/to/file", "content")
delete_file("path/to/file")

Tasks and Parallelism

Tasks spawn Claude Code subagents to handle subtasks autonomously. This is one of Stim's most powerful features, enabling complex multi-agent workflows.

Agent Types

Agent Description
general General-purpose agent (default). Maps to general-purpose in Claude Code.
explore Fast codebase exploration agent. Use for searching files, reading code, answering questions about the codebase.
bash Command execution specialist. Use for git operations, builds, terminal tasks.
plan Software architect agent. Use for designing implementation plans.

Inline Task

Spawn a subagent with an inline body:

task "description" {
  // statements the agent will execute
}

With an explicit agent type:

task explore "find auth patterns" {
  ask("What authentication patterns exist in the codebase?")
  wait_for_response()
}

Compiled Output:

Spawn a Explore subagent task: "find auth patterns"
Use the Task tool with:
- subagent_type: Explore
- description: find auth patterns
- prompt:
  - Ask the user the question from variable: What authentication patterns exist in the codebase?
  - Wait for user response before continuing.

File Reference Task

Reference another .stim file. The file is read and parsed at compile time, and its body is inlined:

task("helpers/research.stim")
task("helpers/research.stim", explore)

Parameters:

  • First argument (string): path to .stim file, relative to the current file
  • Second argument (optional): agent type

The referenced file must contain a valid command declaration. The command name becomes the task description if none is provided.

Parallel Block

Run multiple tasks concurrently:

parallel {
  task "analyze frontend" {
    ask("What frontend patterns exist?")
  }
  task explore "analyze backend" {
    ask("What backend patterns exist?")
  }
}

Compiled Output:

Spawn 2 subagent tasks in parallel:

### Task 1
Spawn a general-purpose subagent task: "analyze frontend"
Use the Task tool with:
- subagent_type: general-purpose
- description: analyze frontend
- prompt:
  - Ask the user the question from variable: What frontend patterns exist?

### Task 2
Spawn a Explore subagent task: "analyze backend"
Use the Task tool with:
- subagent_type: Explore
- description: analyze backend
- prompt:
  - Ask the user the question from variable: What backend patterns exist?

Rules:

  • A parallel block may only contain task statements
  • Each task runs as an independent subagent
  • Tasks within a parallel block execute concurrently

Circular Reference Detection

When using file reference tasks, Stim detects circular references at compile time:

// a.stim
command a {
  task("b.stim")  // b.stim references a.stim -> Error!
}

This produces: Error: Circular task file reference detected: b.stim

Operators

Arithmetic Operators

Addition (+)

Used for string concatenation:

result = "Hello " + "World"        // "Hello World"
message = "Count: " + count        // "Count: 5"

Comparison Operators

Equality (==)

if (status == "complete") {
  ask("Task is done!")
}

Inequality (!=)

if (status != "pending") {
  ask("Status has changed")
}

Logical Operators

Logical NOT (!)

if (!is_complete) {
  ask("Still working...")
}

Logical AND (&&)

if (is_ready && has_permission) {
  ask("Starting process...")
}

Logical OR (||)

if (is_admin || is_owner) {
  ask("Access granted")
}

Array Operations

join(separator)

Convert array to string with separator:

items = ["a", "b", "c"]
result = items.join(", ")    // "a, b, c"

Comments

Single-line Comments

// This is a comment
ask("Hello")  // Comment at end of line

Multi-line Comments

Not currently supported. Use multiple single-line comments:

// This is a multi-line comment
// that spans several lines
// to document complex logic

Targets

Every .stim file can be compiled for one of multiple AI tools. The --target flag selects which.

stim compile reviewer.stim --target cursor
stim install reviewer.stim --target chatgpt --local
Target Default? Output extension Supports tools/model Install location
claude .md ~/.claude/{commands,agents}/
cursor .mdc drops with warning ./.cursor/rules/
chatgpt .md drops with warning ./dist/chatgpt/ or ./prompts/

stim compile always writes to ./dist/<target>/<name>.<ext> so that multi-target builds never collide.

See Targets for deeper adapter behavior and how to add a new target.

Compilation Output

Understanding how Stim compiles to target markdown helps debug issues.

Variable Assignments

name = "John"

Compiles to:

Set name = John

Control Flow

if (condition) {
  ask("Hello")
}

Compiles to:

If condition:
- Ask the user: "Hello"

Loops

for item in items {
  ask(item)
}

Compiles to:

For each item in items:
- Ask the user the question from variable: item

Functions

create_file("test.txt", "content")

Compiles to:

Create file "test.txt" with content: content

Tasks

task explore "find bugs" {
  ask("What bugs exist?")
}

Compiles to:

Spawn a Explore subagent task: "find bugs"
Use the Task tool with:
- subagent_type: Explore
- description: find bugs
- prompt:
  - Ask the user the question from variable: What bugs exist?

Parallel Tasks

parallel {
  task "task A" {
    ask("Do A")
  }
  task "task B" {
    ask("Do B")
  }
}

Compiles to:

Spawn 2 subagent tasks in parallel:

### Task 1
Spawn a general-purpose subagent task: "task A"
...

### Task 2
Spawn a general-purpose subagent task: "task B"
...

Agents

agent reviewer {
  description "Reviews PRs"
  tools [Read, Grep]
  model "sonnet"
  "You are a code reviewer."
}

Compiles to (claude target):

---
name: reviewer
description: Reviews PRs
tools: [Read, Grep]
model: sonnet
---

You are a code reviewer.

Compiles to (cursor target):

---
description: Reviews PRs
globs:
alwaysApply: false
---

You are a code reviewer.

Compiles to (chatgpt target):

# reviewer

> Reviews PRs

You are a code reviewer.

Error Handling

Common Compilation Errors

Syntax Errors

Error: Expected command declaration: command <name> {
Error: Invalid ask statement: ask(unclosed string"
Error: Invalid assignment: name =

Runtime Errors

Error: File not found: /path/to/file.stim
Error: No input file specified
Error: Input file must have .stim extension

Debugging Tips

  1. Check syntax: Ensure all strings are quoted and braces are balanced
  2. Verify file paths: Use absolute paths for input files
  3. Test compilation: Use bun run dev compile --dry-run to check syntax
  4. Read output: Check the generated .md file for expected behavior

Best Practices

Variable Naming

  • Use descriptive names: deployment_environment not env
  • Use consistent casing: stick to snake_case or camelCase
  • Avoid reserved words: don't use if, for, while as variable names

Function Usage

  • Always quote string literals: ask("Hello") not ask(Hello)
  • Use variables for reusable content: store repeated strings in variables
  • Handle edge cases: check conditions before loops and file operations

Code Organization

  • Group related variables at the top
  • Use comments to explain complex logic
  • Keep functions focused on single responsibilities

Version Compatibility

This API reference is for Stim v1.0. Future versions may include:

Planned Features

  • v1.1: String interpolation, standard library
  • v2.0: Multi-file projects, package management

Deprecation Policy

  • Breaking changes will be announced in advance
  • Migration guides will be provided for major version updates
  • Backward compatibility maintained within major versions

For more help:

  • Tutorial - Step-by-step learning guide
  • Examples - Real-world command examples
  • FAQ - Common questions and troubleshooting