🤏 Puny

A minimal natively compiled single-binary coding agent with a ~1 MB footprint. For professionals on limited hardware who want results, not bloat.

puny
Welcome to Puny 0.1.0 (6016ab8) - Your tiny AI coding assistant
AI makes mistakes - read the fucking code

  Provider: OpenCode Zen (https://opencode.ai/zen)
  Model: deepseek-v4-flash-free
  Session: 550e8400-e29b-41d4-a716-446655440000

Available commands:
  /quit, /exit       Exit Puny
  /new, /reset       New session
  /stats             Show session statistics
  /config            Reconfigure URL and API key
  /plan [task]       Enter planning mode
  /build [task]      Switch to build mode
  /model [id]        Switch to another model
  /provider [name]   Switch to another provider
  /thinking [level]  Change reasoning effort
  /sessions          List saved sessions
  /resume [id]       Resume a saved session
  /prune             Remove old sessions
  /skills            List global and repository skills
  /file [path|url]   Load a prompt from a file or URL

Type a prompt and press Enter to start chatting.

Prompt:

Why fast and small matters

Startup time ~1ms means Puny is always ready when you are — no spinner, no waiting. The ~1 MB binary and minimal memory footprint mean it runs comfortably on a Raspberry Pi, a remote server over SSH, or a decade-old laptop. Every millisecond and megabyte is deliberate: there is no hidden runtime, no garbage collector, no Node.js dependency, no Electron shell.

Why the feature set is intentionally limited

Puny is designed around the way I work. It is highly opinionated.

Other coding agents include MCP, subagents, plugins, extensions, animations, and dozens of other features I never asked for. Puny does not. The feature set is limited to what I need to get results: read files, write files, run commands, search code, load skills, fetch web pages. If you want parallel work, run another instance.

Each feature earns its place. Nothing ships because it looks good on a comparison table. This is not a platform — it is a tool.

Puny does not show the model's reasoning or thinking output by default. I do not care about the model's internal monologue. I see it as a wall of text, a huge TL;DR you have to scroll past to get to the actual answer. If you want it, pass --show-thinking. If you think you want it later, pass --chat-log which saves the entire conversation, noise included, to puny_chat.log.

The four supported providers are the ones I use personally:

Features

🧠

Multiple Providers

The four providers I use personally: LM Studio, OpenCode Zen, OpenCode Go, and GitHub Copilot

🔧

Tool Calling

Read, write, and list files, run shell commands, search code, load skills, and fetch web pages

📦

Skills System

Load reusable prompt-engineering skills via slash command, keyword triggers, or automatic model invocation

💬

Interactive Chat

Multi-turn conversations with session management and PRD export

🎯

Model Picker

Interactive model selection on startup

Installation

Build from Source

Dev

Requires Zig 0.16.0 or later.

git clone https://github.com/christianhelle/puny.git
cd puny
zig build

The compiled binary is written to zig-out/bin/puny.

To install a release build to ~/.local/bin (the same directory used by the install scripts):

zig build install-release

Other optimization modes are available:

zig build install-release-safe
zig build install-release-fast
zig build install-debug

Override the install directory with INSTALL_DIR or --prefix.

Docker

Container

Puny is published as a container image.

docker pull christianhelle/puny:latest
docker run -it --mount "type=bind,source=${PWD},target=/app" christianhelle/puny

Usage

Sessions

Each session is identified by a UUID. A new session is created on every start, /new, or /reset. Use /sessions to list saved sessions and /prune to clean up old ones. In /plan mode, once you confirm the plan is ready, the model saves the final PRD as both plan.md and plan.html to the session folder via the save_prd tool.

Skills

Puny supports reusable prompt-engineering skills stored as markdown files. Skills are scanned from ~/.agents/skills/ (global) and <repo>/.agents/skills/ (per-project).

Each skill directory contains a SKILL.md file with YAML frontmatter:

nameCanonical identifier
descriptionShort summary shown in /skills
triggersComma-separated phrases that auto-load the skill
disable-model-invocationSet to true to restrict to manual loading

Skills load three ways: /<name> slash command, mentioning a trigger phrase in your message, or the model calling load_skill automatically when it finds a relevant skill.

Quick Start with LM Studio

Start LM Studio, load a model with tool-calling support, then:

puny

OpenCode Zen

puny --provider opencode --api-key YOUR_API_KEY

OpenCode Go

puny --provider opencode-go --api-key YOUR_API_KEY

GitHub Copilot

puny --provider copilot

Prompt Files

Load the first prompt from a local file or an http:///https:// URL via --prompt-file at startup or /file in a session:

puny --prompt-file spec.md --oneshot

Docker

Run with Docker

Puny is published as a container image to both Docker Hub and GitHub Container Registry.

docker pull christianhelle/puny:latest
docker run -it --mount "type=bind,source=${PWD},target=/app" christianhelle/puny

For detailed Docker documentation, including LM Studio integration, one-shot prompts, and building locally, see Docker Documentation.