Files
platform/seed/templates/SCRIPTS.md
pastilhasandClaude Opus 4.6 22c60d4a57 add pipeline task system, agentic music tasks, copy buttons, and pi-bridge cleanup
- Pipeline mode: new task mode that chains agentic tasks sequentially with
  foreach/subdirectory iteration and skip_if conditions
- Pipeline executor backend (WebSocket at /api/tasks/pipeline/ws) with
  support for both Pi and Claude Code models
- Frontend PipelineRunner component with step progress, streaming output,
  and aggregate cost tracking
- New agentic tasks: prepare-discography, fetch-album-info, build-discography
  (pipeline combining both)
- Seed parser extended to handle pipeline steps in frontmatter config
- CopyButton component added to assistant bubbles, error bubbles, and
  tool input/output sections
- Removed obsolete SearXNG/Apify/browser relay code from pi-bridge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:20:20 +00:00

6.0 KiB

Script Task Templates

When creating a script-mode task, always use one of these templates. The template handles all boilerplate (input parsing, validation, iteration, error handling, summary). You only write the task-specific logic.

Inputs

All task inputs defined in the TASK.md frontmatter are available to the script in two ways:

  1. Environment variables: INPUT_<NAME> (uppercase) — e.g. file_path$INPUT_FILE_PATH
  2. Positional arguments: if args: [file_path] is set in TASK.md, the value is passed as $1

Input types and UI rendering

Type UI Notes
string Text field Free-form text input
string + options Selectable pills User picks one from a list
number Number field Numeric input
boolean No/Yes toggle Defaults to false if not specified

Inputs provided by context (e.g. file_path from the file browser) are auto-filled and hidden from the form.

Autofill

Inputs can declare autofill to pre-fill from the trigger context. Available context values:

Value Source
entry_name Name of the file or directory that triggered the task
entry_path Full path of the file or directory

Autofilled inputs are visible and editable (unlike file_path which is hidden).

Templates

1. File Processor

Use when the task operates on a file or directory of files.

When to use: converting files, transcoding, extracting metadata, batch renaming, any per-file operation.

Structure: Define EXTENSIONS and process_file(), then the template handles discovery, iteration, and summary.

#!/usr/bin/env bash
set -euo pipefail

# ── Task: <Task Name> ──

EXTENSIONS="ext1|ext2|ext3"

process_file() {
  local input="$1"
  # ... do work on $input ...
  # return 0 on success, 1 on failure
}

# ── Template: File Processor ──

TARGET="${1:-${INPUT_FILE_PATH:-}}"

if [[ -z "$TARGET" ]]; then
  echo "Error: No file or directory path provided" >&2
  exit 1
fi

if [[ ! -e "$TARGET" ]]; then
  echo "Error: Path does not exist: $TARGET" >&2
  exit 1
fi

converted=0
failed=0

if [[ -f "$TARGET" ]]; then
  if process_file "$TARGET"; then
    converted=$((converted + 1))
  else
    failed=$((failed + 1))
  fi
elif [[ -d "$TARGET" ]]; then
  while IFS= read -r -d '' file; do
    if process_file "$file"; then
      converted=$((converted + 1))
    else
      failed=$((failed + 1))
    fi
  done < <(find "$TARGET" -type f -regextype posix-extended -iregex ".*\.($EXTENSIONS)" -print0 | sort -z)

  if [[ $converted -eq 0 && $failed -eq 0 ]]; then
    echo "No matching files found in: $TARGET"
    exit 0
  fi
else
  echo "Error: Not a file or directory: $TARGET" >&2
  exit 1
fi

echo ""
echo "Summary: $converted processed, $failed failed"

Slots to fill:

  • EXTENSIONS — pipe-separated list of file extensions to match when processing a directory
  • process_file() — receives one argument: the full path to the file. Print progress to stdout, errors to stderr. Return 0 on success, 1 on failure.

Example (convert audio to MP3):

EXTENSIONS="flac|wav|ogg|wma|aac|m4a|opus"

process_file() {
  local input="$1"
  local output="${input%.*}.mp3"

  if [[ -f "$output" ]]; then
    echo "Skipping (exists): $output"
    return 0
  fi

  echo "Converting: $input"
  if ffmpeg -i "$input" -codec:a libmp3lame -b:a 320k -y "$output" 2>/dev/null; then
    echo "  Done"
  else
    echo "  Failed" >&2
    return 1
  fi
}

2. Standalone

Use when the task doesn't operate on a specific file target — it uses inputs from environment variables or takes no input at all.

When to use: fetching data from APIs, generating reports, system tasks, anything that isn't per-file processing.

#!/usr/bin/env bash
set -euo pipefail

# ── Task: <Task Name> ──

main() {
  # Access inputs via $INPUT_* environment variables
  # e.g. $INPUT_COUNTRY, $INPUT_LIMIT, $INPUT_OUTPUT_DIR

  # ... do work ...
}

# ── Template: Standalone ──
main

Slots to fill:

  • main() — the entire task logic. Use $INPUT_* env vars for parameters.

Example (download RSS feed):

main() {
  local url="$INPUT_FEED_URL"
  local output="${INPUT_OUTPUT_DIR:-$HOME}/feed.xml"

  echo "Fetching: $url"
  if curl -sSL "$url" -o "$output"; then
    echo "Saved to: $output"
  else
    echo "Failed to fetch feed" >&2
    exit 1
  fi
}

TASK.md Frontmatter

Every script task needs a TASK.md with this structure:

---
name: Task Name
description: What the task does
version: 1
mode: script
language: bash
triggers:                    # optional — enables context menu on matching files
  - type: file
    extensions:
      - ext1
      - ext2
  - type: directory
inputs:
  input_name:
    type: string             # string, number, boolean
    description: What this input is
    default: value           # optional — default value
    autofill: entry_name     # optional — pre-fill from context (entry_name or entry_path)
    options:                 # optional — renders as selectable pills in UI
      - option1
      - option2
args: [input_name]           # optional — pass inputs as positional args
---

# Task Name

Brief description of what the task does.

Rules

  1. Always use set -euo pipefail — fail fast on errors.
  2. Print progress to stdout — the user sees this streamed in the UI.
  3. Print errors to stderr — they appear in red in the UI.
  4. Return proper exit codes — 0 = success, non-zero = failure. The UI shows "Task complete" or "Task failed" based on exit code.
  5. Don't assume tools are installed — check with command -v before using optional dependencies.
  6. Use $INPUT_* env vars — never hardcode paths or values that should come from inputs.
  7. The script runs inside a bwrap sandbox for non-admin users — it has access to /data/home/ (user's home), /tmp, and standard system tools. It cannot access other users' data.
  8. Keep scripts self-contained — the entire script is stored in the database as a single text blob. No external file dependencies.