Skip to main content

Local-first AI agent with tools โ€” GUI and CLI

Project description

Pengy ๐Ÿง

A local-first AI agent with tools. Desktop GUI, web UI, and command-line โ€” all backed by the same agent core, talking to any OpenAI-compatible API.

PyPI - Version PyPI - Python Version PyPI - License


What is Pengy?

Pengy is an LLM agent that runs on your own machine. It connects to OpenAI, Ollama, vLLM, Groq, OpenRouter, or any local endpoint, and gives the model a set of tools to operate on your filesystem, run code, search the web, and fetch URLs โ€” all with your approval.

Three interfaces, one agent:

๐Ÿง Pengy Desktop ๐Ÿง Pengy CLI ๐Ÿง Pengy Web
Qt6 GUI with markdown rendering, multi-session sidebar, file attachments Terminal REPL with slash commands, single-shot mode for scripting Flask web UI with Bootstrap, responsive layout, SSE live streaming

All three share the same core โ€” same tools, same chat history, same config. Use whichever fits your flow.


Quick Start

Install

Pengy requires Python 3.10+. On macOS, the default /usr/bin/python3 may be too old, so the recommended install method is uv, which can install Pengy with a compatible Python automatically:

# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh

# Everything (GUI + CLI + Web)
uv tool install "pengy[all]"

# CLI only
uv tool install "pengy[cli]"

# GUI only
uv tool install "pengy[gui]"

# Web UI only
uv tool install "pengy[web]"

If you already have Python 3.10+ available, pip also works:

# Everything (GUI + CLI + Web)
pip install "pengy[all]"

# CLI only
pip install "pengy[cli]"

# GUI only
pip install "pengy[gui]"

# Web UI only
pip install "pengy[web]"

# Minimum (no GUI, no CLI โ€” use as a library)
pip install pengy

Desktop GUI

pengy

CLI (interactive)

pengy-cli

CLI (single-shot)

pengy-cli "What is the capital of France?"
pengy-cli "List all files in /tmp"

Web UI

# Localhost only (default)
pengy-web

# Listen on all interfaces (for nginx reverse proxy)
pengy-web --host 0.0.0.0

# Custom port
pengy-web --host 0.0.0.0 --port 8080

The web UI is designed for single-user personal use. For remote access, put it behind nginx with SSL and HTTP basic auth โ€” Pengy itself has no authentication.


Features

  • OpenAI-compatible โ€” Works with OpenAI, Ollama, vLLM, LM Studio, OpenRouter, Groq, or any local endpoint
  • 11 built-in tools โ€” Read, write, and edit files; run bash (with sudo support) and Python code; search the web and fetch URLs; explore directory trees and search codebases
  • Agentic workflow โ€” The LLM can call multiple tools per turn, chaining them to accomplish complex tasks
  • Tool confirmation โ€” Three modes: YOLO (All) skips all confirmations, Safe auto-approves read-only tools, None confirms everything
  • Context management โ€” Elide old tool results to save context window space; configurable per-chat
  • Token usage display โ€” See prompt/completion token counts after every turn (GUI sidebar + CLI footer)
  • Theme system โ€” System, light, and dark modes plus selectable accent colors; applied across the desktop UI with scaled markdown/code rendering
  • Tasks system โ€” Reusable prompt templates for repeated workflows, with %placeholder% inputs collected at run time
  • Model discovery โ€” Fetch available models from your endpoint with one click or /models command
  • Multi-session โ€” Create, switch, and delete chat sessions; history saved locally as JSON; shared across all interfaces
  • File attachments โ€” GUI: attach files from the input bar; CLI: use /attach <path> or @path inline syntax
  • Web UI โ€” Responsive Bootstrap interface served by Flask; SSE live streaming; works great on mobile
  • Slash commands (CLI) โ€” /new, /load, /models, /yolo, /model, /list, /delete, /attach, /compact, and more
  • Templated system message โ€” Auto-fills {date}, {username}, {hostname}, {osinfo} at send time
  • Persistent config โ€” Settings, task templates, and chat history live in ~/.config/pengy/, shared between GUI, CLI, and Web โ€” and across all Pengy versions (Python, Rust, C++)

Screenshots

Main chat UI Settings / theme controls Tasks templates
Pengy main chat UI Pengy settings and theme controls Pengy tasks template manager

Configuration

Desktop: Click โš™ Settings in the sidebar.
CLI: Run /config to view, /model <name> to switch models.
Web: Click โš™ in the top-right navbar.

Setting Description
Base URL API endpoint (e.g. http://localhost:11434/v1 for Ollama)
API Key Your API key (or anything for local endpoints)
Model Model name, e.g. gpt-4o, llama3, gemma
System Message Supports {date}, {username}, {hostname}, {osinfo} placeholders
Tool Confirmation YOLO (All) / Safe Only / None โ€” controls which tools require approval
Theme Mode (GUI) System / Light / Dark โ€” System follows the OS palette
Accent Color (GUI) Default, Blue, Teal, Green, Orange, Red, Pink, or Purple
UI Scale (GUI) 75 / 100 / 125 / 150 / 175 / 200 % โ€” restart for full native-widget scaling

Theme System

The desktop UI includes a theme system built around two choices:

  • Mode: System, Light, or Dark. System follows the current OS/Qt palette.
  • Accent: Default, Blue, Teal, Green, Orange, Red, Pink, or Purple. The accent drives buttons, links, focus rings, selection colours, and other highlights.

Theme settings are saved in ~/.config/pengy/settings.json as theme_mode, theme_accent, and ui_scale, so they travel with the rest of your local Pengy configuration. The renderer also scales explicit markdown, code, and input fonts so the chat view tracks the configured UI scale instead of only resizing native widgets.


Tasks

Tasks are reusable prompt templates for workflows you repeat often โ€” for example summarizing a YouTube video, drafting a release note, or running a standard code-review checklist. Open Tasks from the desktop sidebar to create, edit, delete, or play templates.

A task has a title and a prompt template. Use %placeholder% tokens anywhere in the template to ask for values when the task is played:

Summarize this YouTube video: %Youtube Video URL%
Always use the youtube transcription skill.

When you click โ–ถ Play, Pengy asks for each unique placeholder once, renders the final prompt, and sends it through the normal chat path so tools, skills, history, and confirmation settings all work exactly like a hand-written prompt. Tasks are stored locally in ~/.config/pengy/tasks.json and are shared by the Python, Rust, and C++ editions.


Tools

Pengy gives the LLM these tools to operate on your machine:

Tool Description
read_file / read_multiple_files Read one or more files at once
write_file Write or overwrite a file
replace_in_file Targeted text replacement (safer than full rewrites)
run_bash Execute shell commands (configurable timeout; sudo password dialog)
run_python Execute Python code (uses the same interpreter/venv as Pengy)
web_search DuckDuckGo web search
download_file Download a URL to ~/Downloads/
fetch_url Fetch a URL's text content into context
directory_tree Visual directory structure listing
search_content Regex search across files in a codebase

Skills

The 11 built-in tools cover the basics, but Pengy is designed to be extended with skills โ€” your own custom instructions and scripts stored as plain markdown files.

Skills are not a plugin system. There is no SDK, no manifest file, no packaging. A skill is just a skillname/skillname_skill.md file with instructions Pengy can read, optionally backed by a bash or Python script. You point Pengy at a directory of these, and it uses them automatically.

This means your Pengy can do whatever you need it to:

  • Fetch weather from an API
  • Control devices on your home network
  • Query your local databases
  • Generate reports from your own data
  • Run system administration tasks
  • Send notifications, emails, or messages
  • Anything you can describe in a prompt and a script

Skills are also self-authoring โ€” you can ask Pengy to create new skills for you, write the markdown, write the script, and update the skill index, all in one conversation.

๐Ÿ“– Read the full guide: skills/README.md โ€” covers the philosophy, how skills work, 4 complete examples with code, how to make your own, and a call to action to build your first skill.


API Compatibility

Service Base URL
OpenAI https://api.openai.com/v1
Ollama http://localhost:11434/v1
LM Studio http://localhost:1234/v1
vLLM http://localhost:8000/v1
OpenRouter https://openrouter.ai/api/v1
Groq https://api.groq.com/openai/v1

Project Structure

pengy/
โ”œโ”€โ”€ main.py              # Desktop GUI entry point
โ”œโ”€โ”€ cli/
โ”‚   โ””โ”€โ”€ main.py          # CLI entry point (interactive + single-shot)
โ”œโ”€โ”€ assets/
โ”‚   โ””โ”€โ”€ icon.png         # App icon
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ config.py        # Settings load/save + system message templating
โ”‚   โ”œโ”€โ”€ chat_manager.py  # Chat session CRUD
โ”‚   โ”œโ”€โ”€ task_manager.py  # Task template CRUD + placeholder rendering
โ”‚   โ”œโ”€โ”€ llm_client.py    # API client (generator protocol for tool handling)
โ”‚   โ””โ”€โ”€ tools.py         # Tool definitions and execution
โ”œโ”€โ”€ ui/
โ”‚   โ”œโ”€โ”€ main_window.py   # Main window; wires all signals
โ”‚   โ”œโ”€โ”€ chat_history.py  # Sidebar chat list + quick settings
โ”‚   โ”œโ”€โ”€ chat_view.py     # Markdown chat renderer
โ”‚   โ”œโ”€โ”€ chat_input.py    # Input field + file attachment
โ”‚   โ”œโ”€โ”€ chat_worker.py   # Background thread driving the LLM generator
โ”‚   โ”œโ”€โ”€ settings_dialog.py  # Settings dialog
โ”‚   โ”œโ”€โ”€ tasks_dialog.py     # Task template manager/player
โ”‚   โ””โ”€โ”€ theme.py            # Light/dark/accent theme system
โ””โ”€โ”€ web/
    โ”œโ”€โ”€ app.py           # Flask application (routes, WebWorker, SSE)
    โ”œโ”€โ”€ main.py          # Web entry point (argparse, app.run)
    โ””โ”€โ”€ templates/
        โ”œโ”€โ”€ base.html    # Navbar, sidebar, Bootstrap layout
        โ”œโ”€โ”€ chat.html    # Chat view + JS SSE client
        โ””โ”€โ”€ settings.html # Settings form

Development

Install from source

git clone https://github.com/patw/pengy.git
cd pengy
uv sync --extra all

Or, with Python 3.10+ already available:

pip install -e ".[all]"

Running tests

pip install -e ".[all]"
python -m pytest tests/ -v

Dependencies

Package Purpose
PySide6 Qt6 GUI framework
flask Web UI framework
openai OpenAI-compatible API client
markdown Markdown rendering (GUI + Web)
pygments Syntax highlighting (GUI + Web)
ddgs DuckDuckGo web search
rich CLI formatting (tables, panels, markdown)

Also Available

Pengy (Python) is the reference implementation. Two high-performance ports are also fully certified, all sharing the same ~/.config/pengy/ data:

Edition Language Notes
Pengy Python Reference implementation โ€” easiest to hack on
PengyR Rust + Qt6 High-performance native binary, statically-linked core
PengyCPP C++17 + Qt6 Highest performance, smallest memory footprint, zero external dependencies

All three offer the same 11 tools, desktop theme controls, reusable task templates, three interfaces (GUI/CLI/Web), and full chat/task interop. PengyR and PengyCPP ship pre-built AppImage, .deb, .dmg, and .zip releases for Linux, macOS, and Windows.


License

MIT

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

pengy-1.3.9.tar.gz (810.9 kB view details)

Uploaded Source

Built Distribution

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

pengy-1.3.9-py3-none-any.whl (798.3 kB view details)

Uploaded Python 3

File details

Details for the file pengy-1.3.9.tar.gz.

File metadata

  • Download URL: pengy-1.3.9.tar.gz
  • Upload date:
  • Size: 810.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pengy-1.3.9.tar.gz
Algorithm Hash digest
SHA256 a8831216d33494b001073681bf726c8edae558cd5c829a4ef256d1b57256fc00
MD5 c00b471a186495a93ca3043c0a52a948
BLAKE2b-256 b00ffba5e1cf51445263d05a7ad2186c11cfb86180aca6d52f038407b29baa5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pengy-1.3.9.tar.gz:

Publisher: publish.yml on patw/Pengy

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

File details

Details for the file pengy-1.3.9-py3-none-any.whl.

File metadata

  • Download URL: pengy-1.3.9-py3-none-any.whl
  • Upload date:
  • Size: 798.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pengy-1.3.9-py3-none-any.whl
Algorithm Hash digest
SHA256 fc9cf9da17c0003dcc85ed4582b282c33ac93cd03552bd5b58b52404534c7cd8
MD5 466a3cf1778f1c08d5dd7dcefab0962a
BLAKE2b-256 d3edef45f94d776d2a966efe0bd7fd01923b3a706e2a349b9ca4c5c247c4f7fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for pengy-1.3.9-py3-none-any.whl:

Publisher: publish.yml on patw/Pengy

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