Skip to content

Latest commit

History

286 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Mr Smith

Mr Smith is a lightweight, framework-free agentic coding harness for the command line. It connects to any OpenAI-compatible chat endpoint, streams responses token by token, and gives the model a toolbox — shell, file editing, web fetch, skills, task lists, and sub-agents — so it can actually get work done in your repository.

It is a plain interactive REPL: type a prompt, watch the model reason and answer (or call tools), and drive the session with simple / commands.


Features

  • Interactive chat against any OpenAI-compatible endpoint, with live token-by-token streaming.
  • Reasoning display — thinking/reasoning streams live in yellow (plain when piped), stored in history but never re-sent to the model.
  • Tool calling loop — the model can invoke tools (capped at 32 rounds per turn by default, configurable per agent; optionally also bounded by a per-session tool budget), with confirmation prompts for any action that modifies your filesystem — each prompt offers an a/always option to approve a specific tool for the rest of the session. When the round cap is reached the loop asks whether to continue with a fresh set of rounds, so it is not a hard stop unless you decline.
  • Multiple providers & agents — named providers (credentials/endpoint) and named agents (model + system prompt + context limit + tool allowlist), switchable mid-session.
  • Skills — reusable markdown instruction bundles (SKILL.md) discovered on disk and loaded on demand into the context.
  • Sub-agents — a task tool that dispatches isolated sub-agents with their own nested tool loop, transcript, and optional resume.
  • Session persistence — every session gets a time-ordered UUID (v7) and a JSONL transcript under the sessions directory.
  • Context awareness — per-turn usage lines, a /usage report, and warnings at 85% / 100% of the configured context limit.
  • Sliding-window context — agents can opt into a sliding context builder that keeps the most recent turns within a fraction of the configured context limit, dropping the oldest turns automatically.
  • Sandboxed file tools — all file/command activity is rooted at the CWD where mr-smith was launched; paths that escape it are refused.

Requirements

  • Java 21+ (LTS) — the project uses records, pattern matching, and the JDK HTTP client.
  • Maven 3.x to build.
  • An OpenAI-compatible API endpoint and key (any provider speaking the /chat/completions streaming dialect).

Build & Run

mvn -q package
java -jar target/mr-smith.jar

To see the CLI help:

java -jar target/mr-smith.jar --help

The shaded (java -jar-ready) artifact is target/mr-smith.jar.


Configuration

Mr Smith reads its configuration from ~/.config/mrsmith/config.json (create it on first use). Providers own the credentials and endpoint; agents combine a provider with a model, system prompt, context limit, and tool allowlist.

{
"providers": [
{ "name": "opencode", "apiKey": "sk-...", "baseUrl": "https://opencode.ai/zen/go/v1" }
],
"agents": [
{
"name": "coder",
"provider": "opencode",
"model": "opencode-go/deepseek-v4-flash",
"systemPrompt": "You are an expert software engineer working in a Java repository.",
"maxContextTokens": 128000,
"maxToolRounds": 32,
"maxToolCallsPerSession": 500,
"reasoningEffort": "high",
"contextBuilder": "sliding",
"tools": ["shell", "read_file", "write_file", "list_dir", "glob", "web_fetch"]
}
],
"defaultAgent": "coder",
"includeUsage": true,
"contextWindowRatio": 0.75,
"sessionsDir": "~/.config/mrsmith/sessions",
"projectSkillsDir": "./skills",
"globalSkillsDir": "~/.config/mrsmith/skills"
}

Fields

FieldMeaning
providers[].nameUnique provider name
providers[].apiKeyAPI key (required unless MRSMITH_<PROVIDER>_API_KEY is set)
providers[].baseUrlEndpoint base URL, e.g. https://api.openai.com/v1 (required)
agents[].nameUnique agent name
agents[].providerProvider this agent uses
agents[].modelModel name (required)
agents[].systemPromptSystem prompt (optional)
agents[].maxContextTokensContext window limit; enables limit warnings (optional)
agents[].maxToolRoundsMax tool-call rounds per turn (optional, default 32)
agents[].maxToolCallsPerSessionMax executed tool calls per session, shared with sub-agents (optional; unlimited by default). Warns at 80% and stops the loop with a graceful message when exhausted
agents[].reasoningEffortOptional reasoning_effort value (e.g. low, medium, high) sent verbatim to the provider on every request; omitted when unset or blank
agents[].toolsAllowlist of built-in tools (optional; edit, todowrite, question, skill, task are always available)
agents[].shellHarmlessCommandsCommand specs promoted to read-only on top of the built-in defaults (e.g. "kubectl get"); one token ("ps") allows the whole binary, two tokens allow that subcommand only
agents[].shellDangerousCommandsCommand specs forced to require approval, taking precedence over the safe lists (e.g. "mydeploy --push")
agents[].contextBuilderContext strategy for this agent: full (default) or sliding; overrides the global default (optional)
contextBuilderGlobal default context strategy (full or sliding), applied to agents without their own override (optional, default full)
contextWindowRatioFraction of the agent's maxContextTokens to keep in a sliding window (optional, default 0.75, must be in (0, 1])
defaultAgentAgent used at startup (required, must match an agent)
includeUsageSend stream_options.include_usage for real token counts (default true; set false if your provider rejects it with a 400)
sessionsDirWhere session transcripts are stored (default ~/.config/mrsmith/sessions)
projectSkillsDirProject-level skills directory (default ./skills)
globalSkillsDirGlobal skills directory (default ~/.config/mrsmith/skills)

Precedence

CLI flags (--agent, --sessions-dir) > environment variable (MRSMITH_SESSIONS_DIR) > config file > defaults. Provider API keys are read from MRSMITH_<PROVIDER>_API_KEY (provider name uppercased, dashes → underscores), which overrides the providers[].apiKey file value — so keys can be kept out of the config file. Provider names that differ only in separators (e.g. my-provider vs my_provider) map to the same env var.

The context-builder strategy (--context-builder / MRSMITH_CONTEXT_BUILDER) and window ratio (--context-window-ratio / MRSMITH_CONTEXT_WINDOW_RATIO) follow the same precedence and set the global default; each agent may override the strategy with its own contextBuilder field.


Usage

Start a chat:

java -jar target/mr-smith.jar
java -jar target/mr-smith.jar --agent coder

Type anything to send it to the model. Reasoning streams in yellow, then the answer, then a per-turn usage line. A session banner prints the session UUID — transcripts are written to <sessionsDir>/<uuid>/transcript.jsonl.

REPL commands

CommandDescription
/exitQuit
/resetClear history and start a fresh session (new UUID, fresh context)
/helpShow commands
/usageShow token usage, context-limit percentage, history size, and the tool-call budget
/agentsList configured agents
/agent <name>Switch agent (starts a new session)
/skillsList discovered skills (* marks loaded ones)
/skills <name>Load a skill into the context manually
/tasksShow the session task list
/reasoningShow the current reasoning_effort (override, config, or "not set")
/reasoning <value>Override reasoning_effort for this session
/reasoning offClear the override (fall back to the configured value)

Anything else is sent to the LLM. Unknown / commands are rejected with a hint.


Tools

The model can call tools during a turn; results are fed back so it can iterate until it produces a final answer. Read-only tools run automatically; anything that modifies the filesystem prompts for confirmation (y/N, or a to always allow). The shell tool further classifies each command: read-only commands run automatically, while filesystem-modifying or unknown commands prompt.

Per-agent built-ins (opt-in via agents[].tools)

ToolRead-onlyDescription
shellnoRuns bash -c <command> in the CWD; returns stdout, stderr, exit code (30s timeout). Read-only commands (ls, cat, git status, ...) run automatically; commands that modify the filesystem or unknown commands require approval. The a/always option is per-command (e.g. git commit)
read_fileyesReads a file (capped at 1 MiB)
write_filenoWrites a file relative to the CWD, creating parent directories
list_diryesLists directory entries
globyesMatches files under the CWD (e.g. src/**/*.java)
web_fetchyesFetches an HTTP(S) URL and returns the body text (1 MiB cap); asks you before fetching private/link-local/localhost hosts, and re-checks every redirect hop

Always-on tools (available to every agent)

