Skip to main content

Build, test, and play Wherigo cartridges with AI — an MCP server for GPS-based interactive stories

Project description

wheriflo

🧪 Beta. wheriflo is under active development — expect rough edges and please report issues.

Build, test, and play Wherigo cartridges from the command line — with an MCP server for AI-assisted cartridge creation.

Describe it. AI builds it. Go play it.

What is Wheriflo?

Install

One command, any AI client — installs wheriflo and configures every AI client found on your machine (Claude Desktop, Claude Code, VS Code/Copilot, Cursor, OpenAI Codex):

Mac / Linux:

curl -LsSf https://raw.githubusercontent.com/harrisonhoffman1/wheriflo/main/scripts/install.sh | sh

Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/harrisonhoffman1/wheriflo/main/scripts/install.ps1 | iex"

Already have Python? You can install with pip and run the configurator yourself:

pip install wheriflo
wheriflo setup        # detects your AI clients and configures them

wheriflo setup merges into existing config files (never overwrites other servers), backs up anything it touches, and is safe to re-run. Use --dry-run to preview and --client KEY to target one client.

Verify it works:

wheriflo --version

Note: If you have multiple Python environments, wheriflo --version may report a different version than what you just installed (e.g. a previously installed version in user site-packages). Use pip show wheriflo to confirm which version is active.

Running with uvx in sandboxed environments

Some AI coding agents and CI sandboxes only allow writes inside the workspace or temporary directories. If uvx cannot write to its default directories under your home folder, it may fail before wheriflo starts. Set both UV_CACHE_DIR and UV_TOOL_DIR to writable paths:

UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools uvx --from wheriflo wheriflo compile path/to/Cartridge.lua

Use absolute paths if your MCP client starts outside the workspace.

Quick Start

CLI Commands

# Configure your AI clients to use wheriflo (one-time)
wheriflo setup

# Scaffold a new geocache cartridge (default type)
wheriflo init "My Adventure" --author "Jane" --location 47.6,-122.3 --find-location 47.601,-122.301

# Scaffold a standalone game (no physical cache)
wheriflo init "Mystery Game" --author "Jane" --location 47.6,-122.3 --activity WherigoGame

# Test in browser (auto-reloads when file changes)
wheriflo play my-adventure/MyAdventure.lua --watch

# Build for release
wheriflo build my-adventure/MyAdventure.lua

# Store Groundspeak credentials securely (one-time setup)
wheriflo credentials set

# Compile via the official Groundspeak API
wheriflo compile my-adventure/MyAdventure.lua

# Review and edit cartridge text — iOS screen previews, variable inspector, inline editing
wheriflo edit my-adventure/MyAdventure.lua

# View gameplay flow map with jump-to-section testing
wheriflo flow my-adventure/MyAdventure.lua

# Publish to wherigo.com (opens browser, copies .gwz path)
wheriflo publish my-adventure/MyAdventure.lua

# Validate a compiled cartridge
wheriflo validate MyAdventure.gwc

# Check version
wheriflo --version

How It Works

Build Pipeline

Groundspeak Compiler

The toolkit can compile your cartridge through the official Groundspeak (wherigo.com) compiler API. This is the definitive compatibility test — if Groundspeak accepts it, the cartridge will work on all Wherigo players.

Setting up credentials

You need a free wherigo.com account.

Option 1: System keyring (recommended) — credentials are encrypted by your OS:

pip install keyring            # if not already installed
wheriflo credentials set       # prompts for username and password
wheriflo credentials check     # verify credentials are stored

This uses Windows Credential Manager, macOS Keychain, or Linux Secret Service.

Option 2: Environment variables — for CI/automation or if keyring is unavailable:

# Linux / Mac
export WHERIGO_USERNAME=your_username
export WHERIGO_PASSWORD=your_password

# Windows (PowerShell)
$env:WHERIGO_USERNAME = "your_username"
$env:WHERIGO_PASSWORD = "your_password"

Option 3: Provide at compile time — when using the MCP server, the AI assistant can ask for your credentials and pass them directly to wheriflo_compile. They are never stored.

For MCP clients, you can also add credentials to your server configuration (note: these are stored as plain text in the config file):

{
    "servers": {
        "wheriflo": {
            "command": "uvx",
            "args": ["wheriflo", "mcp"],
            "env": {
                "WHERIGO_USERNAME": "your_username",
                "WHERIGO_PASSWORD": "your_password"
            }
        }
    }
}

Security: Credentials are resolved in order: runtime parameters → environment variables → system keyring. They are never logged, never included in error messages, and the connection to wherigo.com uses HTTPS. The SOAP request body is built with XML-safe escaping to prevent injection.

Sandbox: Cartridge Lua runs in a restricted lupa (Lua 5.1) sandbox when you play/test a cartridge. The Python bridge is disabled (register_eval=False, register_builtins=False), an attribute filter blocks access to private/dunder attributes of Python objects, and io, os, debug, loadfile, dofile, loadstring, load, and package.loadlib/loaders are removed before cartridge code runs. See SECURITY.md for details.

MCP Server

The toolkit includes an MCP server for use with AI coding assistants (GitHub Copilot, Claude Desktop, Claude Code, Cursor, Zed, etc.).

Tools

MCP Server Tools

Tool Description
wheriflo_init Scaffold a new cartridge project
wheriflo_build Compile .lua → .gwc/.gwz (local)
wheriflo_compile Compile via official Groundspeak API
wheriflo_validate Validate a .gwc binary
wheriflo_lint Check .lua for common mistakes
wheriflo_play Load cartridge + start web player
wheriflo_get_state Inspect current game state
wheriflo_teleport Enter a zone (trigger OnEnter)
wheriflo_leave_zone Exit a zone (trigger OnExit)
wheriflo_set_position Set player GPS coordinates
wheriflo_respond Dismiss message or answer prompt
wheriflo_autoplay Run a sequence of play-test steps
wheriflo_get_resource Read API reference, design guide, or template
wheriflo_edit Review/extract all cartridge text
wheriflo_flow Analyze cartridge gameplay flow graph
wheriflo_publish Open wherigo.com to upload or update
wheriflo_reset Full state wipe and restart
wheriflo_stop Stop web player and free the port

Resources

  • wherigo://api-reference — Lua API docs
  • wherigo://design-guide — Design best practices
  • wherigo://lua-template — Starter template

Guides

  • Getting Started — Installation, setup, first cartridge
  • Flow Map Guide — Interactive gameplay flow visualization, jump-to-section testing, coverage tracking

Prompts

  • design-cartridge — Guided workflow to create a cartridge from scratch
  • review-cartridge — Automated play-test and bug report

Quick Start for AI Agents

This is the typical MCP workflow for building and testing a cartridge:

1. wheriflo_init           → scaffold a new project
2. (edit the .lua file)    → write your cartridge logic
3. wheriflo_lint           → check for common mistakes
4. wheriflo_build          → compile to .gwc/.gwz + auto-starts web player
5. wheriflo_teleport       → enter a zone
   wheriflo_respond        → dismiss messages / answer prompts
   wheriflo_leave_zone     → test OnExit handlers
   wheriflo_get_state      → inspect zones, inventory, tasks
6. wheriflo_compile        → validate with official Groundspeak API
7. wheriflo_publish        → upload or update on wherigo.com
8. wheriflo_stop           → shut down the web player when done

Use wheriflo_get_resource("api-reference") to read the full Lua API documentation, and wheriflo_get_resource("design-guide") for best practices.


Setup: automatic (any client)

wheriflo setup

Detects installed AI clients and writes the MCP configuration for each. The sections below are the equivalent manual steps, if you prefer to edit configs yourself or need a workspace-scoped setup.

Setup: VS Code / GitHub Copilot

Add to .vscode/mcp.json in your workspace:

{
    "servers": {
        "wherigo": {
            "command": "uvx",
            "args": ["wheriflo", "mcp"]
        }
    }
}

Or open the Command Palette → MCP: Open User Configuration to add it globally.

If your agent environment restricts writes to the workspace, add workspace-local uv directories so uvx does not try to use ~/.cache/uv or ~/.local/share/uv/tools:

{
    "servers": {
        "wherigo": {
            "command": "uvx",
            "args": ["wheriflo", "mcp"],
            "env": {
                "UV_CACHE_DIR": ".uv-cache",
                "UV_TOOL_DIR": ".uv-tools"
            }
        }
    }
}

Setup: Claude Desktop

Add to your claude_desktop_config.json:

{
    "mcpServers": {
        "wherigo": {
            "command": "uvx",
            "args": ["wheriflo", "mcp"]
        }
    }
}

On Windows, use:

{
    "mcpServers": {
        "wherigo": {
            "command": "cmd",
            "args": ["/c", "uvx", "wheriflo", "mcp"]
        }
    }
}

Setup: Claude Code

claude mcp add wherigo -- uvx wheriflo mcp

Setup: OpenAI Codex

codex mcp add -- uvx wheriflo mcp

Setup: Cursor

Add to Cursor Settings → MCP Servers:

{
    "mcpServers": {
        "wherigo": {
            "command": "uvx",
            "args": ["wheriflo", "mcp"]
        }
    }
}

Setup: pip install (alternative to uvx)

If you prefer a permanent install instead of uvx:

pip install wheriflo

Then replace "command": "uvx", "args": ["wheriflo", "mcp"] with "command": "wheriflo", "args": ["mcp"] in any config above.

Setup: Docker

docker build -t wheriflo .
{
    "mcpServers": {
        "wherigo": {
            "command": "docker",
            "args": ["run", "--rm", "-i", "wheriflo"]
        }
    }
}

Linting

Check a .lua file for common Wherigo mistakes without building:

wheriflo lint MyAdventure.lua

Checks for:

  • Media = nil / Icon = nil (crashes iOS app)
  • ShowObjects = "OnEntry" (wrong enum, should be "OnEnter")
  • MoveObject() usage (doesn't exist — suggests MoveTo() instead)
  • Missing require "Wherigo", OnStart, OnEnter, OnGetInput
  • Unreachable zones (never set Active = true)
  • Apostrophes in comments (crashes Groundspeak compiler)

Add -- wheriflo:ignore to any line to suppress warnings on that line. For zones activated dynamically through helper functions, add the comment to the Wherigo.Zone() constructor line.

Also available as the wheriflo_lint MCP tool.

Debugging

Test the MCP server with the MCP Inspector:

npx @modelcontextprotocol/inspector uvx wheriflo mcp

Or with mcp dev:

uv run mcp dev wheriflo/src/wheriflo/mcp_server.py

Architecture

%%{init: {'theme': 'base', 'themeVariables': {'fontFamily': 'Segoe UI, sans-serif', 'lineColor': '#78909c'}}}%%
flowchart LR
    subgraph clients["Works with any MCP client"]
        direction TB
        VS["<b>VS Code</b>\n+ GitHub Copilot"]
        CL["<b>Claude</b>\nDesktop &amp; Code"]
        CX["<b>OpenAI Codex</b>"]
        CU["<b>Cursor</b>"]
    end

    subgraph mcp["wheriflo MCP Server"]
        direction TB
        tools["🛠️ <b>18 Tools</b>\ninit · build · compile · lint\nplay · teleport · leave_zone · set_position\nrespond · autoplay · get_state · get_resource\nedit · flow · publish · validate · reset · stop"]
        resources["📚 <b>3 Resources</b>\nAPI reference\nDesign guide\nStarter template"]
        prompts["💬 <b>2 Prompts</b>\ndesign-cartridge\nreview-cartridge"]
    end

    subgraph engine["Sandboxed Lua Engine"]
        direction TB
        shim["Wherigo API shim"]
        sandbox["🔒 No io · os · debug"]
        web["🌐 Web player\nlocalhost:8000"]
    end

    clients <-->|"stdio"| mcp
    mcp <--> engine

    style clients fill:#e3f2fd,stroke:#1a73e8,rx:12,color:#0d47a1
    style mcp fill:#fff3e0,stroke:#ff9800,rx:12,color:#e65100
    style engine fill:#fce4ec,stroke:#e91e63,rx:12,color:#880e4f
    style VS fill:#bbdefb,stroke:#42a5f5,rx:8,color:#0d47a1
    style CL fill:#bbdefb,stroke:#42a5f5,rx:8,color:#0d47a1
    style CX fill:#bbdefb,stroke:#42a5f5,rx:8,color:#0d47a1
    style CU fill:#bbdefb,stroke:#42a5f5,rx:8,color:#0d47a1
    style tools fill:#ffe0b2,stroke:#ffa726,rx:8,color:#e65100
    style resources fill:#ffe0b2,stroke:#ffa726,rx:8,color:#e65100
    style prompts fill:#ffe0b2,stroke:#ffa726,rx:8,color:#e65100
    style shim fill:#f8bbd0,stroke:#ec407a,rx:8,color:#880e4f
    style sandbox fill:#f8bbd0,stroke:#ec407a,rx:8,color:#880e4f
    style web fill:#f8bbd0,stroke:#ec407a,rx:8,color:#880e4f

Troubleshooting

uvx cache or tool directory permission errors

If a command fails with an error like Failed to initialize cache at ~/.cache/uv, Could not create temporary file, or a path under ~/.local/share/uv/tools, the failure is from uvx setup rather than wheriflo, Groundspeak, or your cartridge. Point uv at writable directories:

UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools uvx --from wheriflo wheriflo compile path/to/Cartridge.lua

For MCP server configs, put the same values in the server env block. Use absolute paths if relative paths are resolved outside your project.

Run the diagnostic tool to check your setup:

wheriflo doctor

This verifies Python version, lupa, mcp SDK, credentials, Groundspeak API reachability, and the starter template.

Known Limitations

  • Media in web player — images referenced in ZMedia objects are embedded in the GWC/GWZ and displayed in the web player during play-testing. Audio files are embedded but not played back in the web player.
  • Timers run in real timeZTimer Countdown and Interval timers fire OnTick/OnStop on real wall-clock schedules during play-testing. Because MCP play-testing is turn-based, a timer may fire between tool calls; check wheriflo_get_state after waiting out a timer. Timer state is not saved/restored.
  • No save/restoreOnRestore is not implemented. The engine always starts fresh. Use wheriflo_reset to restart.
  • Single-player only — the engine simulates one player. Multi-player or co-op cartridges can only be tested on the single-player path.
  • Limited GPS simulation — zones are entered via wheriflo_teleport, not by simulating GPS movement. Use wheriflo_set_position to set arbitrary coordinates for proximity testing, but OnDistanceChanged callbacks don't fire automatically.
  • iOS line breaks — only [[ ]] long strings render line breaks on the iOS Wherigo app. \n in quoted strings works on Android and the web player but not iOS. See the API reference for workarounds.
  • Web player is local only — the browser player binds to localhost and is not suitable for remote access or sharing.

Security

The Lua runtime is sandboxed: io, os, debug, loadfile, and dofile are removed before any cartridge code executes. Cartridges can only use the Wherigo API and standard Lua string/table/math operations.

See SECURITY.md for the full security policy and vulnerability reporting.

Contributing

See CONTRIBUTING.md for development setup, project structure, and guidelines.

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wheriflo-2.14.0.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wheriflo-2.14.0-py3-none-any.whl (170.6 kB view details)

Uploaded Python 3

File details

Details for the file wheriflo-2.14.0.tar.gz.

File metadata

  • Download URL: wheriflo-2.14.0.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for wheriflo-2.14.0.tar.gz
Algorithm Hash digest
SHA256 d7e923662dce49220cd209b91eb16bc84214df96e111eeeae320ff6747441ccf
MD5 add077b57d8016268ddfc10e67bddb9b
BLAKE2b-256 1864ab0ff19cab0359b606573d608cc86f44bede182932649a2150a19e6dbb3b

See more details on using hashes here.

Provenance

The following attestation bundles were made for wheriflo-2.14.0.tar.gz:

Publisher: publish.yml on harrisonhoffman1/wheriflo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wheriflo-2.14.0-py3-none-any.whl.

File metadata

  • Download URL: wheriflo-2.14.0-py3-none-any.whl
  • Upload date:
  • Size: 170.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for wheriflo-2.14.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cda6acd73dc39b598bec5b0a7c7da6d50c4a0654b067ea81de4d0fad6ba90e1b
MD5 99319603b3b9a50230e7660d04ef40be
BLAKE2b-256 c6faff87414d2fbb5557532800167a4f63cff4cb7df55156f8229d27d7d23335

See more details on using hashes here.

Provenance

The following attestation bundles were made for wheriflo-2.14.0-py3-none-any.whl:

Publisher: publish.yml on harrisonhoffman1/wheriflo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page