Skip to content

The Anatomy of a SmartTool

Every SmartTool is just a YAML file with a secret superpower: it turns plain English instructions into Unix commands. In the next 10 minutes, you'll understand exactly how that magic works.

What You'll Learn

  • The 5 essential parts of every tool config
  • How variables flow through your tool like water through pipes
  • The one YAML gotcha that trips up everyone (and how to avoid it)

The Simplest Tool That Actually Works

Let's start with something real. Here's a complete, working tool in just 8 lines:

name: shout
version: "1.0.0"
description: Makes text LOUD

steps:
  - type: prompt
    provider: claude
    prompt: "Convert this to ALL CAPS with enthusiasm: {input}"
    output_var: result

output: "{result}"

Save this to ~/.smarttools/shout/config.yaml and you've got a working command:

$ echo "hello world" | shout
HELLO WORLD!!!

That's it. Everything else is just adding features to this basic pattern.

The Five Parts of Every Tool

Think of a SmartTool config like a recipe card:

1. Identity

name, version, description

Who is this tool?

2. Arguments

Custom flags like --format

What options does it accept?

3. Steps

Prompts and code blocks

What does it do?

4. Output

The final template

What comes out?

Let's see all five in action:

# 1. IDENTITY - Who is this tool?
name: translate
version: "1.0.0"
description: Translate text to any language

# 2. ARGUMENTS - What knobs can users turn?
arguments:
  - flag: --lang
    variable: language
    default: "Spanish"
    description: Target language

# 3. STEPS - The actual work
steps:
  - type: prompt
    provider: claude
    prompt: |
      Translate this text to {language}:

      {input}
    output_var: translation

# 4. OUTPUT - What comes out the other end
output: "{translation}"

Variables Are Pipes

Here's the mental model that makes everything click: variables are pipes that carry data through your tool.

# The user runs:
echo "Hello" | translate --lang French

Inside your tool, three pipes are now flowing:

Variable Contains Source
{input} "Hello" Piped in from stdin
{language} "French" From --lang flag
{translation} "Bonjour" Created by the AI step

You can use any variable in any step that comes after it's created. They flow downstream, never up.

The YAML Trap Everyone Falls Into

Warning: Unquoted Numbers

YAML is helpful in ways that will hurt you. Watch out for versions:

# WRONG - YAML sees this as the number 1.0
version: 1.0

# RIGHT - YAML sees this as the string "1.0.0"
version: "1.0.0"

Always quote your version numbers. Always. Even if they look fine. Future you will thank present you.

Try It Yourself

Exercise: Build a Tone Shifter

Create a tool that rewrites text in different tones. It should:

  1. Accept a --tone flag (default: "professional")
  2. Rewrite the input in that tone
  3. Output just the rewritten text
Click to see the solution
name: tone-shift
version: "1.0.0"
description: Rewrite text in a different tone

arguments:
  - flag: --tone
    variable: tone
    default: "professional"
    description: "Target tone (casual, professional, enthusiastic, formal)"

steps:
  - type: prompt
    provider: claude
    prompt: |
      Rewrite this text with a {tone} tone.
      Keep the meaning but change the style.

      Text: {input}
    output_var: result

output: "{result}"

Naming Your Tools

Tool names become Unix commands, so they follow Unix conventions:

# GOOD - lowercase, hyphens
name: code-review
name: fix-grammar
name: json2csv

# BAD - these won't work
name: CodeReview    # No uppercase
name: fix_grammar   # No underscores
name: fix grammar   # No spaces

Pick names that complete the sentence: "I need to _____ this file."

Where To Next?

You now understand the structure. Time to add superpowers: