honk-user-guide
HONK User Guide
The functor F: FS β DNS preserves structure. This tool is the morphism.
Installation
# Clone from sourcehut
git clone https://git.sr.ht/~graemefawcett/honk
cd honk
# Install as Python module
pip install -e .
# Or install directly
pip install git+https://git.sr.ht/~graemefawcett/honk
# Verify
honk --help
# Initialize config
honk initQuick Start
Reading from DNS
# Fetch content to file
honk get pelicans
# Creates pelicans.out (27KB JPEG)
# Output to stdout
honk cat rss | bash
# Executes the RSS discovery command
# Specify domain
honk get mydata --domain=example.comWriting to DNS
# Configure credentials first
vim ~/.config/honk/config.json
# Upload a file
honk put myimage photo.jpg
# With gzip compression (sets flag 0x0001)
honk put myimage photo.jpg --gzip
# With custom flags
honk put myscript install.sh --flags=4 # EXEC flagUnicode Mode
# Encode text as AAAA records
honk unicode "HONKπͺΏβ€"
# Output:
# example.com. AAAA 0001:0048:004f:004e:004b:d83e:debf:2764
# Decode AAAA records
honk unicode-get haiku --domain=loss.devShell Integration
# Print shell function to add to ~/.bashrc
honk install >> ~/.bashrc
source ~/.bashrc
# Now use directly
honk_get pelicans > pelican.jpg
honk_get rss | bashConfiguration
Config file: ~/.config/honk/config.json
{
"domain": "loss.dev",
"dns_provider": "dnsmadeeasy",
"dnsmadeeasy": {
"api_key": "your-api-key",
"secret_key": "your-secret-key",
"domain_id": "123456"
},
"chunk_size": 250,
"default_ttl": 300
}Getting DNS Made Easy Credentials
- Log in to https://dnsmadeeasy.com
- Go to Account β API Credentials
- Generate API key and secret
- Find domain ID in the DNS management dashboard URL
Commands
| Command | Description |
|---|---|
| File Operations | |
honk get <name> |
Fetch content via SRV manifest |
honk put <name> <file> |
Upload content to DNS (auto-detects flags) |
honk cat <name> |
Output content to stdout |
honk ls |
List all HONK resources with metadata |
honk tree <name> |
Show resource structure |
| Queue Primitives | |
honk enqueue <queue> <payload> |
Add JSON to queue (timestamped TXT) |
honk dequeue <queue> |
Pop oldest unread item, update offset |
honk dequeue <queue> --peek |
Read without updating offset |
honk qdepth <queue> |
Get unread count |
honk qdepth <queue> --all |
Show total/unread/offset breakdown |
| Counter Primitives | |
honk incr <counter> [amount] |
Increment CRDT counter (AAAA record) |
honk counter <counter> |
Read counter total (sum all nodes) |
| Encoding | |
honk encode <file> |
Encode file to JSON chunks |
honk decode <out> <chunks...> |
Decode chunks to file |
honk unicode <text> |
Encode text as AAAA records |
honk unicode-get <name> |
Decode AAAA records as UTF-16 |
| Setup | |
honk init |
Create config file |
honk domains |
List available domains |
honk domains --set |
Set domain_id interactively |
Flags (Capability Bitfield)
The SRV port field is a 16-bit capability bitfield. Bit 0 (HONK) is always set.
| Flag | Hex | Meaning |
|---|---|---|
| HONK | 0x0001 | Protocol marker (always set) |
| GZIP | 0x0002 | Content is gzip compressed |
| URL | 0x0004 | Content is a URL |
| EXEC | 0x0008 | Content is executable |
| BINARY | 0x0010 | Content is base64 binary |
| IMAGE | 0x0020 | Content is an image |
| UTF16 | 0x0040 | Content is UTF-16 encoded |
| ENCRYPTED | 0x0080 | Content is encrypted |
| SIGNED | 0x0100 | Content has signature |
Common combinations:
0x0001(H) - Raw text0x0003(HG) - Gzipped text0x0011(HB) - Binary (no compression)0x0031(HBI) - Image0x000B(HGX) - Gzipped executable
honk put auto-detects flags from file type. Use -y to accept without prompting.
How It Works
Queue System
Queues use timestamped TXT records. No deletes needed - offset tracking handles consumption.
# Queue items (timestamped)
_1766099487050.jobs.q.loss.dev TXT '{"task":"build"}'
_1766099487051.jobs.q.loss.dev TXT '{"task":"deploy"}'
# Offset per consumer (tracks last-read timestamp)
_a25a.jobs.offset.loss.dev TXT "1766099487050"Dequeue flow:
- Read offset for this node
- Find items where timestamp > offset
- Return oldest unread
- Update offset to that timestamp
Multiple consumers each track their own offset (like Kafka consumer groups).
Counter System (CRDT)
Counters use AAAA records. Each node writes its own record; readers sum all.
page_views.c.loss.dev AAAA a25a:002a:0000:1234:0000:0000:0000:0000
page_views.c.loss.dev AAAA b3f1:0015:0000:1235:0000:0000:0000:0000
# Total: 0x2a + 0x15 = 63CRDT property: No conflicts. Each node only updates its own record. Convergence guaranteed.
SRV Manifest
_mydata._tcp.loss.dev. SRV <start> <count> <flags> <pool>- start: First chunk index in pool
- count: Number of chunks
- flags: Capability bitfield
- pool: Domain containing chunks
Chunk Pool
_12345.loss.dev. TXT "base64chunk..."
_12346.loss.dev. TXT "base64chunk..."
_12347.loss.dev. TXT "base64chunk..."Resolution Flow
query(_mydata._tcp.loss.dev)
β SRV: 12345 3 1 loss.dev
β fetch _12345.loss.dev, _12346.loss.dev, _12347.loss.dev
β concatenate chunks
β base64 decode
β gunzip (if flags & 1)
β outputExamples
List Resources
honk ls
# NAME TYPE SIZE CHUNKS FLAGS
# pelicans image/jpeg 27282 146 H
# test-meta text/plain 24 1 HUpload an Image
# Auto-detects flags from file type
honk put pelican photo.jpg -y
# Result:
# {
# "name": "pelican",
# "domain": "loss.dev",
# "start": 45678,
# "count": 146,
# "flags": 1
# }Retrieve Anywhere
# On any machine with dig
honk get pelican --domain=loss.dev
# Or the pure DNS one-liner:
dig +short SRV _pelican._tcp.loss.dev | ...Queue: Job Processing
# Producer: add jobs to queue
honk enqueue jobs '{"task":"build","repo":"myapp"}'
honk enqueue jobs '{"task":"deploy","env":"prod"}'
# Consumer: process jobs
while job=$(honk dequeue jobs 2>/dev/null); do
echo "Processing: $job"
# do work...
done
# Monitor queue depth
honk qdepth jobs --all
# Queue: jobs
# Total: 4
# Unread: 0
# Offset: 1766100657799Counter: Page Views
# Increment (each node tracks its own count)
honk incr page_views
# Read total (sums all nodes - CRDT merge)
honk counter page_views
# 42
# Scrape via DNS for monitoring
dig +short AAAA page_views.c.loss.devReally Silly Syndication
# RSS feed announcement
dig +short TXT rss.loss.dev | tr -d '"' | bash
# Output: https://graemefawcett.ca/hiSee Also
Verification
The reflection validates reality. πͺ
Test Suite Status
TableConfig:
array_path: tests
columns:
Category: class
Test: test
Status: status
format: markdownβ Fence Execution Error: "'honk-test-suite' - Curiouser and curiouser! That path seems to have vanished. Perhaps you meant: 'honk-user-guide', 'poke-test-fixture'?"
Summary
| Metric | Value |
|---|---|
| Total Tests | 34 |
| Passed | β 34 |
| Failed | β 0 |
| Success Rate | 100% |
Tests run via pytest against mocked DNS Made Easy API.
- (honk-protocol) - RFC F0UL specification [honk-protocol]
- (goose-distribution-network) - The origin story [goose-distribution-network]
- (yoneda-lemon) - Why objects are defined by morphisms [yoneda-lemon]
honk πͺΏ
North
slots:
- context:
- User guide links up to RFC specification
slug: honk-protocol
South
slots:
- context:
- Linking user guide to test suite (LGD pattern)
slug: honk-test-suite