Skip to content

Latest commit

 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DoStuff

A pip-installable AI agent harness with a Textual TUI, persistent sessions, and MCP tool support.

Python litellm MCP License textual

InstallQuick startConfigurationTUI controlsMCP serversSkillsTroubleshooting

DoStuff is a terminal AI agent that runs anywhere pip runs. It gives you a full interactive session with persistent memory, multi-provider LLM support via litellm, and pluggable MCP tool servers. State lives in ~/.dostuff/, so any project you launch dostuff from shares the same memory and sessions.

TUI demo showing agent loop with tool call and response

Tip

If you have used claude-code or aider, this will feel familiar. DoStuff is opinionated, minimal, and easy to extend.


Features

  • Textual TUI with per-role colored messages, status bar, and a loading spinner
  • Multi-provider LLMs via litellm — OpenAI, Anthropic, Gemini, Groq, Mistral, Ollama, OpenRouter
  • Persistent sessions in SQLite; resume with dostuff --session <id>
  • Long-term memory (semantic + episodic) backed by ChromaDB
  • MCP server support — stdio (npx, uvx) and HTTP transports
  • Skills loader — drop a SKILL.md in the right folder, restart, done
  • Per-tool timeout (120s) to prevent hung servers
  • Token tracking — per-turn and cumulative totals
  • Graceful exitCtrl+Q or /exit saves, cleans up, and stops background workers

Install

Install from PyPI:

pip install dostuff

This installs the dostuff command on your PATH. Done.

Other install methods

For an isolated install with pipx:

pipx install dostuff

For development (editable mode, from a clone):

git clone https://github.com/<you>/dostuff.git
cd dostuff
pip install -e .           # core
pip install -e ".[full]"   # + onnxruntime + grpcio

Verify:

dostuff --help

Quick start

# 1. Set up config and secrets
mkdir -p ~/.dostuff
cp config.example.yaml ~/.dostuff/config.yaml
cp .env.example ~/.dostuff/.env
nano ~/.dostuff/.env   # add OPENAI_API_KEY=sk-...

# 2. Edit ~/.dostuff/config.yaml and set model.name
#    (see config.example.yaml)

# 3. Launch the TUI
dostuff

In the TUI:

> hi there
[agent replies]

> /exit
[session saved, goodbye]

Note

No config? No .env? The TUI shows a clear message and lets you quit without crashing. See Troubleshooting.


CLI reference

Command Description
dostuff Launch the interactive TUI
dostuff --session <id> Resume a prior session
dostuff --user <id> Override the user ID
dostuff init Create .dostuff/ in the current directory
dostuff config Show resolved config paths and values
dostuff doctor Health check (config, data dir, user ID)
dostuff session-list List all past sessions with their working dirs

TUI controls

Key / command Action
Enter Submit message
Ctrl+J Insert a newline (multi-line input)
/exit Save memories and quit
Ctrl+Q Graceful quit with save
/help Show available in-TUI commands

Visual elements:

  • User messages — blue background
  • Agent messages — neutral
  • Tool calls and results — teal background, truncated at 600 chars
  • Confirmations — yellow background (respond with y or n)
  • Errors — red background
  • Status barcwd • session-id • new/resumed • ↑total ↓total
  • Loading⏳ agent is thinking... while waiting for the model

Configuration

Config is layered, with later sources overriding earlier ones:

  1. ~/.dostuff/config.yaml — global defaults
  2. <cwd>/.dostuff/config.yaml — per-project overrides
  3. ~/.dostuff/.env / <cwd>/.dostuff/.env — secrets
  4. Environment variables — highest priority

config.yaml

# ~/.dostuff/config.yaml
data:
  global_dir: ~/.dostuff/data

mcp:
  config_path: ~/.dostuff/mcp_config.json

tracing:
  enabled: false # default OFF (no 4317 noise)
  exporter: "otlp" # otlp | console | none

model:
  name: "openai/gpt-4o-mini" # litellm format: provider/model
  api_key_env: "OPENAI_API_KEY" # name of the env var holding the key

See config.example.yaml for a full template.

.env

Never put secrets in config.yaml. Use ~/.dostuff/.env:

# ~/.dostuff/.env (chmod 600 on Unix)
OPENAI_API_KEY=sk-...
GEMINI_API_KEY=AIza...
GROQ_API_KEY=gsk_...
TAVILY_API_KEY=tvly-...

Override at runtime

MODEL=gemini/gemini-3.1-flash-lite dostuff
OTEL_ENABLED=true OTEL_EXPORTER=console dostuff

Models

The name field uses litellm format: provider/model-name.

Provider Model name API key env
OpenAI openai/gpt-4o-mini OPENAI_API_KEY
Anthropic anthropic/claude-3-5-sonnet-20240620 ANTHROPIC_API_KEY
Gemini gemini/gemini-3.1-flash-lite GEMINI_API_KEY
Groq groq/llama-3.1-70b-versatile GROQ_API_KEY
Ollama ollama/llama3.1 (none)

If name has no /, the provider field is auto-prepended.


MCP servers

MCP servers extend the agent with new tools. Configure them in ~/.dostuff/mcp_config.json.

Discovery order: mcp.config_path~/.dostuff/mcp_config.json<cwd>/.dostuff/mcp_config.json<cwd>/mcp_config.json.

Conflict resolution: No merge — the first found config wins. If ~/.dostuff/mcp_config.json exists, the project-level .dostuff/mcp_config.json is silently ignored. To use a custom path, set mcp.config_path in config.yaml — that takes highest priority.

Example config

{
  "mcpServers": {
    "tavily": {
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@tavily/mcp-server"],
      "env": { "TAVILY_API_KEY": "tvly-..." }
    },
    "github": {
      "transport": "stdio",
      "command": "uvx",
      "args": ["mcp-server-github"],
      "env": { "GITHUB_TOKEN": "ghp_..." }
    },
    "remote": {
      "transport": "http",
      "url": "https://mcp.example.com/sse",
      "headers": { "Authorization": "Bearer xxx" }
    }
  }
}
Field Required for Notes
transport optional stdio (default) or http
command stdio Executable (npx, uvx, ...)
args stdio Argument list
env stdio Env vars for the child process
url http Remote MCP server URL
headers http HTTP headers

MCP connections start in a background worker, so the TUI never blanks during boot. Each server is announced with a or in the message area.

To force a re-registration, delete:

rm ~/.dostuff/data/mcp_client_registrations.json

Skills

Skills are markdown documents that teach the agent new workflows. Each is a directory with a SKILL.md (frontmatter + body).

Discovered from (in order):

  1. <cwd>/.dostuff/skills/
  2. <cwd>/.agents/skills/
  3. ~/.dostuff/skills/
  4. ~/.agents/skills/
  5. <cwd>/skills/

Conflict resolution: No deduplication. If two skills share the same name (from different directories), both are loaded and passed to the model — the agent may see the same skill twice with different location paths. To avoid confusion, keep names unique across the search paths.

Example structure:

~/.agents/skills/
└── my-skill/
    ├── SKILL.md        # required
    └── helpers/        # optional

SKILL.md:

---
name: my-skill
description: One-line description of what this skill does
---

# My Skill

Detailed instructions for the agent go here.

Run dostuff init to bootstrap a local .dostuff/skills/ folder. Restart the agent after adding new skills.


Sessions and memory

  • DB: ~/.dostuff/data/sessions.db (SQLite)
  • Resume: dostuff --session <id>
  • List: dostuff session-list
  • Memory stores: ~/.dostuff/data/chroma/
    • Semantic (key/value facts)
    • Episodic (events with summaries and timestamps)
  • Saved on: /exit or Ctrl+Q

Long-term memory survives pip install . --upgrade because it lives in the user's home directory, not in the package.


Tracing (opt-in)

Tracing is OFF by default to avoid spurious localhost:4317 errors.

# ~/.dostuff/config.yaml
tracing:
  enabled: true
  exporter: "console" # or "otlp"
  endpoint: "localhost:4317"

Or via env:

OTEL_ENABLED=true OTEL_EXPORTER=console dostuff

Troubleshooting

Warning

TUI says "No LLM configured"

Set model.name in ~/.dostuff/config.yaml and add the API key to ~/.dostuff/.env. See Quick start.

Warning

Connection closed (MCP tool)

The MCP server disconnected. Check the command and logs. Force a reconnect:

rm ~/.dostuff/data/mcp_client_registrations.json
dostuff

Warning

MarkupError when a tool returns a long URL

Fixed in the current version. Update:

pip install --upgrade dostuff

Warning

Tracing errors / localhost:4317 retrying

Tracing is OFF by default. If you enabled it and have no collector, set:

OTEL_ENABLED=false dostuff

Warning

Session not resuming

Use dostuff session-list to find the session ID. Each session also stores the working directory it was started from.

Warning

pip install . fails

Requires Python 3.10+. Upgrade pip first:

pip install --upgrade pip

Project structure

dostuff/
├── cli_tui.py              # Textual App + adapter
├── cli.py                  # typer CLI entrypoint
├── config.py               # layered config (env > project > global > default)
├── agent/
│   ├── loop.py             # agent loop, tool dispatch, token tracking
│   ├── call_agent.py       # LLM call wrapper
│   └── run_tool.py         # tool execution
├── lib/
│   ├── tracing.py          # opt-in OpenTelemetry tracing
│   ├── model.py            # model resolution
│   ├── memory/             # SQLite + ChromaDB stores
│   └── mcp/                # MCP client and registries
├── helpers/
│   ├── skills/             # skill discovery
│   ├── agent/              # identity, constants, exit handlers
│   ├── mcp/                # config loading
│   └── ui/                 # emit shim
└── tools/                  # tool definitions
    ├── bash/
    ├── files/
    └── mcp/

Project metadata

About

DoStuff: AI Agent Harness

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages