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.
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
/modelscommand - 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@pathinline 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 |
|---|---|---|
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, orDark.Systemfollows the current OS/Qt palette. - Accent:
Default,Blue,Teal,Green,Orange,Red,Pink, orPurple. 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pengy-1.4.3.tar.gz.
File metadata
- Download URL: pengy-1.4.3.tar.gz
- Upload date:
- Size: 834.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98dcd206eb452cee11e846fe27cdd28197a3b8b30a8651c319df9d852f0b5416
|
|
| MD5 |
bbb00e47d66f4361a3dae90b7050719a
|
|
| BLAKE2b-256 |
2c0a16fa922c795f257c5e17d7534e081013252e201003e70bb8925a0c64e322
|
Provenance
The following attestation bundles were made for pengy-1.4.3.tar.gz:
Publisher:
publish.yml on patw/Pengy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pengy-1.4.3.tar.gz -
Subject digest:
98dcd206eb452cee11e846fe27cdd28197a3b8b30a8651c319df9d852f0b5416 - Sigstore transparency entry: 2241823257
- Sigstore integration time:
-
Permalink:
patw/Pengy@c25b8a05d13eb5e4b526e64643c85fcc9215a686 -
Branch / Tag:
refs/tags/v1.4.3 - Owner: https://github.com/patw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c25b8a05d13eb5e4b526e64643c85fcc9215a686 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pengy-1.4.3-py3-none-any.whl.
File metadata
- Download URL: pengy-1.4.3-py3-none-any.whl
- Upload date:
- Size: 811.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89bdaacd0270db6885bb2ffdef38ee6e8da9a279f00b62e157f6110250ca9bfc
|
|
| MD5 |
b86306557a1ecc80406ed00775a2a11c
|
|
| BLAKE2b-256 |
ac2154e429e33a7ef40578f81f9da2c26e07f9babad36fa0f23dc3172dfaf4e6
|
Provenance
The following attestation bundles were made for pengy-1.4.3-py3-none-any.whl:
Publisher:
publish.yml on patw/Pengy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pengy-1.4.3-py3-none-any.whl -
Subject digest:
89bdaacd0270db6885bb2ffdef38ee6e8da9a279f00b62e157f6110250ca9bfc - Sigstore transparency entry: 2241823647
- Sigstore integration time:
-
Permalink:
patw/Pengy@c25b8a05d13eb5e4b526e64643c85fcc9215a686 -
Branch / Tag:
refs/tags/v1.4.3 - Owner: https://github.com/patw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c25b8a05d13eb5e4b526e64643c85fcc9215a686 -
Trigger Event:
push
-
Statement type: