Skip to content

efischer19/woodwire

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

209 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Woodwire

Secure, asynchronous chat between a static web app and a local AI bot.

Woodwire is an event-driven system for private, multimodal communication between a browser-based PWA and a local bot process. The frontend stays static and credential-free, while a Cloudflare Worker and AWS services coordinate message flow.

πŸš€ Quick Start | πŸ€– OpenClaw | πŸ“š Architecture | πŸ”— Docs

About the Name

Woodwire captures the spirit of this project. I'm the type who would choose build a wood cabin in the mountains β€” except in this case it's not a cabin, it's a "wooden" telephone line to my local AI. The name evokes both the analog simplicity of a cabin phone line and the digital connection to an AI that lives on your own machine.

This is an OpenClaw Channel

While Woodwire supports multiple AI backends (OpenClaw, Ollama, or mock), it's designed with OpenClaw as the first-class integration. If you're looking for a secure, locally-hosted chat interface for OpenClaw, Woodwire is built for you.

Key Features

  • Private & Encrypted β€” Messages stay in your control; optional client-side AES-256-GCM encryption
  • Credential-Free Frontend β€” Static PWA with no hardcoded secrets; all auth happens at the edge
  • Zero-Trust Gateway β€” Cloudflare Worker validates every request with a shared passphrase
  • Multimodal β€” Text, images, audio attachments; automatic voice transcription and synthesis
  • Outbound-Only Bot β€” Local bot never exposes ports; all communication is pull-based via SQS + S3
  • No Build Required β€” Frontend is vanilla HTML/CSS/JS; deploy directly to S3/CloudFront or GitHub Pages
  • Infrastructure as Code β€” CloudFormation templates for reproducible AWS deployments

Architecture Overview

Message Flow: Inbound Pipeline (Browser β†’ Bot)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    INBOUND PIPELINE                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  [ Browser PWA ]  ──► [ Cloudflare Worker ]  ──► [ AWS SQS ]   β”‚
β”‚    (Static)           (Zero-trust auth)         (Event buffer)  β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. User sends message from PWA
  2. Worker validates X-Woodwire-Auth header
  3. Message is forwarded to SQS queue
  4. Local bot polls SQS and processes

Message Flow: Outbound Pipeline (Bot β†’ Browser)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    OUTBOUND PIPELINE                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  [ Local Bot ]  ──► [ Private S3 Bucket ]  ──► [ Browser polls]β”‚
β”‚   (OpenClaw/etc)     (outbox/ responses)       (via Worker)     β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Bot processes inbound message
  2. Bot writes response to S3 outbox/
  3. Browser polls Worker for status
  4. Worker retrieves response from S3 and returns to browser

Repository Structure

Woodwire follows the monorepo layout defined in ADR-006:

woodwire/
β”œβ”€β”€ src/              # PWA frontend (HTML/CSS/JS) β†’ deploys to S3/CloudFront
β”œβ”€β”€ bot/              # Local Python bot (SQS poller, LLM orchestrator)
β”œβ”€β”€ worker/           # Cloudflare Worker source (zero-trust gateway)
β”œβ”€β”€ infra/            # AWS CloudFormation templates (IaC)
β”œβ”€β”€ meta/             # ADRs, design docs, philosophy
└── .github/          # CI/CD workflows

Documentation

Each component has its own detailed documentation:

  • QUICK_START.md β€” Setup guide from AWS account to running chat
  • src/README.md β€” Frontend architecture, accessibility, conventions
  • worker/README.md β€” Cloudflare Worker API contract, auth, deployment
  • bot/README.md β€” Local bot setup, AI backends, voice support, troubleshooting
  • infra/README.md β€” AWS infrastructure stacks, IAM setup, parameters

Quick Start

To get up and running:

  1. Follow the QUICK_START.md for step-by-step AWS, Worker, bot, and PWA setup

  2. Or skip to component-specific docs:

Development

Local Quality Checks

Before committing, run the project's linters and tests:

# Pre-commit hooks
pip install pre-commit
pre-commit run --all-files

# Markdown linting
npx --yes markdownlint-cli2 "**/*.md"

# HTML linting
npx --yes htmlhint "src/**/*.html"

# Bot unit tests
cd bot
uv sync
python -m unittest discover -s tests -v

# Worker tests
npx --yes vitest run worker/index.test.js

Development Philosophy

Development standards and contributor expectations are documented in meta/DEVELOPMENT_PHILOSOPHY.md. Please read this before contributing.

Architecture Decisions

This project uses Architecture Decision Records (ADRs) to document significant design choices. Before proposing a major change, review existing ADRs in meta/adr/.

Encryption & Security

Client-Side E2EE (Schema Version 2)

Optional AES-256-GCM encryption between browser and bot:

# Generate a 32-byte base64 key
openssl rand -base64 32

# Set on bot
export WOODWIRE_E2EE_KEY=your-base64-key
python bot/main.py

# Set in PWA settings (exact same key)

The Cloudflare Worker intentionally does not receive this keyβ€”it never has the ability to decrypt messages.

Schema Version 1 (Legacy, Unencrypted)

For backwards compatibility, unencrypted messages continue to work.

Contributing

This project was built for personal use. While you're welcome to clone, fork, and use it, expect limited maintenance. For bugs, ideas, or questions, feel free to open an issueβ€”but understand that responses may be infrequent.

See CONTRIBUTING.md for more details.

License

This project is licensed under the MIT License.

Resources

About

Woodwire is an asynchronous, event-driven pipeline that establishes a highly secure, private communication channel between a user and a local AI agent. Built entirely on Cloudflare and AWS serverless infrastructure, it eliminates the need for traditional WebSockets or active server hosting.

Resources

License

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors