SkillAgentSearch skills...

Rowbound

Open-source CLI and MCP server for Google Sheets enrichment — waterfalls, conditions, HTTP API integrations

Install / Use

/learn @eliasstravik/Rowbound
About this skill

Quality Score

0/100

Supported Platforms

Claude Code
Cursor

README

<p align="center"> <img src="assets/logo.png" width="80" alt="Rowbound logo" /> </p> <h1 align="center">Rowbound</h1> <p align="center"> A CLI for GTM Engineering in Google Sheets with Claude Code. </p> <p align="center"> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a> <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg" alt="Node.js" /></a> </p>

Demo

Rowbound demo

Install

Prerequisites

  • Node.js 22+node --version must be >= 22.0.0
  • gws CLIGoogle Workspace CLI for Sheets access
npm install -g @googleworkspace/cli
gws auth setup   # first time: creates Cloud project, enables APIs, logs in
gws auth login   # subsequent logins

Quick install

npm install -g github:eliasstravik/rowbound

Build from source

git clone https://github.com/eliasstravik/rowbound.git
cd rowbound
npm install
npm run dev -- <command>

Quick Start

# 1. Initialize a sheet
rowbound init <spreadsheet-id>

# 2. Add an action
rowbound config add-action <spreadsheet-id> --json '{
  "id": "enrich_company",
  "type": "http",
  "target": "company_info",
  "method": "GET",
  "url": "https://api.example.com/company?domain={{row.domain}}",
  "headers": { "Authorization": "Bearer {{env.API_KEY}}" },
  "extract": "$.name"
}'

# 3. Store API keys and run
rowbound env set API_KEY=your_key_here
rowbound run <spreadsheet-id>
rowbound run <spreadsheet-id> --dry-run   # preview first

Column names are automatically resolved to stable IDs when you run rowbound sync.

Features

Sources — Create rows from external data

  • HTTP sources — fetch from any API, extract array from response, map columns via JSONPath
  • Exec sources — run shell commands, parse JSON output into rows
  • Script sources — run named scripts to generate rows from their output
  • Webhook sources — accept inbound POST payloads, create rows in real-time
  • Deduplication — skip or update existing rows based on a match column
  • Scheduling — run sources manually, hourly, daily, or weekly

Actions — Enrich existing rows

  • HTTP actions — call any REST API with templated URLs, headers, and bodies; extract values with JSONPath; ifEmpty fallback when extract returns nothing
  • Waterfall actions — try multiple providers in order until one returns a result (e.g., Clearbit → Apollo → Hunter)
  • Formula actions — compute derived values with JavaScript expressions using {{Column Name}} references
  • AI actions — run headless Claude or Codex per row with configurable model, max turns, tools, and bare mode for faster startup
  • Exec actions — run shell commands and capture stdout
  • Script actions — run reusable named scripts stored in config; supports bash, python3, and node runtimes
  • Lookup actions — pull data from other tabs (boolean, count, or full row JSON)
  • Write actions — push data to other tabs with column mapping; supports append, upsert, and array expansion via expandPath
  • Per-action environment variables — inject env vars per action (e.g., PLAYWRIGHT_HEADLESS=true)

Pipeline

  • Conditional execution — skip actions per-row with when expressions
  • Smart skip — automatically skips rows where the target cell already has a value
  • Watch mode — poll sheets on an interval or trigger runs via webhook
  • Column tracking — stable column IDs that survive header renames and reordering
  • --columns flag — target specific columns by letter (e.g., --columns A-C,E,AP)
  • --rows flag — flexible row specs (e.g., --rows 2-5,8,10-12)
  • Rate limiting — configurable seconds between requests (default: 1 per second)
  • Timeouts in seconds — all user-facing timeouts in seconds, not milliseconds
  • Retry with backoff — exponential, linear, or fixed backoff on failures
  • Structured error handling — per-action onError config maps status codes to actions (skip, write fallback)
  • MCP server — expose all operations as Model Context Protocol tools for Claude Desktop and other AI assistants
  • Run history — track pipeline executions with per-action summaries, durations, and error logs
  • Dry run — preview what would change without writing to the sheet
  • Per-tab stop/start — enable or disable processing per tab; stops mid-run if toggled during execution
  • Per-tab settings — override concurrency, rate limit, retries, and backoff per tab
  • BYOK — bring your own API keys, pay only for the APIs you use

CLI Commands

| Command | Description | |---------|-------------| | rowbound init <sheetId> | Initialize a sheet with a default pipeline config | | rowbound run <sheetId> | Run the enrichment pipeline (--dry-run, --rows, --columns) | | rowbound status <sheetId> | Show pipeline status and enrichment rates | | rowbound watch <sheetId> | Watch for changes and run continuously (--interval, --port) | | rowbound sync <sheetId> | Reconcile columns, validate config, fix issues | | rowbound config show <sheetId> | Display the pipeline config as JSON | | rowbound config add-action <sheetId> | Add an action to the pipeline | | rowbound config remove-action <sheetId> | Remove an action by ID | | rowbound config update-action <sheetId> | Update an action (merge partial JSON) | | rowbound config list-actions <sheetId> | List configured actions (--json) | | rowbound config add-source <sheetId> | Add a source to the pipeline | | rowbound config remove-source <sheetId> | Remove a source by ID | | rowbound config update-source <sheetId> | Update a source (merge partial JSON) | | rowbound config set <sheetId> | Update pipeline settings (--enabled, --disabled, --concurrency, --rate-limit, etc.) | | rowbound config add-script <sheetId> | Add a script to the pipeline config | | rowbound config remove-script <sheetId> | Remove a script by name | | rowbound config update-script <sheetId> | Update a script (merge partial JSON) | | rowbound config validate <sheetId> | Validate the pipeline config | | rowbound runs [runId] | List recent runs or view a specific run | | rowbound runs clear | Delete all run history | | rowbound source run <sheetId> | Run a source to create rows (--source, --dry-run) | | rowbound source list <sheetId> | List configured sources | | rowbound env set <KEY=value> | Store an API key globally | | rowbound env remove <KEY> | Remove a stored key | | rowbound env list | List stored keys (values masked) | | rowbound mcp | Start the MCP server (stdio) |

MCP Server

Rowbound exposes all pipeline operations as MCP tools. Add this to your Claude Desktop config:

{
  "mcpServers": {
    "rowbound": {
      "command": "rowbound",
      "args": ["mcp"]
    }
  }
}

| Tool | Description | |------|-------------| | init_pipeline | Initialize a sheet with a default pipeline config | | run_pipeline | Run the enrichment pipeline | | add_action / remove_action / update_action | Manage pipeline actions | | add_source / remove_source / update_source | Manage data sources | | run_source | Execute a source to create rows | | update_settings | Update pipeline settings (concurrency, rate limit, retry) | | sync_columns | Sync the column registry with the current sheet state | | get_config / validate_config | Read or validate the pipeline config | | get_status | Return pipeline status with enrichment rates | | dry_run | Run in dry mode (no writes) | | start_watch / stop_watch | Manage watch mode | | preview_rows | Read and display rows from the sheet | | list_runs / get_run | View pipeline run history |

Source Types

Sources create rows from external data. They run before actions in the pipeline — new rows are created first, then actions enrich them on the next run.

http source

Fetch from an API and create rows from the response.

{
  "id": "search_companies",
  "type": "http",
  "method": "POST",
  "url": "https://api.blitz-api.ai/v2/search/company",
  "headers": { "x-api-key": "{{env.BLITZ_API_KEY}}" },
  "body": { "industry": "restaurants", "country_code": ["SE"] },
  "extract": "$",
  "extractPath": "$.results",
  "columns": { "Title": "$.company_name", "Website": "$.website_url", "LinkedIn": "$.linkedin_url" },
  "dedup": "Website",
  "schedule": "daily"
}

exec source

Run a shell command and parse JSON output into rows.

{
  "id": "import_leads",
  "type": "exec",
  "command": "curl -s https://api.example.com/leads",
  "extract": "$.data",
  "columns": { "Name": "$.name", "Email": "$.email" },
  "dedup": "Email",
  "updateExisting": true
}

webhook source

Accept inbound POST payloads and create rows. Used with rowbound watch.

{
  "id": "form_submissions",
  "type": "webhook",
  "columns": { "Name": "$.name", "Email": "$.email", "Company": "$.company" },
  "dedup": "Email"
}

Source options

| Field | Description | |-------|-------------| | columns | Maps sheet column headers to JSONPath per item: { "Name": "$.name" }. Use $.nested.field for nested data, or literal strings for static values. | | extract / extractPath | JSONPath to locate the array in the response. extractPath drills into a nested object first (e.g., $.results extracts from {"results": [...]}). | | dedup | Column header to deduplicate on. Existing rows with the same value are skipped. | | updateExisting | When true and dedup is set, update matched rows instead of skipping (default: false). | | schedule | "manual" (default), "hourly", "daily", or "weekly". Watch mode checks schedules automatically. |

script source

Run a named script (defined in the scripts config section) and parse its output into rows.

{
  "id": "import_from_script",
  
View on GitHub
GitHub Stars27
CategoryDevelopment
Updated14h ago
Forks5

Languages

TypeScript

Security Score

90/100

Audited on Apr 10, 2026

No findings