Skip to main content

Tommy — memnos-native coding orchestrator

Tommy is a lightweight CLI orchestrator that sits between your editor and your coding harness (Claude Code, Codex, etc.). It enriches every task with long-term memory from memnos, routes work to the right harness, and lets you steer a running sub-agent mid-run without waiting for it to finish.

This file is the mechanical reference (CLI flags, config keys, MCP tool signatures, the control-channel wire protocol). For what Tommy is, why it exists, how the pieces fit together, and what's genuinely still prompted behavior vs. code-enforced, see docs/guides/tommy.md.

┌─────────────┐   tommy --mcp   ┌──────────────────────────────────────────┐
│  Editor /   │ ─────────────→  │             Tommy (stdio process)         │
│  IDE        │ ←────────────── │  8 MCP tools  ·  memnos  ·  harness mgr  │
└─────────────┘  JSON-RPC/stdio └──────────────────────┬───────────────────┘
                                                        │ Popen
                                              TOMMY_CTRL_PORT
                                                        │
                                         ┌──────────────▼──────────────┐
                                         │  Harness (Claude Code, etc.) │
                                         │  progress / wrap_up / abort  │
                                         └─────────────────────────────┘

Key design decisions:

  • Tommy is a stdio subprocess, not a daemon or HTTP server. The editor spawns it (tommy --mcp) and owns its lifecycle.
  • memnos is the only persistent server. Tommy talks to memnos for memory; it exposes no long-lived listening ports.
  • A TCP loopback control channel (TOMMY_CTRL_PORT) is opened transiently — one ephemeral 127.0.0.1:0 socket per dispatch, closed when the sub-agent exits. This lets Tommy send wrap_up / abort / pivot to a running sub-agent and receive live progress without polling.

Requirements

Dependency Version
Python ≥ 3.10
uv any recent
memnos installed and running (HTTP or stdio)
A supported harness Claude Code (claude), Codex, etc.

Install

# From the memnos repo root (editable, uv-managed):
uv tool install -e ~/git/memnos/agents/tommy

# Verify:
tommy --version

Note: always use --force when pyproject.toml dependencies change:

uv tool install -e ~/git/memnos/agents/tommy --force

First-time setup

tommy --install

This creates ~/.memnos/agents/tommy/tommy.conf with sensible defaults.


Configuration

Edit ~/.memnos/agents/tommy/tommy.conf:

# Who you are
TOMMY_USER=YourName
ORG=your-org

# memnos namespaces
TOMMY_NS=user:yourname:tommy          # where Tommy journals its own sessions
DEFAULT_NS=org:your-org:engineering   # default namespace for new memories

# Model & harness
DEFAULT_MODEL=claude-sonnet-4-5
HARNESS=claude                        # claude | codex | auto
SMART_ROUTING=on

# Projects — format: key:Name:JIRA_PROJECT:absolute/path/to/repo
# (one per line, comma-separated)
PROJECTS=\
  myapp:MyApp:MYAPP:~/git/myapp,\
  platform:Platform:PLAT:~/git/platform,\
  infra:Infra:PLAT:~/git/infra

Project fields

Field Meaning
key Short identifier used in tommy --project <key>
Name Human-readable label
JIRA_PROJECT Jira project key (used in commit messages, ticket links)
path Absolute path — the workspace Tommy gives to the harness

Usage

CLI

# Launch harness with memory context
tommy

# Activate a project (workspace + namespace auto-set)
tommy --project myapp

# List configured projects
tommy --list-projects

# List detected harnesses
tommy --list-harnesses

# Upgrade (respects uv/pipx/pip — never mixes installers)
tommy --upgrade

MCP stdio mode (for editors)

tommy --mcp

The editor spawns this process, sends JSON-RPC over stdin/stdout, and kills the process when done. In MCP mode Tommy itself has no persistent listening port — but each tommy_dispatch call opens a transient 127.0.0.1:0 TCP control channel that is closed when the sub-agent exits.


