runprompt

repository·main·Indexed 19 days ago

https://github.com/chr15m/runprompt

A single-file Python tool for running LLM .prompt files from the shell. It supports structured JSON output via Picoschema, dynamic context gathering through 'before:' shell commands, interactive chat modes, and the integration of Python, shell, and built-in tools. It utilizes a subset of Handlebars/Mustache syntax for templates and allows configuration via CLI flags, environment variables, and config files.

Tokens
4.2K
Snippets
14
Records
19
Agent score
16%

What's inside runprompt

  1. Use Template syntax and special variables

    main

    Runprompt uses a subset of Handlebars/Mustache syntax for prompt templates.

    Special Variables

    • {{STDIN}}: Raw stdin content.
    • {{ARGS}}: Command line arguments passed after the prompt file.
    • {{INPUT}}: {{STDIN}} if provided, otherwise {{ARGS}}.
    • {{BEFORE}}: Combined output from all before: commands.
    • {{variable_name}}: Individual variables from before: commands.

    Supported Features

    • Interpolation: {{variableName}}, {{object.property}}
    • Conditionals: {{#if key}}...{{/if}}, {{#unless key}}...{{/unless}}
    • Iteration: {{#each items}}...{{/each}} (supports @index, @first, @last, @key)
    • Sections: {{#key}}...{{/key}} (renders if truthy)
    • Inverted Sections: {{^key}}...{{/key}} (renders if falsy)
    • Comments: {{! comment }}
  2. Use special template variables: {{STDIN}}, {{ARGS}}, and {{INPUT}}

    main

    The following special variables are always available in your .prompt templates:

    • {{STDIN}}: Contains the raw STDIN as a string.
    • {{ARGS}}: Contains all command-line arguments provided after the prompt file, joined with spaces.
    • {{INPUT}}: A convenience variable that contains STDIN if provided, otherwise it contains {{ARGS}}.

    Example using {{STDIN}}:

    ---
    model: anthropic/claude-sonnet-4-20250514
    ---
    Summarize this text: {{STDIN}}

    Example using {{ARGS}}:

    ---
    model: anthropic/claude-sonnet-4-20250514
    ---
    Process this: {{ARGS}}
  3. Understand Dotprompt specification compliance

    main

    runprompt is a minimal implementation of the Dotprompt specification.

    Currently NOT supported:

    • Multi-message prompts ({{role}}, {{history}})
    • Helpers ({{json}}, {{media}}, {{section}})
    • Model configuration (temperature, maxOutputTokens, etc.)
    • Partials ({{>partialName}})
    • Nested Picoschema (objects, arrays of objects, enums)

    YAML Parsing Note: The default YAML parser is minimal and handles only simple key-value pairs, nested objects, and lists in frontmatter. It may fail on complex features like anchors, multi-line strings, or flow syntax. For full support, install the pyyaml optional dependency.

  4. Execute shell commands before prompting with 'before:'

    main

    The before: key in the frontmatter allows you to run shell commands to gather dynamic context. The stdout of each command is captured and made available as a template variable. All outputs are also combined into a single {{BEFORE}} variable.

    Example:

    ---
    model: anthropic/claude-sonnet-4-20250514
    before:
      latest_commit: git log -1 --oneline
      current_date: date
    ---
    At {{current_date}}, the last commit was {{latest_commit}}.

    Commands run in your configured shell (defaulting to /bin/sh). Template variables are passed as environment variables to the shell, allowing you to use them within the before: commands (e.g., echo "Using model: ${model}").

    --- 
    model: anthropic/claude-sonnet-4-20250514
    before:
      latest_commit: git log -1 --oneline
      current_date: date
    ---
    Latest commit: {{latest_commit}}
  5. Configure safe tools for auto-approval

    main

    By default, tool calls require manual confirmation in the terminal. You can mark specific tools as "safe" to allow them to run without prompting when using the --safe-yes flag, the RUNPROMPT_SAFE_YES environment variable, or the safe_yes: true configuration.

    Marking Python tools as safe

    Set the .safe attribute on the function object in your Python tool module:

    def get_weather(city: str):
        """Gets the current weather (read-only)."""
        return {"temp": 72}
    
    get_weather.safe = True

    Marking Shell tools as safe

    In the prompt frontmatter, set safe: true within the shell_tools definition.

    shell_tools:
      git_log:
        cmd: git log --oneline
        safe: true
        description: Show recent git commits
  6. Install optional dependencies for full YAML and web scraping support

    main

    To extend runprompt functionality, you can install optional dependencies:

    • pyyaml: Provides full YAML specification support for frontmatter.
    • playwright: Enables high-quality web scraping via the builtin.fetch_clean tool.

    If you installed via pip or uv, use the following command to install the full extra from the repository:

    pip install "runprompt[full] @ git+https://github.com/chr15m/runprompt.git"
  7. Define and use Python tools

    main

    Tools allow the LLM to execute Python functions during prompt execution. Any Python function with a docstring can be used as a tool.

    Defining tools

    Create a Python file where functions include docstrings. The docstring provides the description the LLM uses to understand when and how to call the function.

    Importing tools

    Reference tools in the prompt's YAML frontmatter using Python import syntax:

    • module.*: Imports all functions with docstrings from module.py.
    • module.function_name: Imports a specific function.

    To prevent functions from being exposed to the LLM during wildcard imports, prefix the function or file name with an underscore (_).

    # my_tools.py
    def get_weather(city: str):
        """Gets the current weather for a city.
        
        Returns the temperature and conditions for the specified location.
        """
        return {"temp": 72, "conditions": "sunny"}
    ---
    model: anthropic/claude-sonnet-4-20250514
    tools:
      - my_tools.*
    ---
    What's the weather in Tokyo?
  8. Install runprompt

    main

    You can install runprompt using several methods depending on your preferred tool:

    uv pip install git+https://github.com/chr15m/runprompt

    Using pip

    pip install "git+https://github.com/chr15m/runprompt.git"

    Direct Download

    Download the single-file script and make it executable:

    curl -O https://raw.githubusercontent.com/chr15m/runprompt/main/runprompt
    chmod +x runprompt

    Run without installation

    Use uvx to run it directly from the repository:

    uvx --from git+https://github.com/chr15m/runprompt runprompt hello.prompt
    uv pip install git+https://github.com/chr15m/runprompt
  9. Connect to custom endpoints (Ollama, etc.)

    main

    To use an OpenAI-compatible endpoint (like Ollama), use the base_url option. When a custom base_url is set, the provider prefix in the model string is ignored, and the OpenAI-compatible API format is used.

    Methods to set Base URL

    • CLI Flag: ./runprompt --base-url http://localhost:11434/v1 hello.prompt
    • Environment Variable: export RUNPROMPT_BASE_URL="http://localhost:11434/v1"
    • Config File: base_url: http://localhost:11434/v1
    ./runprompt --base-url http://localhost:11434/v1 hello.prompt
  10. Enable and manage response caching

    main

    To avoid redundant API calls during development, you can enable response caching. Cached responses are stored in ~/.cache/runprompt/ (or $XDG_CACHE_HOME/runprompt/) based on the inputs applied to the template and frontmatter.

    CLI Flags

    • --cache or -c: Enables caching for a single command.
    • --clear-cache: Deletes the cached responses directory.

    Environment Variable

    • RUNPROMPT_CACHE=1: Enables caching across an entire pipeline of commands.
    # Enable caching with -c or --cache
    ./runprompt --cache hello.prompt
    
    # Second run with same input uses cached response
    ./runprompt --cache hello.prompt
    
    # Enable the cache across a whole pipeline with the env var
    export RUNPROMPT_CACHE=1; echo "..." | ./runprompt a.prompt | ./runprompt b.prompt
    
    # Clear the cache directory
    ./runprompt --clear-cache
  11. Use interactive chat mode

    main

    To start an interactive conversation with the LLM, use the --chat flag, set the RUNPROMPT_CHAT=1 environment variable, or set chat: true in the prompt frontmatter.

    Starting chat:

    ./runprompt --chat expert.prompt
    # Or a bare chat:
    ./runprompt --chat --model anthropic/claude-sonnet-4-20250514

    Chat Commands:

    • /read <path-or-url>: Append the contents of a file or URL to the chat context.
    • /edit <path>: Expose a write_file tool for the specified file, allowing the LLM to edit it.
    • /drop <path>: Remove the write_file tool for the specified file.

    Persistence: To persist readline history, set RUNPROMPT_CHAT_HISTORY=1 or chat_history: true. The history file location is controlled by RUNPROMPT_HISTORY_FILE (defaults to .runprompt.history).

  12. Define and use Shell tools

    main

    Shell tools allow you to define simple shell scripts directly in the prompt frontmatter.

    Syntax

    Use the shell_tools key in the YAML frontmatter. You can use a simple key-value pair for basic commands or a long-form object for more control.

    Fields

    • cmd (required): The shell command to execute.
    • safe (optional, default: false): If true, the tool is auto-approved when running with --safe-yes.
    • description (optional, default: cmd): The description provided to the LLM.

    LLM Arguments

    The LLM can pass arguments to these tools:

    • args (string): Appended to the command.
    • Environment variables: Passed as named parameters.
    ---
    model: anthropic/claude-sonnet-4-20250514
    shell_tools:
      git_status: git status --short
      count_py_files: find . -name "*.py" | wc -l
    ---
    What's the current git status?