plurigrid/asi

syrup

Syrup binary serialization for OCapN/CapTP wire format. Canonical encoding for capability messages.

First seen Jun 12, 2026

Installation

$ npx skills add plurigrid/asi --skill syrup

Also in this package

Other skills from plurigrid/asi · top by installs.

npx skills add plurigrid/asi

Browse all from plurigrid/asi

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 62
License LICENSE
Default branch main
Open issues 3
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,756 B
  • docs SUMMARY.md 112 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Syrup: Binary Serialization for OCapN

Trit: -1 (MINUS - constraining/validating serialization) Color: #8B4513 (Saddlebrown - like syrup) Source: ocapn/syrup


Overview

Syrup is a lightweight binary serialization format for the OCapN (Object Capability Network). It provides canonical encoding - the same data always serializes to identical bytes - making it suitable for hashing, signing, and capability transport.

Core principle: Simple, canonical, easy to implement across languages.


Type Encoding Reference

Type Format Example
Boolean t or f t = true
Positive int <digits>+ 42+
Negative int <digits>- 123- = -123
Bytestring <len>:<bytes> 3:cat
String <len>"<utf8> 5"hello
Symbol <len>'<utf8> 3'foo
Float F<4 bytes> IEEE 754 single
Double D<8 bytes> IEEE 754 double
List [<items>] [3+4+5+] = [3,4,5]
Dict {<k><v>...} {3"age12+}
Set #<items>$ #3:a3:b$
Record <<label><args>> <4"date2024+5+1+>

Installed Implementations

Python

# pip install via: gh repo clone ocapn/syrup && cd syrup/impls/python
from syrup import syrup_encode, syrup_decode, Symbol, record

# Encode
syrup_encode({"name": "alice", "age": 30})
# => b'{3"age30+4"name5"alice}'

# Decode  
syrup_decode(b'{3"age30+4"name5"alice}')
# => {'age': 30, 'name': 'alice'}

# Symbols (for Lisp-like keys)
syrup_encode({Symbol('species'): b'cat'})
# => b"{7'species3:cat}"

# Records (custom types)
syrup_encode(record('date', 2024, 5, 1))
# => b'<4"date2024+5+1+>'

Guile Scheme

;; Install: copy syrup.scm to your Guile load path
(use-modules (syrup))

;; Encode
(syrup-encode 42)
;; => #vu8(52 50 43)  ; "42+"

(syrup-encode '("hello" "world"))
;; => #vu8(91 53 34 104 101 108 108 111 53 34 119 111 114 108 100 93)

;; Decode
(syrup-decode #vu8(52 50 43))
;; => 42

;; Records
(syrup-encode (make-syrec* (string->utf8 "date") 2024 5 1))

Racket

#lang racket
(require syrup)

;; Encode
(syrup-encode #hash(("name" . "alice") ("age" . 30)))
;; => #"{3\"age30+4\"name5\"alice}"

;; Decode
(syrup-decode #"{3\"age30+}")
;; => #hash(("age" . 30))

;; Records
(syrup-encode (record* #"date" 2024 5 1))
;; => #"<4:date2024+5+1+>"

;; Marshalling custom types
(struct point (x y) #:transparent)
(syrup-encode (point 1 2)
              #:marshallers (list (cons point? 
                                       (λ (p) (record* 'point (point-x p) (point-y p))))))

Package: syrup (installed via raco pkg)


Canonical Property

Syrup guarantees canonical encoding:

  1. Dictionaries: Keys sorted by their serialized byte representation
  2. Sets: Items sorted by their serialized byte representation
  3. No duplicate keys: Dicts must not contain the same key twice

This means: hash(syrupencode(x)) == hash(syrupencode(y)) iff x == y


Backwards Compatibility

Syrup decoders accept:

  • Bencode: d3:agei12ee → dict
  • Canonical S-expressions: (3:foo 3:bar) → list
# Bencode
syrup_decode(b'd3:agei12e4:name5:Missye')
# => {b'age': 12, b'name': b'Missy'}

# S-expressions
syrup_decode(b'(3:cat 7:tabatha)')
# => [b'cat', b'tabatha']

GF(3) Triads

# Wire Format Bundle
syrup (-1) ⊗ captp (0) ⊗ gay-mcp (+1) = 0 ✓  [Colored Capabilities]
syrup (-1) ⊗ localsend-mcp (0) ⊗ tailscale-file (+1) = 0 ✓  [P2P Transfer]
syrup (-1) ⊗ beeper-mcp (0) ⊗ agent-o-rama (+1) = 0 ✓  [Message Encoding]

# Serialization Stack
syrup (-1) ⊗ preserves (0) ⊗ json (+1) = 0 ✓  [Format Spectrum]

Commands

# Python (after installing to PYTHONPATH)
python3 -c "from syrup import *; print(syrup_encode({'test': 42}))"

# Guile (after installing to load path)
guile -c "(use-modules (syrup)) (display (syrup-encode 42))"

# Racket (after raco pkg install)
racket -e "(require syrup) (displayln (syrup-encode #hash((\"x\" . 1))))"

Use Cases

Use Case Why Syrup
CapTP messages Wire format for capability transport
Content addressing Canonical = deterministic hashes
Signing Sign serialized form, verify anywhere
Storage Compact binary, self-describing
Cross-language Same bytes from Python/Guile/Racket

Related Skills

Skill Relation
captp CapTP uses Syrup as wire format
preserves Syrup is a Preserves serialization
localsend-mcp P2P transfer could use Syrup
acsets Serialize ACSets with Syrup

Installation

# Clone the repo
gh repo clone ocapn/syrup

# Python: add to PYTHONPATH or copy syrup.py
cp syrup/impls/python/syrup.py ~/.local/lib/python3/

# Guile: copy to load path
cp syrup/impls/guile/syrup.scm ~/.local/share/guile/site/3.0/

# Racket: install package
cd syrup/impls/racket && raco pkg install syrup/

References


Skill Name: syrup Type: Binary Serialization Format Trit: -1 (MINUS) GF(3): Constrains data to canonical form Invariant: Same data → same bytes, always

ACP atlas

Part of: acp-commons.