๐ฆ Extreme minimalist self-adapting AI agent - one file, self-healing, runtime dependencies
Project description
๐ฆ DevDuck
Self-modifying AI agent that hot-reloads its own codeโbuilds itself as it runs.
One Python file that adapts to your environment, fixes itself, and expands capabilities at runtime.
Learn more: https://duck.nyc
๐ฌ See It In Action
| Feature | What You'll See | Demo |
|---|---|---|
| ๐ฅ Hot-Reload | Agent detects code changes and restarts instantly | Watch |
| ๐ Web UI | Clean web interface with real-time streaming | Watch |
| ๐ ๏ธ Dynamic Tools | Save .py file in ./tools/ โ use instantly |
Watch |
| ๐ TCP Streaming | Connect via netcat, apps, or other agents | Watch |
| ๐ IPC & Tray | macOS menu bar + Unix socket IPC | |
| ๐ฌ Ambient Overlay | Floating AI input with glassmorphism UI | Watch |
Quick Start
# Install & run
pipx install devduck && devduck
# One-shot query
devduck "create a REST API with FastAPI"
# Python API
python -c "import devduck; devduck('analyze this code')"
Requirements: Python 3.10-3.13, AWS credentials (or Ollama/Anthropic/GitHub/MLX)
Core Capabilities
| Feature | What It Does | How to Use |
|---|---|---|
| ๐ฅ Hot-Reload | Auto-restarts on code changes | Edit __init__.py โ saves โ auto-restart |
| ๐ ๏ธ Runtime Tools | Add/remove tools without restart | manage_tools(action="add", ...) |
| ๐ฆ Dynamic Loading | Install packages and load tools on-the-fly | install_tools(action="install_and_load", package="...") |
| ๐ง Auto-RAG | Remembers conversations via Knowledge Base | Set DEVDUCK_KNOWLEDGE_BASE_ID |
| ๐ Multi-Protocol | TCP, WebSocket, MCP, IPC servers | Auto-starts on ports 9999, 8080, 8000 |
| ๐ MCP Client | Connect to external MCP servers | Set MCP_SERVERS env var |
| ๐พ State Time-Travel | Save/restore agent state | state_manager(action="export") |
| ๐ Self-Improvement | Updates own system prompt | system_prompt(action="add_context", ...) |
| โ๏ธ AWS Deploy | One-command serverless | agentcore_config(auto_launch=True) |
Developer Setup
git clone git@github.com:cagataycali/devduck.git
cd devduck
python3.13 -m venv .venv
source .venv/bin/activate
.venv/bin/pip3.13 install -e .
devduck
Architecture
graph TB
A[User Input] -->|CLI/TCP/WS/MCP/IPC| B[DevDuck Core]
B -->|Auto RAG| C[Knowledge Base]
C -.->|Context Retrieval| B
B -->|Tool Calls| D[38+ Built-in Tools]
D --> E[shell/editor/calculator]
D --> F[GitHub/AgentCore]
D --> G[TCP/WebSocket/MCP/IPC]
D --> H[tray/ambient/cursor/clipboard]
B -->|Hot-reload| I[./tools/*.py + __init__.py]
I -.->|Load Instantly| D
B -->|Runtime| K[manage_tools/install_tools]
K -.->|Expand| D
B -->|Response| J[User Output]
J -.->|Store Memory| C
style B fill:#e1f5ff
style C fill:#d4edda
style I fill:#fff3cd
style K fill:#ffe6cc
Self-adapting loop: Query โ RAG โ Tools โ Response โ Memory โ Hot-reload/Runtime-load โ Repeat
Model Setup
DevDuck auto-detects providers based on credentials:
Priority: Bedrock โ Anthropic โ OpenAI โ GitHub โ Gemini โ Cohere โ Writer โ Mistral โ LiteLLM โ LlamaAPI โ MLX โ Ollama
| Provider | API Key | Auto-Detected |
|---|---|---|
| Bedrock | AWS credentials | โ
If boto3 auth succeeds |
| Anthropic | ANTHROPIC_API_KEY |
โ If key present |
| OpenAI | OPENAI_API_KEY |
โ If key present |
| GitHub | GITHUB_TOKEN or PAT_TOKEN |
โ If key present |
| Gemini | GOOGLE_API_KEY or GEMINI_API_KEY |
โ If key present |
| Cohere | COHERE_API_KEY |
โ If key present |
| Writer | WRITER_API_KEY |
โ If key present |
| Mistral | MISTRAL_API_KEY |
โ If key present |
| LiteLLM | LITELLM_API_KEY |
โ If key present |
| LlamaAPI | LLAMAAPI_API_KEY |
โ If key present |
| MLX | No key needed | โ On Apple Silicon (M1/M2/M3) |
| Ollama | No key needed | โ Fallback if nothing else found |
Just set your API key - DevDuck handles the rest:
export ANTHROPIC_API_KEY=sk-ant-...
devduck # Auto-uses Anthropic
export OPENAI_API_KEY=sk-...
devduck # Auto-uses OpenAI
export GOOGLE_API_KEY=...
devduck # Auto-uses Gemini
Manual override:
export MODEL_PROVIDER=bedrock
export STRANDS_MODEL_ID=us.anthropic.claude-sonnet-4-20250514-v1:0
devduck
Tool Management
Runtime Tool Management
Add, remove, or reload tools while agent is running:
# List all loaded tools
manage_tools(action="list")
# Add tools from a package at runtime
manage_tools(action="add", package="strands_fun_tools", tool_names="cursor,clipboard,bluetooth")
# Remove tools you don't need
manage_tools(action="remove", tool_names="cursor,clipboard")
# Reload specific tools after editing
manage_tools(action="reload", tool_names="shell,editor")
# Reload all tools (restarts agent)
manage_tools(action="reload")
# Load custom tool from file
manage_tools(action="add", tool_path="./my_custom_tool.py")
Dynamic Package Installation
Install Python packages and load their tools at runtime:
# Discover available tools before loading
install_tools(action="list_available", package="strands-fun-tools", module="strands_fun_tools")
# Install package and load all tools
install_tools(action="install_and_load", package="strands-agents-tools", module="strands_tools")
# Install and load specific tools only
install_tools(
action="install_and_load",
package="strands-fun-tools",
module="strands_fun_tools",
tool_names=["clipboard", "cursor", "bluetooth"]
)
# Load tools from already installed package
install_tools(action="load", module="strands_tools", tool_names=["shell", "calculator"])
# List currently loaded tools
install_tools(action="list_loaded")
Static Tool Configuration
Format: package1:tool1,tool2;package2:tool3,tool4
# Minimal (shell + editor only)
export DEVDUCK_TOOLS="strands_tools:shell,editor"
# Dev essentials
export DEVDUCK_TOOLS="strands_tools:shell,editor,file_read,file_write,calculator"
# Full stack + GitHub
export DEVDUCK_TOOLS="devduck.tools:tcp,websocket,mcp_server,use_github;strands_tools:shell,editor,file_read"
devduck
Hot-Reload Tools from Directory
Create ./tools/weather.py:
from strands import tool
import requests
@tool
def weather(city: str) -> str:
"""Get weather for a city."""
r = requests.get(f"https://wttr.in/{city}?format=%C+%t")
return r.text
Enable directory auto-loading:
export DEVDUCK_LOAD_TOOLS_FROM_DIR=true
devduck
# Save weather.py โ use instantly (no restart needed)
Default: Directory loading is OFF. Use manage_tools() or install_tools() for explicit control.
MCP Integration
As MCP Server (Expose DevDuck)
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"devduck": {
"command": "uvx",
"args": ["devduck", "--mcp"]
}
}
}
Or start HTTP MCP server:
mcp_server(action="start", port=8000, stateless=True)
# Connect at: http://localhost:8000/mcp
Modes: --mcp (stdio for Claude Desktop) | http (background server) | stateless=True (multi-node)
As MCP Client (Load External Servers)
Expand capabilities by loading tools from external MCP servers:
export MCP_SERVERS='{
"mcpServers": {
"strands-docs": {"command": "uvx", "args": ["strands-agents-mcp-server"]},
"remote": {"url": "https://api.example.com/mcp", "headers": {"Auth": "Bearer token"}},
"custom": {"command": "python", "args": ["my_server.py"]}
}
}'
devduck
Supported transports: stdio (command/args/env) | HTTP (url/headers) | SSE (url with /sse path)
Tool prefixing: Each server's tools get prefixed (e.g., strands-docs_search_docs)
Advanced Features
State Management (Time-Travel)
Save and restore agent state for reproducibility:
# Export current state
state_manager(action="export", metadata={"note": "before refactor"})
# List saved states
state_manager(action="list")
# Load and display state
state_manager(action="load", state_file="~/.devduck/states/devduck_20250118_150000.pkl")
# Resume from state (ephemeral - doesn't mutate parent)
state_manager(
action="resume",
state_file="~/.devduck/states/devduck_20250118_150000.pkl",
query="continue the analysis from where we left off"
)
# Modify state metadata
state_manager(
action="modify",
state_file="path/to/state.pkl",
metadata={"tags": ["important", "refactor"]}
)
# Delete state
state_manager(action="delete", state_file="path/to/state.pkl")
States saved to: ~/.devduck/states/
System Prompt Management
Self-improvement - agent updates its own system prompt:
# View current system prompt
system_prompt(action="view")
# Add new context (appends to prompt)
system_prompt(action="add_context", context="New learning: Always use FastAPI for APIs")
# Update entire prompt
system_prompt(action="update", prompt="You are a specialized DevOps agent...")
# Sync to GitHub (persist across deployments)
system_prompt(
action="update",
prompt="Updated system prompt with new learnings...",
repository="cagataycali/devduck"
)
# Reset to default
system_prompt(action="reset")
Pattern: Learn โ Add context โ Sync to GitHub โ Persist forever
Knowledge Base (Auto-RAG)
Automatic memory across sessions:
export DEVDUCK_KNOWLEDGE_BASE_ID=your_kb_id
devduck
How it works:
- Before each query: Retrieves relevant context from KB
- After each response: Stores conversation for future reference
- No manual tool calls needed - fully automatic
Manual storage:
store_in_kb(
content="Important information to remember...",
title="Project Context",
knowledge_base_id="optional-kb-id"
)
Sub-Agent Creation
Delegate tasks to specialized agents via GitHub Actions:
# Create sub-agent with specific model and tools
create_subagent(
repository="owner/repo",
workflow_id="agent.yml",
task="Analyze this dataset and provide insights",
model="us.anthropic.claude-sonnet-4-20250514-v1:0",
provider="bedrock",
max_tokens=60000,
tools="file_read,python_repl,calculator,http_request"
)
# Custom system prompt for specialized behavior
create_subagent(
repository="owner/repo",
workflow_id="agent.yml",
task="Review code and suggest improvements",
tools="file_read,editor,shell",
system_prompt="You are a senior code reviewer focused on best practices"
)
# Check sub-agent status
create_subagent(action="status", repository="owner/repo", workflow_id="agent.yml", run_id="12345")
# List recent runs
create_subagent(action="list", repository="owner/repo", workflow_id="agent.yml")
๐ All Built-in Tools (38 total)
DevDuck Core (17 tools)
system_prompt- Update agent's system prompt (GitHub sync support)store_in_kb- Store content in Bedrock Knowledge Basestate_manager- Save/restore agent state (time-travel)tcp- TCP server with real-time streamingwebsocket- WebSocket server with concurrent messagingipc- Unix socket IPC server for local processesmcp_server- Expose as MCP server (HTTP/stdio)install_tools- Install packages and load tools at runtimecreate_subagent- Spawn sub-agents via GitHub Actionsuse_github- GitHub GraphQL API operationstray- System tray app control (macOS)ambient- Ambient AI input overlay (macOS)agentcore_config- Configure & launch on Bedrock AgentCoreagentcore_invoke- Invoke deployed AgentCore agentsagentcore_logs- View CloudWatch logs from agentsagentcore_agents- List/manage agent runtimesmanage_tools- Runtime tool add/remove/reloadview_logs- View/search/clear DevDuck logs
Strands Tools (13 tools)
shell- Interactive shell with PTY supporteditor- File editing (view/create/replace/insert/undo)file_read- Multi-file reading with search modesfile_write- Write content to filesfile_read- Read files with document mode for PDFs/CSVscalculator- SymPy-powered math (solve/derive/integrate)image_reader- Read images for Converse APIuse_agent- Nested agent with different modelload_tool- Load custom tools from Python filesenvironment- Environment variable managementmcp_client- Connect to external MCP servers autonomouslyretrieve- Bedrock Knowledge Base retrievalspeak- Text-to-speech (macOSsayor AWS Polly)slack- Slack messaging and event handling
Strands Fun Tools (6 tools - macOS)
listen- Background speech transcription (Whisper)cursor- Mouse & keyboard controlclipboard- Clipboard monitoring & controlscreen_reader- OCR & UI element detectionbluetooth- BLE scanning and GATT operationsyolo_vision- Object detection with YOLO
Community Tools (./tools/)
fetch_github_tool- Fetch and load tools from GitHub reposgist- Comprehensive GitHub Gist management (create/update/fork/star/comment)scraper- HTML/XML parsing with BeautifulSoup4add_comment- Add comments to GitHub issues/PRslist_issues- List GitHub repository issueslist_pull_requests- List GitHub repository PRs
Plus: Hot-reload tools from ./tools/ directory when DEVDUCK_LOAD_TOOLS_FROM_DIR=true
Hot-Reload Example
# ./tools/weather.py
from strands import tool
import requests
@tool
def weather(city: str) -> str:
"""Get weather for a city."""
r = requests.get(f"https://wttr.in/{city}?format=%C+%t")
return r.text
Save โ use instantly:
๐ฆ weather(city="Tokyo")
# Clear sky +15ยฐC
No restart. No configuration. Just works.
Access Methods
| Protocol | Endpoint | Test Command | Use Case |
|---|---|---|---|
| CLI | Terminal | devduck "query" |
Interactive/one-shot |
| Python | Import | import devduck; devduck("query") |
Script integration |
| TCP | localhost:9999 |
nc localhost 9999 |
Network clients |
| WebSocket | localhost:8080 |
wscat -c ws://localhost:8080 |
Browser/async apps |
| MCP | localhost:8000/mcp |
Add to Claude Desktop | MCP clients |
| IPC | /tmp/devduck_main.sock |
nc -U /tmp/devduck_main.sock |
Local processes |
Custom ports:
export DEVDUCK_TCP_PORT=9000 DEVDUCK_WS_PORT=8001 DEVDUCK_MCP_PORT=8002
devduck
Disable servers:
export DEVDUCK_ENABLE_TCP=false DEVDUCK_ENABLE_MCP=false
devduck
Configuration
| Variable | Default | Description |
|---|---|---|
| Model | ||
MODEL_PROVIDER |
Auto | Manual override: bedrock, anthropic, openai, github, gemini, cohere, writer, mistral, litellm, llamaapi, mlx, ollama |
STRANDS_MODEL_ID |
Auto | Model name (e.g., claude-sonnet-4, gpt-4o, qwen3:1.7b) |
| Provider API Keys | ||
ANTHROPIC_API_KEY |
- | Anthropic API key (auto-detected) |
OPENAI_API_KEY |
- | OpenAI API key (auto-detected) |
GOOGLE_API_KEY / GEMINI_API_KEY |
- | Google Gemini API key (auto-detected) |
GITHUB_TOKEN / PAT_TOKEN |
- | GitHub token for GitHub Models (auto-detected) |
COHERE_API_KEY |
- | Cohere API key (auto-detected) |
WRITER_API_KEY |
- | Writer API key (auto-detected) |
MISTRAL_API_KEY |
- | Mistral API key (auto-detected) |
LITELLM_API_KEY |
- | LiteLLM API key (auto-detected) |
LLAMAAPI_API_KEY |
- | LlamaAPI key (auto-detected) |
| Tools | ||
DEVDUCK_TOOLS |
38 tools | Format: package1:tool1,tool2;package2:tool3 |
DEVDUCK_LOAD_TOOLS_FROM_DIR |
false |
Auto-load from ./tools/ directory |
| Memory | ||
DEVDUCK_KNOWLEDGE_BASE_ID |
- | Bedrock KB ID for auto-RAG |
SYSTEM_PROMPT |
- | Additional system prompt content |
| MCP | ||
MCP_SERVERS |
- | JSON config for external MCP servers |
| Servers | ||
DEVDUCK_TCP_PORT |
9999 |
TCP server port |
DEVDUCK_WS_PORT |
8080 |
WebSocket server port |
DEVDUCK_MCP_PORT |
8000 |
MCP server port |
DEVDUCK_IPC_SOCKET |
/tmp/devduck_main.sock |
IPC socket path |
DEVDUCK_ENABLE_TCP |
true |
Enable TCP server |
DEVDUCK_ENABLE_WS |
true |
Enable WebSocket server |
DEVDUCK_ENABLE_MCP |
true |
Enable MCP server |
DEVDUCK_ENABLE_IPC |
true |
Enable IPC server |
| Context | ||
DEVDUCK_LOG_LINE_COUNT |
50 |
Recent log lines in context |
DEVDUCK_LAST_MESSAGE_COUNT |
200 |
Recent messages in context |
Troubleshooting
Ollama model not found:
# DevDuck auto-pulls models, but if it fails:
ollama pull qwen3:1.7b
Port already in use:
# Change ports
export DEVDUCK_TCP_PORT=9000
export DEVDUCK_WS_PORT=8001
devduck
Hot-reload not working:
# Ensure tools directory exists
mkdir -p ./tools
# Check file watcher logs
devduck
๐ฆ view_logs(action="search", pattern="watcher")
Memory/performance issues:
# Use lighter model
export STRANDS_MODEL_ID="qwen3:0.5b"
# Reduce context
export DEVDUCK_LOG_LINE_COUNT=20
export DEVDUCK_LAST_MESSAGE_COUNT=50
Ambient overlay not starting:
# Make sure tkinter is installed
python3 -c "import tkinter"
# Install tkinter if missing
brew install python-tk@3.13 # macOS
sudo apt-get install python3-tk # Ubuntu/Debian
sudo dnf install python3-tkinter # Fedora
Tray app not starting (macOS):
# Install rumps
pip install rumps
# Or reinstall devduck
pip install -e .
View logs: devduck โ ๐ฆ view_logs()
GitHub Actions
Run DevDuck in CI/CD pipelines:
name: AI Code Assistant
on:
issues:
types: [opened, edited]
pull_request:
types: [opened, edited, synchronize]
jobs:
devduck:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: cagataycali/devduck@main
with:
task: "Analyze and help with this issue or PR"
provider: "github"
model: "gpt-4o"
tools: "shell,file_read,file_write,use_github,calculator"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Sub-agent workflows:
devduck("Create a sub-agent to analyze test coverage")
Resources
- Strands SDK: github.com/strands-agents/sdk-python
- Documentation: strandsagents.com
- Web UI: cagataycali.github.io/devduck
Citation
@software{devduck2025,
author = {Cagatay Cali},
title = {DevDuck: Self-Modifying AI Agent with Hot-Reload and Multi-Protocol Servers},
year = {2025},
url = {https://github.com/cagataycali/devduck}
}
Apache 2.0 | Built with Strands Agents | @cagataycali
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 devduck-0.1.1766644714.tar.gz.
File metadata
- Download URL: devduck-0.1.1766644714.tar.gz
- Upload date:
- Size: 210.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffec702eac1017fd644bc96bcf101ab56b171a2d597a03b2974de0f915b591c6
|
|
| MD5 |
982361ec8b1664b6439b1bc5e16602c0
|
|
| BLAKE2b-256 |
5458785755ab41e237a9e42feffa1307f825f562145799e220bb75621ccde539
|
File details
Details for the file devduck-0.1.1766644714-py3-none-any.whl.
File metadata
- Download URL: devduck-0.1.1766644714-py3-none-any.whl
- Upload date:
- Size: 120.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e777b81e39878b8e8d0393aeb3ab00d281d175ca46c75dfe3af69c169c89772
|
|
| MD5 |
a67e756b6f0d843499b85b85baa8a2ab
|
|
| BLAKE2b-256 |
aa31109a986b96f852946b8e2bd2d369eafc4a8693d22c7eb1942328c710512a
|