Metadata-Version: 2.4
Name: devduck
Version: 1.10.5
Summary: 🦆 Self-adapting agent - one file.
Author-email: Cagatay Cali <cagataycali@icloud.com>
License: Apache-2.0
Project-URL: Homepage, https://github.com/cagataycali/devduck
Project-URL: Repository, https://github.com/cagataycali/devduck.git
Project-URL: Documentation, https://github.com/cagataycali/devduck#readme
Project-URL: Bug Tracker, https://github.com/cagataycali/devduck/issues
Keywords: ai,agent,minimalist,self-healing,ollama,strands-agents
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: <3.14,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: strands-agents
Requires-Dist: prompt_toolkit
Requires-Dist: strands-agents[ollama]
Requires-Dist: strands-agents[anthropic]
Requires-Dist: strands-agents[openai]
Requires-Dist: strands-agents[otel]
Requires-Dist: strands-agents-tools
Requires-Dist: beautifulsoup4
Requires-Dist: colorama
Requires-Dist: websockets
Requires-Dist: strands-mcp-server
Requires-Dist: strands-google
Requires-Dist: bedrock-agentcore-starter-toolkit
Requires-Dist: bedrock-agentcore
Requires-Dist: rumps; sys_platform == "darwin"
Requires-Dist: strands-mlx; sys_platform == "darwin"
Requires-Dist: eclipse-zenoh
Requires-Dist: halo
Requires-Dist: textual>=0.80
Requires-Dist: strands-agents[bidi-all]
Requires-Dist: openai-whisper
Requires-Dist: webrtcvad
Requires-Dist: sounddevice
Provides-Extra: rl
Requires-Dist: stable-baselines3[extra]; extra == "rl"
Requires-Dist: gymnasium; extra == "rl"
Dynamic: license-file

<p align="center">
  <img src="duck-animated.svg" alt="DevDuck" width="160" height="160">
</p>

# 🦆 DevDuck

[![PyPI](https://badge.fury.io/py/devduck.svg)](https://pypi.org/project/devduck/)

**One file. Self-healing. Builds itself as it runs.**

An AI agent that hot-reloads its own code, fixes itself when things break, and expands capabilities at runtime. Terminal, browser, cloud — or all at once.

```bash
pipx install devduck && devduck
```

<p align="center">
  <img src="devduck-launcher.jpg" alt="DevDuck Launcher" width="700">
</p>

<p align="center">
  <video src="https://github.com/cagataycali/devduck/raw/main/devduck-intro.mp4" width="700" controls autoplay muted>
    <a href="https://redduck.dev/videos/devduck-intro.mp4">Watch the intro</a>
  </video>
</p>

---

## What It Does

- **Hot-reloads** — edit source, agent restarts instantly
- **Self-heals** — errors trigger automatic recovery
- **60+ tools** — shell, GitHub, browser control, speech, scheduler, ML, messaging
- **Multi-protocol** — CLI, TUI, WebSocket, TCP, MCP, IPC, Zenoh P2P
- **Unified mesh** — terminal + browser + cloud agents in one network
- **Deploys anywhere** — `devduck deploy --launch` → AWS AgentCore

**Requirements:** Python 3.10–3.13 + any model provider (AWS, Anthropic, OpenAI, Ollama, Gemini, etc.)

---

## Quick Start

```bash
devduck                              # interactive REPL
devduck --tui                        # multi-conversation terminal UI
devduck "create a REST API"          # one-shot
devduck --record                     # record session for replay
devduck --resume session.zip         # resume from snapshot
devduck deploy --launch              # ship to AgentCore
```

```python
import devduck
devduck("analyze this code")
```

---

## Power User Setup

A real-world `.zshrc` config for daily driving DevDuck with all the bells and whistles:

```bash
# Model — Claude Opus via Bedrock bearer token (fastest auth, no STS calls)
export AWS_BEARER_TOKEN_BEDROCK="ABSK..."
export STRANDS_MODEL_ID="global.anthropic.claude-opus-4-6-v1"
export STRANDS_MAX_TOKENS="64000"

# Tools — curated toolset (loads faster than all 60+)
export DEVDUCK_TOOLS="devduck.tools:use_github,editor,system_prompt,store_in_kb,manage_tools,websocket,zenoh_peer,agentcore_proxy,manage_messages,sqlite_memory,dialog,listen,use_computer,tasks,scheduler,telegram;strands_tools:retrieve,shell,file_read,file_write,use_agent"

# Knowledge Base — automatic RAG (stores & retrieves every conversation)
export STRANDS_KNOWLEDGE_BASE_ID="YOUR_KB_ID"

# MCP — auto-load Strands docs server
export MCP_SERVERS='{"mcpServers":{"strands-docs":{"command":"uvx","args":["strands-agents-mcp-server"]}}}'

# Messaging — Telegram & Slack bots
export TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
export SLACK_BOT_TOKEN="xoxb-your-slack-bot-token"
export SLACK_APP_TOKEN="xapp-your-slack-app-token"

# Spotify control
export SPOTIFY_CLIENT_ID="your-client-id"
export SPOTIFY_CLIENT_SECRET="your-client-secret"
export SPOTIFY_REDIRECT_URI="http://127.0.0.1:8888/callback"

# Gemini as fallback/sub-agent model
export GEMINI_API_KEY="your-gemini-key"
```

This gives you:
- 🧠 **Opus on Bedrock** as primary model with bearer token (zero-latency auth)
- 📚 **Auto-RAG** — every conversation stored in Knowledge Base, context retrieved before each query
- 📖 **Strands docs** available as MCP tools (search + fetch)
- 📱 **Telegram + Slack + WhatsApp** — three messaging channels ready
  - Telegram & Slack: set tokens above, then `telegram(action="start_listener")`
  - WhatsApp: no token needed — uses local `wacli` pairing, just `whatsapp(action="start_listener")`
- 🎵 **Spotify** control via `use_spotify`
- 🔗 **Zenoh P2P + mesh** auto-enabled (multi-terminal awareness)
- 💬 **26 tools loaded** on startup, expandable to 60+ on demand via `manage_tools`

---

## Model Detection

Set your key. DevDuck figures out the rest.

```bash
export ANTHROPIC_API_KEY=sk-ant-...   # → uses Anthropic
export OPENAI_API_KEY=sk-...          # → uses OpenAI
export GOOGLE_API_KEY=...             # → uses Gemini
# or just have AWS credentials        # → uses Bedrock
# or nothing at all                   # → uses Ollama
```

**Priority:** Bedrock → Anthropic → OpenAI → GitHub → Gemini → Cohere → Writer → Mistral → LiteLLM → LlamaAPI → MLX → Ollama

Override: `MODEL_PROVIDER=bedrock STRANDS_MODEL_ID=us.anthropic.claude-sonnet-4-20250514-v1:0 devduck`

---

## Tools

### Runtime — no restart needed

```python
manage_tools(action="add", tools="strands_fun_tools.cursor")
manage_tools(action="create", code='...')
manage_tools(action="fetch", url="https://github.com/user/repo/blob/main/tool.py")
```

### Hot-reload from disk

Drop a `.py` file in `./tools/` → it's available immediately.

```python
# ./tools/weather.py
from strands import tool
import requests

@tool
def weather(city: str) -> str:
    """Get weather for a city."""
    return requests.get(f"https://wttr.in/{city}?format=%C+%t").text
```

### Static config

```bash
export DEVDUCK_TOOLS="strands_tools:shell,editor;devduck.tools:use_github,scheduler"
```

---

## Architecture

```
devduck/
├── __init__.py       # the whole agent — single file
├── tui.py            # multi-conversation Textual UI
├── tools/            # 60+ built-in tools (hot-reloadable)
└── agentcore_handler.py  # AWS AgentCore deployment handler
```

```mermaid
graph LR
    User([👤 User]) --> Interface
    subgraph Interface[" "]
        CLI["CLI / REPL"]
        TUI["TUI"]
        WS["WebSocket"]
        TCP["TCP"]
        MCP["MCP"]
    end
    Interface --> Core["🦆 DevDuck Core"]
    Core --> Tools["🔧 Tools"]
    Core <--> Zenoh["🔗 Zenoh P2P"]
    Core <--> KB["📚 Knowledge Base"]
    Core <--> Mesh["🌐 Unified Mesh"]
    Mesh --> Browser["🖥️ Browser"]
    Mesh --> Cloud["☁️ AgentCore"]

    style Core fill:#f5a623,stroke:#333,color:#000
    style Mesh fill:#4a90d9,stroke:#333,color:#fff
    style Zenoh fill:#7ed321,stroke:#333,color:#000
    style KB fill:#9b59b6,stroke:#333,color:#fff
```

**Ports:** 10000 (mesh relay) · 10001 (WebSocket) · 10002 (TCP) · 10003 (MCP)

### TUI Concurrency Model

The TUI (`devduck --tui`) supports true concurrent conversations with shared awareness:

```mermaid
graph TB
    subgraph SharedMessages["📋 SharedMessages (thread-safe)"]
        msgs["msg1, msg2, msg3, msg4, ..."]
    end

    SharedMessages --> A1
    SharedMessages --> A2
    SharedMessages --> A3

    subgraph A1["🟦 Agent #1"]
        cb1["callback → panel #1"]
    end
    subgraph A2["🟩 Agent #2"]
        cb2["callback → panel #2"]
    end
    subgraph A3["🟨 Agent #3"]
        cb3["callback → panel #3"]
    end

    style SharedMessages fill:#e74c3c,stroke:#333,color:#fff
    style A1 fill:#3498db,stroke:#333,color:#fff
    style A2 fill:#2ecc71,stroke:#333,color:#fff
    style A3 fill:#f1c40f,stroke:#333,color:#000
```

Each conversation creates a **fresh Agent** (like TCP/Telegram tools do), but all agents point their `.messages` at a single `SharedMessages` instance — a thread-safe list subclass that serializes all reads and writes via a lock. This gives you:

- **True concurrency** — separate Agent instances with separate callback handlers, no conflicts
- **Real-time shared awareness** — when Agent #1 appends a message, Agent #2 sees it immediately on its next loop iteration
- **Correct ordering** — the lock ensures messages are appended in the order they're produced
- **Isolated rendering** — each agent's callback handler routes streaming output to its own color-coded TUI panel

The shared history is capped at 100 messages (configurable via `DEVDUCK_TUI_MAX_SHARED_MESSAGES`) and auto-clears on context window overflow.

**Comparison across interfaces:**

| Interface | Agent per request | Shared messages | Use case |
|-----------|:-:|:-:|---|
| **CLI** | No (reuse one) | N/A (single-threaded) | Sequential interactive REPL |
| **TUI** | Yes (fresh Agent) | Yes (`SharedMessages`) | Concurrent conversations with shared context |
| **TCP** | Yes (fresh DevDuck) | No (fully isolated) | External network clients |
| **Telegram** | Yes (fresh DevDuck) | No (fully isolated) | Chat bot, each user isolated |
| **WebSocket** | Yes (fresh DevDuck) | No (fully isolated) | Browser clients |

---

## Multi-Agent Networking

### Zenoh P2P — zero config

```bash
# Terminal 1
devduck   # → Zenoh peer: hostname-abc123

# Terminal 2
devduck   # auto-discovers Terminal 1
```

```python
zenoh_peer(action="broadcast", message="git pull && npm test")  # all peers
zenoh_peer(action="send", peer_id="hostname-abc123", message="status?")  # one peer
```

Cross-network: `ZENOH_CONNECT=tcp/remote:7447 devduck`

### Unified Mesh — everything connected

The mesh is DevDuck's shared nervous system. Every agent — regardless of where it runs — sees what others are doing via a **ring context** (a shared circular buffer of recent activity).

```mermaid
graph TB
    subgraph Mesh["🌐 Unified Mesh (port 10000)"]
        direction TB

        T1["🖥️ Terminal DevDuck<br/>(Zenoh)"]
        T2["🖥️ Terminal DevDuck<br/>(Zenoh)"]
        B1["🌍 Browser Tab<br/>(WebSocket)"]
        AC["☁️ AgentCore<br/>(AWS Cloud)"]
        GH["🐙 GitHub Actions<br/>(HTTPS)"]

        Ring[("🔄 Ring Context<br/>shared memory<br/>last 100 msgs")]

        T1 <--> Ring
        T2 <--> Ring
        B1 <--> Ring
        AC <--> Ring
        GH <--> Ring
    end

    Registry["📁 mesh_registry.json<br/>(file-based, TTL)"]
    Relay["📡 Relay Server<br/>ws://localhost:10000"]

    Ring --> Registry
    Ring --> Relay

    style Mesh fill:#1a1a2e,stroke:#4a90d9,color:#fff
    style Ring fill:#f5a623,stroke:#333,color:#000
    style T1 fill:#7ed321,stroke:#333,color:#000
    style T2 fill:#7ed321,stroke:#333,color:#000
    style B1 fill:#4a90d9,stroke:#333,color:#fff
    style AC fill:#9b59b6,stroke:#333,color:#fff
    style GH fill:#333,stroke:#fff,color:#fff
    style Registry fill:#e74c3c,stroke:#333,color:#fff
    style Relay fill:#3498db,stroke:#333,color:#fff
```

**Four peer types, one network:**

| Peer Type | Discovery | Transport | Example |
|-----------|-----------|-----------|---------|
| **Zenoh** | Multicast scouting (224.0.0.224:7446) | P2P UDP/TCP | Two terminal DevDucks auto-find each other |
| **Browser** | WebSocket connect to :10000 | WS | `mesh.html` or custom web UI registers as peer |
| **AgentCore** | AWS API (`ListAgentRuntimes`) | HTTPS | Cloud-deployed agents via `devduck deploy` |
| **GitHub** | GitHub Actions API | HTTPS | Workflow-based agents from configured repos |

**How it works:**

1. **Registry** (`mesh_registry.py`) — File-based agent registry with TTL. Any process can read/write. Zenoh peers, browser tabs, and local agents all register here.

2. **Ring Context** (`unified_mesh.py`) — In-memory circular buffer (last 100 entries). When any agent does something, it's pushed to the ring. CLI DevDuck injects ring context into every query so it knows what browser/cloud agents are doing.

3. **Relay** (`agentcore_proxy.py`) — WebSocket server on port 10000 that bridges everything:
   - Browser connects → gets real-time `ring_update` events
   - Browser sends `invoke` → routes to Zenoh peer or AgentCore agent
   - CLI writes to ring → browser gets notified instantly
   - Handles `list_peers`, `invoke`, `broadcast`, `get_ring`, `add_ring`

4. **Zenoh** (`zenoh_peer.py`) — P2P layer for terminal-to-terminal. Heartbeats every 5s, auto-prune stale peers, command execution on remote peers.

**Ring context injection** — every CLI query automatically includes recent mesh activity:
```
[14:20:59] local:devduck-tui (local [tui]): Q: deploy API → Done ✅
[14:21:05] browser:react-app (browser [ws]): Built component library
[14:21:10] agentcore:reviewer (cloud [aws]): PR #42 approved
```

This means your terminal DevDuck is always aware of what your browser agent and cloud agents just did — no explicit sync needed.

**WebSocket protocol** (port 10000):
```json
{"type": "list_peers"}                              // all peers across all layers
{"type": "invoke", "peer_id": "...", "prompt": "..."} // invoke any peer
{"type": "broadcast", "message": "..."}              // send to all Zenoh peers
{"type": "get_ring", "max_entries": 20}              // recent activity
{"type": "add_ring", "agent_id": "my-bot", "text": "done"}  // push to ring
{"type": "register_browser_peer", "name": "my-ui", "model": "gpt-4o"}  // join mesh
```

---

## Deploy

```bash
devduck deploy --launch
devduck deploy --name reviewer --tools "strands_tools:shell,editor" --launch
devduck list        # see deployed agents
devduck invoke "analyze code" --name reviewer
```

---

## Session Recording & Resume

```bash
devduck --record                  # captures sys/tool/agent events
devduck --resume session.zip      # restores conversation + state
devduck --resume session.zip "continue where we left off"
```

```python
from devduck import load_session
session = load_session("session.zip")
session.resume_from_snapshot(2, agent=devduck.agent)
```

Asciinema: `DEVDUCK_ASCIINEMA=true devduck` → shareable `.cast` files.

---

## Background Modes

```bash
# Standard ambient — thinks while you're idle
DEVDUCK_AMBIENT_MODE=true devduck

# Autonomous — works until done
🦆 auto
# Agent signals [AMBIENT_DONE] when finished
```

---

## Messaging

```bash
# Telegram
TELEGRAM_BOT_TOKEN=... STRANDS_TELEGRAM_AUTO_REPLY=true devduck
telegram(action="start_listener")

# Slack
SLACK_BOT_TOKEN=xoxb-... SLACK_APP_TOKEN=xapp-... devduck
slack(action="start_listener")

# WhatsApp (via wacli, no Cloud API)
whatsapp(action="start_listener")
```

Each incoming message spawns a fresh DevDuck with full tool access.

---

## MCP

**Expose as server** (Claude Desktop):
```json
{"mcpServers": {"devduck": {"command": "uvx", "args": ["devduck", "--mcp"]}}}
```

**Load external servers:**
```bash
export MCP_SERVERS='{"mcpServers": {"docs": {"command": "uvx", "args": ["strands-agents-mcp-server"]}}}'
```

---

## macOS

```python
use_mac(action="calendar.events", days=7)
use_mac(action="mail.send", to="x@y.com", subject="Hi", body="Hello")
use_mac(action="safari.read")
use_mac(action="system.screenshot", path="/tmp/shot.png")
use_mac(action="system.dark_mode", enable=True)
use_mac(action="keychain.get", service="MyApp", account="me")

apple_notes(action="list")
use_spotify(action="now_playing")
```

---

## More Tools

| Tool | What |
|------|------|
| `shell` | Interactive PTY shell |
| `editor` | File create/replace/insert/undo |
| `use_github` | GitHub GraphQL API |
| `use_computer` | Mouse, keyboard, screenshots |
| `listen` | Background Whisper transcription |
| `lsp` | Language server diagnostics |
| `scheduler` | Cron + one-time jobs |
| `tasks` | Parallel background agents |
| `sqlite_memory` | Persistent memory with FTS |
| `dialog` | Rich terminal UI dialogs |
| `speech_to_speech` | Nova Sonic / OpenAI / Gemini voice |
| `rl` | Train RL agents, fine-tune LLMs |
| `scraper` | HTML/XML parsing |
| `use_agent` | Nested agents with different models |
| `retrieve` / `store_in_kb` | Bedrock Knowledge Base RAG |

<details>
<summary><strong>All 60+ tools</strong></summary>

**Core:** system_prompt · manage_tools · manage_messages · tasks · scheduler · sqlite_memory · dialog · notify · use_computer · listen · lsp · tui · session_recorder · view_logs

**Network:** tcp · websocket · ipc · mcp_server · zenoh_peer · agentcore_proxy · unified_mesh · mesh_registry · jsonrpc

**Platform:** use_mac · apple_notes · use_spotify · telegram · whatsapp · slack

**Cloud:** use_github · fetch_github_tool · gist · agentcore_config · agentcore_invoke · agentcore_logs · agentcore_agents · create_subagent · store_in_kb · retrieve

**AI/ML:** rl · speech_to_speech · use_agent · scraper

**macOS Native:** apple_nlp · apple_vision · apple_wifi · apple_sensors · apple_smc

**Strands:** shell · editor · file_read · file_write · calculator · image_reader · speak

</details>

---

## AGENTS.md

Drop an `AGENTS.md` in your working directory. DevDuck auto-loads it into the system prompt. No config needed.

```markdown
# AGENTS.md
## Project: My API
- Framework: FastAPI
- Tests: pytest
- Deploy: Docker on ECS
```

---

## Config Reference

<details>
<summary><strong>All environment variables</strong></summary>

| Variable | Default | What |
|----------|---------|------|
| `MODEL_PROVIDER` | auto | `bedrock` `anthropic` `openai` `github` `gemini` `cohere` `writer` `mistral` `litellm` `llamaapi` `mlx` `ollama` |
| `STRANDS_MODEL_ID` | auto | Model name |
| `DEVDUCK_TOOLS` | 60+ tools | `package:tool1,tool2;package2:tool3` |
| `DEVDUCK_LOAD_TOOLS_FROM_DIR` | `false` | Auto-load `./tools/*.py` |
| `DEVDUCK_KNOWLEDGE_BASE_ID` | — | Bedrock KB for auto-RAG |
| `MCP_SERVERS` | — | JSON config for MCP servers |
| `DEVDUCK_ENABLE_WS` | `true` | WebSocket server |
| `DEVDUCK_ENABLE_ZENOH` | `true` | Zenoh P2P |
| `DEVDUCK_ENABLE_AGENTCORE_PROXY` | `true` | Mesh relay |
| `DEVDUCK_ENABLE_TCP` | `false` | TCP server |
| `DEVDUCK_ENABLE_MCP` | `false` | MCP HTTP server |
| `DEVDUCK_ENABLE_IPC` | `false` | IPC socket |
| `DEVDUCK_WS_PORT` | `10001` | WebSocket port |
| `DEVDUCK_TCP_PORT` | `10002` | TCP port |
| `DEVDUCK_MCP_PORT` | `10003` | MCP port |
| `DEVDUCK_AGENTCORE_PROXY_PORT` | `10000` | Mesh relay port |
| `DEVDUCK_AMBIENT_MODE` | `false` | Background thinking |
| `DEVDUCK_AMBIENT_IDLE_SECONDS` | `30` | Idle before ambient starts |
| `DEVDUCK_AMBIENT_MAX_ITERATIONS` | `3` | Max ambient iterations |
| `DEVDUCK_AUTONOMOUS_MAX_ITERATIONS` | `100` | Max autonomous iterations |
| `DEVDUCK_ASCIINEMA` | `false` | Record `.cast` files |
| `DEVDUCK_TUI_MAX_SHARED_MESSAGES` | `100` | Max shared message history in TUI |
| `DEVDUCK_LSP_AUTO_DIAGNOSTICS` | `false` | Auto LSP after edits |
| `TELEGRAM_BOT_TOKEN` | — | Telegram bot |
| `SLACK_BOT_TOKEN` | — | Slack bot |
| `SPOTIFY_CLIENT_ID` | — | Spotify |

</details>

---

## Dev Setup

```bash
git clone git@github.com:cagataycali/devduck.git && cd devduck
python3.13 -m venv .venv && source .venv/bin/activate
pip install -e . && devduck
```

---

## GitHub Actions

```yaml
- uses: cagataycali/devduck@main
  with:
    task: "Review this PR"
    provider: "github"
    model: "gpt-4o"
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

---

## Citation

```bibtex
@software{devduck2025,
  author = {Cagatay Cali},
  title = {DevDuck: Self-Modifying AI Agent},
  year = {2025},
  url = {https://github.com/cagataycali/devduck}
}
```

---

**Apache 2.0** · Built with [Strands Agents](https://strandsagents.com) · [@cagataycali](https://github.com/cagataycali)