Editor integration

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "tommy": {
      "command": "tommy",
      "args": ["--mcp"]
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project root (or the global ~/.cursor/mcp.json):

{
  "servers": {
    "tommy": {
      "command": "tommy",
      "args": ["--mcp"]
    }
  }
}

VS Code + Continue

In .continue/config.json:

{
  "mcpServers": [
    {
      "name": "tommy",
      "command": "tommy",
      "args": ["--mcp"]
    }
  ]
}

Zed

In ~/.config/zed/settings.json:

{
  "context_servers": {
    "tommy": {
      "command": {
        "path": "tommy",
        "args": ["--mcp"]
      }
    }
  }
}

MCP tools

Tool Description
tommy_recall Query memnos memory for context
tommy_remember Persist a fact / decision to memnos
tommy_dispatch Launch a harness task (async by default)
tommy_status Check a running task's output / exit code
tommy_control Send wrap_up / abort / pivot / answer to a running task
tommy_switch_project Set active project (workspace + namespace)
tommy_route Dry-run: which harness would Tommy pick?
tommy_list_harnesses Available harnesses + active routing config

tommy_dispatch

tommy_dispatch(
    task="refactor the auth module to use PKCE",
    harness="auto",          # or "claude", "codex", …
    workspace="/path/to/repo",
    async_run=True,          # return task_id immediately
    inject_memory=True,      # prepend memnos recall to prompt
)
→ {"task_id": "a3f1b2c4", "status": "running", "harness": "claude"}

tommy_control — steer a running task

# Ask the harness to wrap up (gives it 60 s to finish gracefully)
tommy_control(task_id="a3f1b2c4", action="wrap_up", budget_seconds=60)

# Stop immediately
tommy_control(task_id="a3f1b2c4", action="abort")

# Redirect to a different goal mid-run
tommy_control(task_id="a3f1b2c4", action="pivot",
              message="focus only on the login flow, skip registration")

# Answer a question the harness asked
tommy_control(task_id="a3f1b2c4", action="answer", message="yes, overwrite")

The harness receives the message over a TCP loopback control channel (TOMMY_CTRL_PORT env var) — no polling required.


Control channel (for harness authors)

If you write a custom harness in Python, connect back to Tommy using the bundled ControlClient:

from tommy.control import ControlClient

def handle_tommy_message(msg: dict) -> None:
    if msg["type"] == "wrap_up":
        # save state and exit within msg["budget_seconds"]
        ...
    elif msg["type"] == "abort":
        raise SystemExit(1)
    elif msg["type"] == "pivot":
        current_goal = msg["new_goal"]
    elif msg["type"] == "answer":
        # Reply to a question you sent via client.question()
        user_answer = msg["text"]

client = ControlClient(on_control=handle_tommy_message)

# Report progress
client.progress(25, "parsed 250 / 1000 files")
client.checkpoint("analysis", "found 3 duplicate patterns")

# Send a question to Tommy/user; answer arrives via the on_control callback as {"type": "answer", "text": ...}
client.question("Should I overwrite existing tests?", options=["yes", "no"])

client.done("refactoring complete — 12 files changed")
client.close()

The client auto-reads TOMMY_CTRL_PORT from the environment.

Protocol (newline-delimited JSON):

Direction type Extra fields
Harness → Tommy progress pct, detail
Harness → Tommy checkpoint phase, summary
Harness → Tommy done summary
Harness → Tommy error message
Harness → Tommy question text, options
Tommy → Harness wrap_up reason, budget_seconds
Tommy → Harness abort
Tommy → Harness pivot new_goal
Tommy → Harness answer text

The control channel uses TCP loopback (127.0.0.1), which works on macOS, Linux, and Windows without any extra setup.


Upgrade

tommy --upgrade

Tommy detects whether it was installed with uv, pipx, or pip and uses the same tool to upgrade — so the venv is never mixed.

To upgrade manually with uv:

uv tool install -e ~/git/memnos/agents/tommy --force

Project structure

agents/tommy/
├── README.md               ← you are here
├── pyproject.toml
└── tommy/
    ├── __init__.py
    ├── cli.py              ← click entrypoint, _launch_harness
    ├── config.py           ← TommyConfig, ProjectEntry
    ├── control.py          ← ControlServer + ControlClient (TCP IPC)
    ├── install.py          ← tommy --install
    ├── mcp_server.py       ← FastMCP stdio server, 8 tools
    ├── prompt.py           ← memnos-enriched system prompt builder
    └── discovery/
        └── harnesses.py    ← auto-detect installed harnesses

Roadmap

  • Supervision loop: idle + wall-clock timeout with automatic wrap_up
  • Smart harness routing by task type (coding vs. research vs. review)
  • memnos lease heartbeat while harness is running
  • Multi-harness fan-out (run two harnesses in parallel, merge outputs)

Download files

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

Source Distribution

tommy_orchestrator-0.1.3.tar.gz (31.2 kB view details)

Uploaded Source

Built Distribution

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

tommy_orchestrator-0.1.3-py3-none-any.whl (38.8 kB view details)

Uploaded Python 3

File details

Details for the file tommy_orchestrator-0.1.3.tar.gz.

File metadata

  • Download URL: tommy_orchestrator-0.1.3.tar.gz
  • Upload date:
  • Size: 31.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tommy_orchestrator-0.1.3.tar.gz
Algorithm Hash digest
SHA256 ce6c52f9824433a112786ebd9bcd3358cf9d8a62b803e80c1f77d34e62678969
MD5 175234e45744b2bbeb4b9e7a189df293
BLAKE2b-256 fc9c1a371194da5c0541053bec8a226d3b4632a6ec0c61b5af9b5a271c921bda

See more details on using hashes here.

Provenance

The following attestation bundles were made for tommy_orchestrator-0.1.3.tar.gz:

Publisher: release.yml on thameema/memnos

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

File details

Details for the file tommy_orchestrator-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for tommy_orchestrator-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f568a96ef1e5c8431ba32f8092a22f5b17714d9137a6df1ae0862021fb341d6a
MD5 ffbaa3c6615e5dd234de53a600ec51ec
BLAKE2b-256 23664b230e6991762409699a55a068ce8279db55a5caf7b33c81ff5145db75d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tommy_orchestrator-0.1.3-py3-none-any.whl:

Publisher: release.yml on thameema/memnos

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

Release history Release notifications | RSS feed

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

This release

0.1.3 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page