ToolRead-onlyDescription
editnoReplaces an exact substring in a file; fails unless it matches exactly once (or replaceAll is set)
todowriteyesReplaces the session task list (content / status / priority); session-scoped
questionyesPrompts you with numbered options and returns your answer(s)
skillyesLoads a skill body into the context (available when skills exist)
taskyesDispatches a sub-agent with an isolated context and returns its final answer

All file tools resolve paths against the CWD, normalize them, and refuse paths that escape the CWD root (including symlink escapes).

Session tool budget

Besides the per-turn round cap, an agent can set maxToolCallsPerSession to bound the total number of executed tool calls across the whole session — including sub-agent tool calls, which draw from the same pool. The budget is scoped to a session and resets on /reset and agent switches.

  • When 80% of the budget is used, a one-time warning is printed.
  • When the budget is exhausted mid-turn, the loop stops and asks the model to summarize and tell you to /reset (or send continue) rather than failing abruptly.
  • /usage reports the current count against the limit (e.g. tool calls: 42/500).
  • It is optional and off by default; leave it unset for unlimited calls.

Skills

Skills package reusable know-how (coding conventions, release checklists, debugging workflows) as markdown files that load into context only when needed. Each skill is a directory containing a SKILL.md with YAML-style frontmatter:

---name: codingdescription: Guidance for writing idiomatic Java in this project.---
Always run `mvn -q test` before claiming work is done.
- Follow the existing package layout in src/main.
  • Skill names must match ^[a-z0-9]+(-[a-z0-9]+)*$ and equal the directory name.
  • Discovered from globalSkillsDir then projectSkillsDir (project wins on name collision).
  • The system prompt always lists available skills (name + description only).
  • The model loads a skill via the skill tool, or you load one with /skills <name>. Once loaded, the body stays in context until /reset or an agent switch.
  • resourceDir is the skill's directory, so bundled scripts are accessible via read_file / shell / glob.

Sub-Agents

The task tool dispatches an isolated sub-agent: a fresh context seeded with your prompt, its own nested tool loop (same tools minus task), and a persistent transcript written as subagent-<n>.jsonl in the session folder.

  • Optional agent argument selects a different configured agent (default: the current agent).
  • Optional task_id (e.g. subagent-3) resumes a prior sub-agent's conversation.
  • Sub-agent usage accumulates in the main session tracker, and sub-agent tool calls count against the session tool budget when one is configured.

Sessions & Transcripts

  • Each session (and /reset, and each agent switch) starts a new time-ordered UUID v7 session.
  • Transcripts are JSONL files under sessionsDir/<uuid>/transcript.jsonl, recording user messages, assistant replies (with thinking), tool calls and results, skill loads, and per-turn token usage (real or estimated).
  • Transcript writes are best-effort; a failure disables persistence for the session with a warning rather than crashing.

Architecture

Single Maven module with disciplined package boundaries under com.mrsmith:

PackageResponsibility
cliMain entry point + picocli ChatCommand
ioIO port + ReplIo (stdin/stdout, colored reasoning)
chatChatSession, context builders, tool loop, sub-agent runner, usage tracking, UUID v7
providerProvider port + OpenAiCompatibleProvider + SSE parser, message DTOs, token estimation
configAgentCatalog, ConfigLoader (JSON config + env + CLI), config records
sessionTranscriptWriter port + FileTranscriptWriter (JSONL), sub-agent transcript store
skillSkillCatalog, SkillFrontmatter parser
utilShared Json ObjectMapper and Warn warning output
toolTool port, built-in tool implementations, ToolRegistry, path containment

Key design points:

  • Ports and adaptersProvider, IO, TranscriptWriter, Tool, and ContextBuilder are seams; new backends/adapters slot in without touching core logic.
  • History vs context — full conversation history (including thinking) is kept separately from the incremental context window actually sent to the model.
  • No framework — JDK HTTP client, Jackson, picocli, JUnit 5. Minimal dependencies.
  • Each feature has a design spec and implementation plan under docs/superpowers/.

Testing

mvn test

The suite (280+ tests) covers config loading and precedence, the chat loop, SSE parsing, provider request serialization (via OkHttp MockWebServer), context building, tool path containment, skill parsing/discovery, sub-agent transcripts, and session persistence. No real API calls are made in tests.


License

See the project repository for licensing details.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages