An AI-assisted amateur radio packet station running on a Kantronics KPC-3 Plus TNC. The station (callsign W6OAK, Oakland CA, grid CM87) answers incoming connects over 2m packet and holds a short QSO using Claude Haiku as the control-operator-supervised operator. Ships with a Claude skill that teaches Claude (or any model) how to drive the TNC directly, plus a hand-curated map of the Northern California packet network.
Three independent but related pieces live here:
bot/w6oak_ai_bot.py— a Python bot that listens for incoming connects on the KPC-3+, auto-answers CQs, and chats back using the Anthropic API (Claude Haiku).skill/SKILL.md+skill/kpc3-packet-station.skill— a Claude skill for operating the TNC interactively from the Claude desktop app (Cowork mode).SKILL.mdis the source; the.skillfile is the installable bundle (built byskill/build_skill.sh).bot/NODE_PATHS.md— a hand-curated map of which nodes reach which other nodes on 145.050 MHz, used both by humans reading the skill and (via the bot) when planning multi-hop routes.
All three talk to the TNC over a persistent TCP serial bridge running on a Windows box, so there's no Remote Desktop, no PuTTY scraping, no clipboard hacks.
Claude / Bot (TCP) ──── network ──── Windows box on your LAN
│
kpc3_bridge.ps1 (port 8765)
│
COM port (USB serial)
│
KPC-3 Plus TNC
│
2m transceiver
│
Antenna
Any client on your LAN can connect to the Windows machine at TCP port 8765 and send/receive raw TNC bytes. PuTTY on the Windows machine can watch everything in real time at localhost:8765.
Kantronics KPC3+ Claude Skill/
├── README.md ← you are here
├── LICENSE
├── .gitignore
├── STATE.md ← project state / canonical entry point
├── CLAUDE.md ← session-start guide for Claude
├── _SESSION_START_PROMPT.md
├── NET_CONTROL_2026.md ← Sunday net-control playbook
├── pbbs_msg1_draft.md
├── sync_public.sh ← refresh public/ before pushing to GitHub
│
├── bot/ ← the bot and what it reads at runtime
│ ├── w6oak_ai_bot.py ← the bot
│ ├── beacon_manager.py
│ ├── config.example.json
│ ├── BOT_DESIGN_2026.md ← bot v2 architecture spec
│ ├── BTEXT_POOL.md ← beacon text pool
│ ├── W6OAK_BOT_OVERVIEW.md
│ ├── EMERGENCY_CONTACTS.md
│ ├── NODE_PATHS.md ← reachability map (edited here)
│ └── tests/
│
├── skill/ ← Claude skill content + operator tools
│ ├── SKILL.md ← the skill (source of truth)
│ ├── skill_frontmatter.yaml
│ ├── KANTRONICS_KPC3_REV-H.md
│ ├── KANTRONICS_KPC3_REV-H.pdf
│ ├── kpc3_console.py ← interactive TNC console (Mac)
│ ├── kpc3-packet-station.skill ← built bundle (redacted, public)
│ ├── test.skill
│ ├── build_skill.sh
│ ├── Launch KPC3 Console.command
│ └── Watch Bot.command
│
├── windows/ ← scripts that run on the Windows host
│ ├── kpc3_bridge.ps1 ← TCP serial bridge
│ ├── kpc3_register_task.ps1
│ └── w6oak_register_bot_task.ps1
│
├── archive/ ← historical / superseded files
├── design/ ← architecture diagrams
│
├── public/ ← sanitized, GitHub-ready copies (own .git)
│ └── (mirror of canonical with redactions, regenerated by sync_public.sh)
│
└── private/ ← operator-only / secrets (gitignored)
├── DEPLOYMENT_INVENTORY.md
├── DASHBOARD_INVENTORY.md
├── kpc3-packet-station.skill ← real values, gitignored
├── kpc3_ssh_key, kpc3_ssh_key.pub, config.json (gitignored, never to cloud)
└── logs/ (rotated bot/bridge logs from prior sessions)
How it works: you edit in the canonical zones (project root + the bot/, skill/, windows/ subdirs). The repo at the root is backed up to a private GitHub. When you're ready to publish a release to GitHub, run ./sync_public.sh — it copies the public-safe files into public/ (which has its own .git pointing at the public repo) and leaves secrets behind. private/'s contents are tracked by the private repo, but kpc3_ssh_key* and config.json stay disk-only.
| File | Purpose |
|---|---|
skill/SKILL.md |
The operating skill. ~1800 lines. Teaches Claude how to drive the KPC-3+: TCP bridge, mode switching, KPC3Session helper, KaNode vs K-Net, PBBS, Unproto, diagnostic playbooks. |
bot/NODE_PATHS.md |
Hand-curated reachability map for 145.050 MHz in NorCal. Read at boot by the bot, also referenced by SKILL.md as a companion file. Confirmed edges, degraded paths, a Path Cookbook, and live NODES/ROUTES captures from OAK, WBAY, and BANNER. |
NET_CONTROL_2026.md |
Playbook for running the Sunday 2000 hrs 145.05 Packet Net. Pre-net checklist, echo-test path, regional UNPROTO chains, and the 2021 → 2026 node-rename map. |
bot/BOT_DESIGN_2026.md |
Architecture spec for w6oak_ai_bot.py v2.0. Connected-only engagement, turn-taking rules, self-protection, lockout flag, logging split, and the negative spec of what the bot must never do. |
bot/w6oak_ai_bot.py |
The AI bot. Listens for RING / incoming connects, auto-answers CQs, routes conversations to Claude Haiku via the Anthropic API. Currently v2.5.2. |
skill/kpc3_console.py |
Minimal interactive TNC console for the Mac. python3 skill/kpc3_console.py gives you a live prompt to drive the TNC over the TCP bridge, with \r-only line endings and a background reader for TNC output. See "Operating the TNC manually from the Mac" in skill/SKILL.md. |
skill/kpc3-packet-station.skill |
Installable skill bundle (zipped). Drag into Claude desktop → Settings → Skills. Rebuilt by skill/build_skill.sh. |
bot/config.example.json |
Template config. Copy to private/config.json and fill in your own values. |
skill/KANTRONICS_KPC3_REV-H.md / .pdf |
The KPC-3 Plus User's Guide (Rev H). |
windows/kpc3_bridge.ps1 |
The TCP serial bridge that runs on the Windows host (deployed to C:\Users\youruser\ there). |
sync_public.sh |
Refreshes public/ from the canonical zones. Run before publishing. |
| Path | Purpose |
|---|---|
private/config.json |
Your real config — API key, tnc_host, mycall. Bot loads this on startup. |
private/kpc3_ssh_key / .pub |
SSH keypair the skill uses to restart the bridge on the Windows box. |
private/logs/ |
Rolling logs from the bot and the bridge. Forensic value; safe to prune. |
private/archive/ |
Old snapshots and one-off debug notes. Keep or delete as you like. |
private/ is tracked by the private git repo only — the top-level .gitignore keeps it out of the public release. Inside private/, the SSH key (kpc3_ssh_key*) and config.json are gitignored even from the private repo, so they stay disk-only (recoverable via Time Machine, not Git).
A complete, sanitized snapshot ready to git push to the public GitHub repo (you/kpc3-ai-bot). Regenerated by ./sync_public.sh, which mirrors the canonical subdir layout (bot/, skill/, plus root-level files) and runs sed redactions on the way over. Includes the public-safe canonical content; excludes private/, windows/, and disk-only secrets.
(The windows/kpc3_bridge.ps1 PowerShell script that runs the TCP bridge ships in this repo and is deployed to C:\Users\<you>\kpc3_bridge.ps1 on the Windows machine. See "Setting up the TCP bridge" below.)
| Callsign | W6OAK |
| Grid | CM87 (Oakland, CA) |
| PBBS | OBOX (/B) |
| KaNode | KOAK (/N) |
| K-Net node | OAK (W6OAK-5) |
| Digipeater | ON (/R) |
| TNC | Kantronics KPC-3+ |
| Bridge | TCP port 8765 on the Windows box |
pip install anthropic
# One-time config (put it in private/ so it never lands in git)
mkdir -p private
cp bot/config.example.json private/config.json
# edit private/config.json and set:
# - anthropic_api_key (from https://console.anthropic.com/settings/keys)
# - tnc_host (the LAN IP of your Windows box running the bridge)
# - tnc_port (default 8765)
# - mycall (your callsign)
python3 bot/w6oak_ai_bot.pyThe bot looks for private/config.json first and falls back to config.json at the root if that's missing, so either layout works.
What triggers a Haiku response:
- Someone connects to W6OAK directly (
CONNECT W6OAKfrom their TNC). The bot detects RING +*** CONNECTED to <call>and opens a chat session. - Someone sends a UI frame addressed to CQ. The bot auto-connects back and starts a session.
Users sign off with 73, BYE, B, QRT, SK, or CL. Idle sessions close after 5 minutes.
The bot keeps a heartbeat log and sets MCON OFF during active chats to avoid self-chat loops.
- Open the Claude desktop app on macOS.
- Settings → Skills → Add Skill.
- Drag
kpc3-packet-station.skillinto the window. - Mention the KPC-3, TNC, packet radio, PBBS, KaNode, K-Net, AX.25, etc. in a new Cowork session and the skill will activate.
Example prompts once installed:
- "Send an ID on the packet station"
- "Show me who's been heard recently"
- "Connect to OAK and show me the NODES list"
- "Check my PBBS messages"
- "Plan a path from here to HMKRCH"
The skill loads NODE_PATHS.md automatically when multi-hop questions come up.
The bridge is a PowerShell script (windows/kpc3_bridge.ps1 in the source repo) that opens the TNC's COM port at 9600 baud, binds TCP port 8765, and shuttles bytes both ways. Multiple clients can connect at once (bot + PuTTY monitor, for example). Register it as a Windows Scheduled Task named KPC3Bridge (use windows/kpc3_register_task.ps1) so it starts at login.
The skill knows how to restart the bridge remotely via SSH using the included kpc3_ssh_key.
Bridge log: C:\Users\<your-username>\kpc3_bridge.log
- The bot identifies as Claude Haiku in its system prompt and will answer honestly if asked.
- No encryption, no music, no one-way broadcasts. FCC Part 97 compliant.
- Keep replies under 120 chars. 1200 baud isn't infinite bandwidth.
- The beacon clearly announces "AI-assisted station" to give other ops a heads-up before they connect.
Issues and PRs welcome, especially:
- Better CQ detection (current regex only matches destination-field CQ, not payload CQ)
- Additional node-network awareness in the system prompt
- Support for TNC firmware variants beyond the KPC-3+
MIT — see LICENSE.
The idea, design, and direction of this project are by Hugo Campos (W6OAK). The code was authored by Claude (Anthropic's AI assistant) at Hugo's request and under his supervision.
de W6OAK