lantern

honk-protocol

RFC F0UL: HONK - Hierarchical Object Namespace for Knowledge

Status: Informational (and Chaotic) Category: Experimental Protocol Abuse Author: G. Fawcett Date: December 2024


Abstract

This document specifies HONK (Hierarchical Object Namespace for Knowledge), a distributed content-addressed storage system implemented entirely within the existing Domain Name System (DNS) infrastructure. HONK repurposes DNS record types according to their actual capabilities rather than their intended uses, providing a globally distributed, cached, reactive data store at the cost of one domain registration ($12/year USD).

The key insight is that DNS has always been a filesystem. This document merely acknowledges that fact.


Status of This Memo

This memo describes a protocol that makes DNS administrators uncomfortable. Distribution of this memo is unlimited, ideally via DNS TXT records.


Table of Contents

  • Introduction
  • Terminology
  • Design Philosophy
  • Theoretical Foundations
  • Record Type Semantics
  • Data Types
  • The Coordinate System
  • Capability Bitfield
  • Reactivity Model
  • The Chunk Pool
  • Operations
  • Examples
  • Security Considerations
  • IANA Considerations
  • References
  • Acknowledgments

1. Introduction

The Domain Name System [RFC1035] was designed to map human-readable names to network addresses. Over four decades of deployment have revealed that DNS is, in fact, a globally distributed, hierarchically namespaced, typed, cached key-value store with built-in replication, aliasing, priority ordering, and arbitrary payload storage.

HONK acknowledges this reality and provides a formal specification for using DNS as a general-purpose distributed storage system.

1.1 Motivation

The author's daughter coughed directly into his face, resulting in a sick day. The author had a half-hour drive. These conditions produced HONK.

1.2 Requirements Language

The key words "MUST", "SHOULD", "HONK", and "REALLY SHOULD HAVE KNOWN BETTER" in this document are to be interpreted as the author sees fit.


2. Terminology

Chunk: A unit of content stored in a TXT record, maximum 255 bytes.

Chunk Pool: The global namespace of numbered TXT records within a domain.

Coordinate: A tuple of (start, count, flags) addressing a range within the chunk pool.

Manifest: An SRV record specifying coordinates and capabilities for a resource.

Pointer: A CNAME record providing indirection to another name.

Goose: The chaotic waterfowl energy that drives this protocol.

HONK: Both the protocol name and the sound of approval.


Queue: A timestamped sequence of TXT records in the .q namespace, ordered by millisecond timestamp.

Offset: A counter tracking the last-read position in a queue, enabling at-least-once delivery without deletes.

Counter: A CRDT (Conflict-free Replicated Data Type) implemented via AAAA records, where each node maintains its own value and readers sum all nodes.

Node ID: A 4-character identifier for a HONK client, used to partition counter writes and queue offsets.

3. Design Philosophy

3.1 The Yoneda Principle

Objects are defined by their morphisms, not their labels. A DNS record is what it can do, not what the RFC says it is "for."

3.2 Protocols Are Playgrounds

Every protocol specification describes one possible use of the underlying capability. HONK describes another.

3.3 The Bits Are The Truth

The protocol designers built flexibility into DNS. HONK merely uses it.


4. Theoretical Foundations

4.1 The Yoneda Principle (Formalized)

The Yoneda Lemma states: an object X is completely determined by the collection of all morphisms pointing into it from every other object.

You don't need to look inside X. You only need to know how everything else relates to X.

Applied to DNS: A record type is not defined by what RFC 1035 says it's "for." It's defined by the operations you can perform on it:

Record Morphisms (What You Can Do) Therefore It Is
TXT Read arbitrary bytes, write arbitrary bytes A storage cell
SRV Query structured tuple, route based on fields A manifest/coordinate
CNAME Resolve to another name, chain resolutions A pointer/reference
MX Query prioritized list, failover semantics A priority queue
A/AAAA Resolve to numeric value, multiple per name A numeric array

The arrows (morphisms) define the object. DNS records ARE what you can do with them.

4.2 The Structural Isomorphism

Two systems are isomorphic when they admit the same morphisms—when the set of valid transformations applicable to one equals those applicable to the other.

Claim: DNS ≅ Filesystem

Filesystem Morphism DNS Morphism
read(path) dig TXT name
write(path, data) API: create TXT record
stat(path) dig SRV name (metadata)
readlink(path) dig CNAME name
readdir(path) dig ANY name
chmod(path, mode) Update SRV port field (capabilities)
Cache invalidation TTL expiry
Symlink CNAME
Hardlink Multiple records pointing to same chunk

If Hom(X, DNS) ≅ Hom(X, Filesystem) for all relevant X, then DNS ≅ Filesystem.

The isomorphism is not metaphorical. The operations are the same. Therefore the systems are the same.

4.3 Records as Morphisms

In HONK, each DNS query is a morphism—a transformation of context:

query("latest.blog.loss.dev")
  → CNAME morphism → "v3.blog.loss.dev"
  → SRV morphism → (46, 26, 1, "loss.dev")
  → TXT morphisms × 26[chunk₀, chunk₁, ..., chunk₂₅]
  → base64 morphism → compressed_bytes
  → gunzip morphism → content

The resolution chain IS a middleware pipeline. Each record type is a transformation. The content emerges from the composition of morphisms.

Data at rest tells you nothing. Data in motion tells you everything.

A TXT record sitting in DNS has no semantics until something queries it, decodes it, decompresses it, acts on it. Each transformation is a morphism. The collection of morphisms defines the meaning.

4.4 The Functor

The functor is constructive: This isn't abstract proof. The code exists. The DNS records exist. Run the functor yourself and get a pelican out:

honk get pelicans --domain=loss.dev
# Output: pelicans.out (27KB JPEG of pelicans)

The RFC-as-thesis proves categorical structure by instantiation. Here's the functor. Here's identity. Here's composition. Execute them.

4.5 Homoiconicity

HONK is homoiconic—code, data, and metadata share the same representation:

  • The TXT installer script is data (bytes in DNS)
  • The TXT installer script is code (pipe to bash)
  • The SRV manifest is data (a record)
  • The SRV manifest is metadata (describes other records)
  • The capability bitfield is data (16 bits)
  • The capability bitfield is code (controls interpretation)

The system interprets itself. The format that stores content also stores the instructions for decoding that content.

4.6 The Identity Arrow

In category theory, every object has an identity morphism—an arrow from itself to itself that does nothing.

In HONK, the identity arrow is:

dig +short TXT peak.loss.dev | tr -d '"' | bash

Output:

| ||
| |_

The system, queried about itself, returns Loss. The identity arrow is a shitpost. This is appropriate.

🍋


5. Record Type Semantics

HONK assigns the following semantics to DNS record types:

Record Traditional Use HONK Semantics
TXT Human-readable notes Content chunks (255 bytes each)
SRV Service location Manifest/coordinates (start, count, flags, pool)
CNAME Hostname alias Pointer/reference (indirection, versioning)
MX Mail routing Priority queue (version failover chain)
A IPv4 address 32-bit value / 4-byte self-ordering chunk
AAAA IPv6 address 128-bit value / 16-byte self-ordering chunk

5.7 AAAA Records as Native Unicode Strings

The true power of AAAA records: each segment is 16 bits. UTF-16 code units are 16 bits. AAAA records ARE Unicode strings.

AAAA = 8 segments × 16 bits = 8 UTF-16 code units
     = 1 sequence + 7 characters (BMP)
     = 1 sequence + up to 3 surrogate pairs + leftovers

The Canonical Example

honk.loss.dev. AAAA 0001:0048:004f:004e:004b:d83e:debf:2764
                    seq   H    O    N    K   🪿hi 🪿lo   ❤

Output: HONK🪿❤

The goose emoji (U+1FABF) requires a surrogate pair:

  • High surrogate: 0xD83E
  • Low surrogate: 0xDEBF

Four ASCII characters + one emoji (2 code units) + one BMP heart = exactly 7 code units. Perfect fit.

Decoding with HONK CLI

honk unicode-get honk --domain=loss.dev
# Output: HONK🪿❤

The CLI handles IPv6 normalization (DNS strips leading zeros, compresses ::) and UTF-16 surrogate pair decoding automatically.

Haiku in DNS

Bashō's frog haiku (古池や蛙飛び込む水の音) stored as native UTF-16:

haiku.loss.dev. AAAA 0001:53e4:6c60:3084:86d9:98db:3073:8fbc
haiku.loss.dev. AAAA 0002:3080:6c34:306e:97f3:0000:0000:0000
honk unicode-get haiku --domain=loss.dev
# Output: 古池や蛙飛び込む水の音

Sort by first segment, concatenate segments 2-8, interpret as UTF-16, strip nulls. No base64. No chunking. Just poetry, cached globally, resolved in milliseconds.

5.1 TXT Records (Cells)

TXT records store content chunks. Each record holds up to 255 bytes of payload, typically base64-encoded.

_42.pool.example.com.  TXT  "SGVsbG8gV29ybGQh..."

5.2 SRV Records (Manifests)

SRV records specify coordinates into the chunk pool:

_resource._tcp.example.com.  SRV  <start> <count> <flags> <pool-domain>

Fields:

  • Priority (16-bit): Start index in chunk pool
  • Weight (16-bit): Number of chunks
  • Port (16-bit): Capability bitfield (see Section 8)
  • Target: Domain containing the chunk pool

5.2.1 Metadata Records

A TXT record at the same name as the SRV manifest provides extended metadata:

_resource._tcp.example.com.  SRV  0 146 1 pool.example.com.
_resource._tcp.example.com.  TXT  "mime=image/jpeg;size=27282;name=pelican.jpg"

Format: Semicolon-separated key=value pairs (like SPF/DKIM). Simple, human-readable, no parsing libraries.

Standard keys:

Key Description Example
mime MIME type image/jpeg, text/plain, application/x-sh
size Original size in bytes 27282
name Original filename pelican.jpg
enc Encoding if not base64 raw, utf16
created Unix timestamp 1734400000
sha256 Content hash (first 16 chars) a3f2b1c4d5e6f7g8

Keys are case-insensitive. Unknown keys SHOULD be ignored. Order is not significant.

The metadata record shares the SRV's TTL and lifecycle—when you create a manifest, create its metadata; when you delete a manifest, delete its metadata.

5.3 CNAME Records (Pointers)

CNAME records provide indirection, enabling versioning and reactivity:

latest.blog.example.com.  CNAME  v3.blog.example.com.

5.4 MX Records (Priority Queues)

MX records specify version precedence for failover:

blog.example.com.  MX  10  v3.blog.example.com.
blog.example.com.  MX  20  v2.blog.example.com.
blog.example.com.  MX  30  v1.blog.example.com.

5.5 A Records (Self-Ordering 4-Byte Chunks)

A records encode 4 bytes as dotted-quad notation. The first octet specifies sequence order:

hello.example.com.  A  01.72.101.108   ; seq=1, "Hel"
hello.example.com.  A  02.108.111.32   ; seq=2, "lo "
hello.example.com.  A  03.87.111.114   ; seq=3, "Wor"
hello.example.com.  A  04.108.100.33   ; seq=4, "ld!"

Decoding: Sort by first octet, concatenate remaining octets, interpret as ASCII.

5.6 AAAA Records (Self-Ordering 16-Byte Chunks)

AAAA records encode 16 bytes in IPv6 notation. First 16 bits specify sequence:

data.example.com.  AAAA  0001:4865:6c6c:6f20:576f:726c:6421:0000

Decoding: Sort by first segment, concatenate remaining segments, decode as binary.


6. Data Types

HONK supports the following data types:

Type Implementation Max Size
string TXT record 255 bytes
blob Multiple TXT chunks Unlimited
int32 A record (as dotted quad) 32 bits
int128 AAAA record 128 bits
list Multiple A/AAAA/TXT records Unlimited
sortedlist MX records (priority-ordered) Unlimited
manifest SRV record 48 bits + hostname
ref CNAME record Pointer to name

| queue | Timestamped TXT in .q namespace | Unlimited (TTL-bounded) | | counter | AAAA CRDT (per-node values) | 16-bit per node | | offset | AAAA record (queue read position) | 48-bit timestamp | | kv | SRV version + TXT value | 255 bytes |

7. The Coordinate System

Every resource in HONK is addressed by coordinates:

(start, count, flags, universe)

Where:

  • start: Index of first chunk (16-bit, from SRV priority)
  • count: Number of chunks (16-bit, from SRV weight)
  • flags: Capability bitfield (16-bit, from SRV port)
  • universe: Chunk pool domain (from SRV target)

This provides 48 bits of address space per domain, sufficient for addressing 2^16 chunks of 255 bytes each (~16MB) per namespace.

7.1 Spatial Interpretation

The coordinate system may be interpreted spatially:

(x, y, z) = (start, count, flags)

CNAME records function as wormholes, teleporting resolution to different coordinates.


8. Capability Bitfield

8. Capability Bitfield

The SRV port field is interpreted as a 16-bit capability bitfield.

Implementation Note: DNS providers require port ≥ 1. Bit 0 is therefore the HONK marker, always set to 1 for valid HONK resources. This guarantees all HONK ports are ≥ 1.

Bit 0  (0x0001): HONK      - Protocol marker (MUST be set)
Bit 1  (0x0002): GZIP      - Content is gzip compressed
Bit 2  (0x0004): URL       - Content is a URL (dereference, don't display)
Bit 3  (0x0008): EXEC      - Content is executable (pipe to shell)
Bit 4  (0x0010): BINARY    - Content is base64-encoded binary
Bit 5  (0x0020): IMAGE     - Content is an image
Bit 6  (0x0040): UTF16     - Content is UTF-16 encoded
Bit 7  (0x0080): ENCRYPTED - Content is encrypted
Bit 8  (0x0100): SIGNED    - Content has signature (in separate record)
Bit 9  (0x0200): CONTINUES - Resource continues at target hostname
Bit 10 (0x0400): STREAMING - Append-only, check for new chunks
Bit 11 (0x0800): IMMUTABLE - Content will never change (cache forever)
Bits 12-15: Reserved for future chaos

8.1 Common Flag Combinations

Flags Hex Meaning
1 0x0001 Raw text (HONK only)
3 0x0003 Gzipped text
11 0x000B Gzipped executable
19 0x0013 Gzipped binary
27 0x001B Gzipped binary executable
5 0x0005 URL to dereference
17 0x0011 Binary (no compression)
33 0x0021 Image (no compression)
35 0x0023 Gzipped image

8.2 Auto-Detection by MIME Type

Implementations SHOULD auto-detect capability flags from file type:

Extension MIME Type Suggested Flags Hex
.txt text/plain HONK 0x0001
.md text/markdown HONK + GZIP 0x0003
.html text/html HONK + GZIP 0x0003
.json application/json HONK + GZIP 0x0003
.sh application/x-sh HONK + GZIP + EXEC 0x000B
.png image/png HONK + BINARY + IMAGE 0x0031
.jpg image/jpeg HONK + BINARY + IMAGE 0x0031
.gif image/gif HONK + BINARY + IMAGE 0x0031
.gz application/gzip HONK + BINARY 0x0011
.tgz application/gzip HONK + BINARY 0x0011
.zip application/zip HONK + BINARY 0x0011
.bin application/octet-stream HONK + BINARY 0x0011
.wasm application/wasm HONK + BINARY 0x0011

For already-compressed formats (.gz, .tgz, .zip, .jpg), do NOT set GZIP—double compression wastes space.

Implementations MAY prompt for confirmation: "Detected image/jpeg → flags 0x0031 (HONK+BINARY+IMAGE). Confirm? [Y/n]"

9. Reactivity Model

HONK achieves reactivity through TTL layering:

Layer Record Type Recommended TTL Mutability
Pointers CNAME 60 seconds Mutable (flip to update)
Manifests SRV 3600 seconds Semi-stable
Content TXT 86400 seconds Immutable

9.1 Update Propagation

To update a resource:

  • Write new content to new chunk range
  • Create new SRV manifest pointing to new chunks
  • Update CNAME pointer to new manifest

Within one pointer TTL (60 seconds), all resolvers worldwide will see the new version. Content remains cached; only pointer resolution is repeated.

9.2 Rollback

To rollback: Update CNAME to point to previous manifest. Old chunks remain in pool.


10. The Chunk Pool

A HONK domain maintains a global chunk pool:

_1.pool.example.com.   TXT  "..."
_2.pool.example.com.   TXT  "..."
_3.pool.example.com.   TXT  "..."
...
_N.pool.example.com.   TXT  "..."

Multiple resources share the same pool. SRV manifests are views into this pool.

10.1 Chunk Naming

Chunks SHOULD be named with underscore prefix and numeric index:

_<index>.<namespace>.<domain>

10.2 Garbage Collection

HONK does not specify garbage collection. Chunks are cheap. Domains are $12/year. Let them accumulate.


11. Operations

11.1 GET (Read)

The simple way:

honk get pelicans --domain=loss.dev
# Output: pelicans.out (27KB JPEG)

honk get blog --domain=loss.dev
# Output: blog.out (markdown content)

The CLI handles SRV manifest lookup, chunk fetching, base64 decoding, and gzip decompression automatically.

Protocol Details

For the curious (or those implementing their own client):

# Get manifest
srv=$(dig +short SRV _resource._tcp.example.com)
start=$(echo $srv | awk '{print $1}')
count=$(echo $srv | awk '{print $2}')
flags=$(echo $srv | awk '{print $3}')
pool=$(echo $srv | awk '{print $4}')

# Fetch chunks
for i in $(seq $start $((start+count-1))); do
  dig +short TXT _$i.$pool | tr -d '"'
done | base64 -d | {
  # Decompress if GZIP flag set
  [[ $((flags & 2)) -ne 0 ]] && gunzip || cat
}

11.2 PUT (Write)

# Encode content
cat content.txt | gzip | base64 > encoded.txt

# Split into chunks
split -b 250 encoded.txt chunk_

# Upload chunks (implementation-specific)
# Create SRV manifest pointing to chunk range

11.3 REF (Pointer Update)

# Update CNAME to flip pointer
# (DNS provider API specific)

11.4 ENQUEUE (Add to Queue)

Queue items are timestamped TXT records in the .q namespace:

_<timestamp>.<queue>.q.<domain>  TXT  "<payload>"

Timestamp is milliseconds since epoch, providing natural ordering.

# Enqueue a job
honk enqueue jobs '{"task":"build","env":"prod"}'
# Creates: _1766099487050.jobs.q.loss.dev TXT '{"task":"build","env":"prod"}'

11.5 DEQUEUE (Read from Queue)

Dequeue uses an offset as consumer position pattern. Each consumer (identified by node ID) maintains its own read position via TXT record:

_<node>.jobs.offset.<domain>  TXT  "<timestamp>"

Algorithm:

  • Read offset from API (needs fresh read, DNS caching defeats queue semantics)
  • List queue items via API
  • Filter items where timestamp > offset
  • Return oldest unread item
  • Update offset to that item's timestamp
# Dequeue oldest unread
honk dequeue jobs
# Returns: {"task":"build","env":"prod"}
# Updates offset to 1766099487050

# Dequeue again
honk dequeue jobs
# Returns next item, or "Queue jobs is empty" if caught up

Key insight: No deletes required. Queue items remain until TTL expires. The offset tracks consumption. Multiple consumers each maintain their own offset (like Kafka consumer groups).

Peek mode: Use --peek to read without updating offset.

11.6 INCR (Counter Increment)

Counters use AAAA records with CRDT semantics. Each node publishes its own increment; readers sum all nodes:

<counter>.c.<domain>  AAAA  <node>:<value>:0000:<time>:0000:0000:0000:0000

Format breakdown:

  • Segment 0: Node ID (4 hex chars, identifies writer)
  • Segment 1: Counter value (16-bit hex)
  • Segment 2: Reserved
  • Segment 3: Timestamp (16-bit, for conflict resolution)
  • Segments 4-7: Reserved (future: checksum, flags)
# Increment counter
honk incr page_views

# Read counter total
honk counter page_views
# Output: 42

# Read with breakdown by node
honk counter page_views --verbose
# Output: page_views = 42 (node1: 15, node2: 27)

Protocol Details

# Read total (sum all nodes)
dig +short AAAA page_views.c.loss.dev | awk -F: '{sum += strtonum("0x"$2)} END {print sum}'

CRDT property: Multiple writers never conflict. Each node only updates its own record. Readers merge by summing. Convergence is guaranteed.

11.7 SET/CAS (KV with Optimistic Locking)

Key-value storage uses SRV records for versioning:

_<key>._kv.<domain>  SRV  <version> 0 0 <value-encoding>
_<key>._kv.<domain>  TXT  "<value>"
  • SET: Increment version, update TXT value
  • CAS: Compare version, fail if mismatch (optimistic locking)
# Set value
honk set rate_limit 100

# Compare-and-swap (only succeeds if version matches)
honk cas rate_limit 150 --version=3

12. Examples

12.1 Blog Post Distribution

; Pointer (reactive)
latest.blog.example.com.     CNAME   v3.blog.example.com.

; Manifest (semi-stable)
v3.blog.example.com.         SRV     146 26 1 pool.example.com.

; Content (immutable)
_146.pool.example.com.       TXT     "H4sIAAAAAAAA..."
_147.pool.example.com.       TXT     "..."
...
_171.pool.example.com.       TXT     "..."

Retrieval:

dig +short TXT blog.example.com | tr -d '"' | bash

12.2 RSS Feed Announcement (Really Silly Syndication)

; Installer
rss.example.com.             TXT     "dig +short SRV _rss._tcp.example.com | awk '{gsub(/\\.$/,\"\",$4); printf \"https://%s/%c%c\\n\", $4, int($3/256), $3%256}'"

; Manifest with port-encoded path
_rss._tcp.example.com.       SRV     0 0 26729 graemefawcett.ca.

Port 26729 = 0x6869 = "hi" (ASCII)

Retrieval:

dig +short TXT rss.example.com | tr -d '"' | bash
# Output: https://graemefawcett.ca/hi

12.3 Hello World (A Record Encoding)

hello.example.com.  A  01.72.101.108
hello.example.com.  A  02.108.111.32
hello.example.com.  A  03.87.111.114
hello.example.com.  A  04.108.100.33

Retrieval:

dig +short A hello.example.com | sort -t. -k1 -n | cut -d. -f2-4 | while read a b c; do printf "\\x$(printf '%02x' $a)\\x$(printf '%02x' $b)\\x$(printf '%02x' $c)"; done
# Output: Hello World!

13. Security Considerations

13.1 Execution Risk

Flag 0x0004 (EXEC) instructs clients to pipe content to a shell. This is as dangerous as it sounds. Users SHOULD only execute HONK content from trusted domains.

13.2 DNSSEC

HONK content SHOULD be served from DNSSEC-signed zones to prevent tampering.

13.3 Rate Limiting

DNS providers implement rate limiting. High-frequency HONK operations may be throttled.

13.4 Cache Poisoning

Standard DNS cache poisoning attacks apply. See [RFC5452].

13.5 The Goose

If you encounter a goose while implementing HONK:

  • Do not make direct eye contact
  • Back away slowly
  • Do not attempt to debug in its presence

14. IANA Considerations

This document requires no IANA actions. HONK uses existing DNS record types for purposes their designers probably anticipated but hoped nobody would actually attempt.


15. References

15.1 Normative References

Mockapetris, P. (1987). Domain Names - Implementation and Specification. RFC 1035. https://doi.org/10.17487/RFC1035
Gulbrandsen, A., Vixie, P., & Esibov, L. (2000). A DNS RR for specifying the location of services (DNS SRV). RFC 2782. https://doi.org/10.17487/RFC2782
Kitterman, S. (2014). Sender Policy Framework (SPF). RFC 7208. https://doi.org/10.17487/RFC7208

15.2 Informative References

Masinter, L. (1998). Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0). RFC 2324. https://doi.org/10.17487/RFC2324
Hubert, A. & van Mook, R. (2009). Measures for Making DNS More Resilient against Forged Answers. RFC 5452. https://doi.org/10.17487/RFC5452
CAD. (2008). Loss. Ctrl+Alt+Del. https://is.this.loss.dev
Yoneda, N. (1954). On the homology theory of modules. Journal of the Faculty of Science, University of Tokyo, 7, 193-227.
Fawcett, G. (2025). Structural Isomorphism of Documents and Programs. Wanderland Apocrypha. https://graemefawcett.ca/blog/structural-isomorphism
Fawcett, G. (2025). Objects Defined by Arrows (The Yoneda Lemon). Wanderland Apocrypha. https://graemefawcett.ca/blog/yoneda-lemon

16. Acknowledgments

The author wishes to thank:

  • His daughter, for the immune system challenge that enabled this work
  • The geese, for their chaotic energy
  • DNS, for being a filesystem this whole time
  • Claude, for staying aligned on the vector

Author's Address

Graeme Fawcett Domain: loss.dev Email: dig TXT email.loss.dev +short | tr -d '"' | tr '!' '\\033' | bash

# TXT record contains (! = escape placeholder):
echo -e '![1;35mOh ![1;36mmy ![1;33mgoodness, ![1;31mno ![1;32mwe ![1;34mdont ![1;35mdo ![1;36mthat ![1;33mhere.![0m'

# Output:
# Oh my goodness, no we dont do that here.
# (in magenta, cyan, yellow, red, green, blue, magenta, cyan, yellow)

honk

Appendix A: Quick Reference

Using the HONK CLI

# Install
pip install git+https://git.sr.ht/~graemefawcett/honk

# Get content from DNS
honk get pelicans --domain=loss.dev
honk get blog --domain=loss.dev

# Unicode from AAAA records
honk unicode-get haiku --domain=loss.dev

# Queue operations
honk enqueue jobs '{"task":"build"}'
honk dequeue jobs
honk qdepth jobs

# Counter operations
honk incr page_views
honk counter page_views

Raw Protocol (Shell Implementation)

For those who want to understand the underlying protocol:

# Universal HONK reader
honk_get() {
  local name=$1
  local srv=$(dig +short SRV _${name}._tcp.loss.dev)
  local start=$(echo $srv | awk '{print $1}')
  local count=$(echo $srv | awk '{print $2}')
  local flags=$(echo $srv | awk '{print $3}')
  local pool=$(echo $srv | awk '{print $4}')

  for i in $(seq $start $((start+count-1))); do
    dig +short TXT _$i.$pool | tr -d '"'
  done | base64 -d | {
    [[ $((flags & 2)) -ne 0 ]] && gunzip || cat
  } | {
    [[ $((flags & 8)) -ne 0 ]] && bash || cat
  }
}

# Usage
honk_get blog
honk_get pelicans > pelicans.jpg

Appendix B: The Origin

dig +short TXT peak.loss.dev | tr -d '"' | bash
| ||
| |_

∎ 🪿


North

slots:
- slug: i-have-done-another-bad-thing-to-a-protocol
  context:
  - HONK is another bad thing done to a protocol - DNS as a filesystem

West

slots:
- slug: goose-distribution-network
  context:
  - HONK is the evolution of the Goose Distribution Network

East

slots:
- slug: yoneda-lemon
  context:
  - The category theory foundation
- slug: structural-isomorphism-thesis
  context:
  - Documents and programs are isomorphic - DNS and filesystems are too

44 The Functor

57 Aaaa Records As Native Unicode Strings

South

slots:
- context:
  - User guide links up to RFC specification
  slug: honk-user-guide

111 Get Read

116 Incr Counter Increment