PAKT Specification

On this page

PAKT — a typed data interchange format. Human-authorable. Streaming. Self-describing.

This site page is a synchronized overview of the current PAKT v0 surface. The normative source remains spec/pakt-v0.md.

Version

PAKT uses single-integer versioning. Each version is a complete specification.

VersionStatusMeaning
PAKT 0DraftIn active development; breaking changes expected
PAKT 0AcceptedFeature-complete; only clarifications and bug fixes
PAKT 1(future)First stable release; no breaking changes within major version

Data Model

The canonical unit grammar is:

unit      = statement*
statement = assign | pack

Current Go implementation support:

  • assign = IDENT type_annot ASSIGN value
  • pack = IDENT type_annot PACK pack_body

Assigns look like:

name:str = 'midwatch'
version:(int, int, int) = (1, 0, 0)
payload:bin = x'48656C6C6F'

Scalar Types

TypeLiteralExample
strQuoted or raw string'hello', r'C:\tmp'
intSigned 64-bit integer42, -7, 0xFF, 0b1010, 0o77, 1_000
decExact decimal3.14, 1_000.50
floatIEEE 754 binary646.022e23, 1.5E-10
boolBoolean keywordtrue, false
uuidUUID550e8400-e29b-41d4-a716-446655440000
dateISO date2026-06-01
tsISO timestamp (tz required)2026-06-01T14:30:00Z
binBinary datax'48656C6C6F', b'SGVsbG8='

bin literals accept hexadecimal (x'...') and RFC 4648 base64 with padding (b'...'). Both forms produce the same bytes.

Strings

PAKT supports:

  • quoted strings: 'hello', "hello"
  • raw strings: r'C:\Users\alice', r"^\d{3}-\d{4}$"
  • triple-quoted strings: ''' ... ''', """ ... """
  • raw triple-quoted strings: r''' ... ''', r""" ... """

Multi-line indentation

The opening triple quote must be followed immediately by a newline. The closing triple quote must appear on its own line.

The first non-blank content line defines the indentation baseline. That much leading whitespace is stripped from each non-blank content line.

query:str = '''
    SELECT id, name
    FROM users
    WHERE active = true
    '''

Raw strings

Raw strings disable escape processing:

path:str     = r'C:\Users\alice\Documents'
template:str = r'''
    Hello \n World
    '''

Composite Types

KindType syntaxValue syntax
Struct{field:type, ...}{ val, ... }
Tuple(type, ...)(val, val, ...)
List[type][val, ...]
Map<K ; V><key ; value, ...>

Maps use ; between the key and value in both the type annotation and each map entry.

users:<int ; str> = <
    1 ; 'Alice'
    2 ; 'Bob'
>

Duplicate map keys are preserved in decode order. Interpreting them is an application/domain concern.

Grammar Excerpts

scalar_type = 'str' | 'int' | 'dec' | 'float' | 'bool' | 'uuid' | 'date' | 'ts' | 'bin'
map_type    = LANGLE type SEMI type RANGLE
value       = scalar | NIL | atom_val | struct_val | tuple_val | list_val | map_val
scalar      = STRING | RAW_STR | ML_STR | ML_RAW | INT | DEC | FLOAT | BOOL | UUID | DATE | TS | BIN
map_entry   = value SEMI value
pack        = IDENT type_annot PACK pack_body

Canonical Specification

For the full normative grammar and semantics, including pack statements and duplicate-key handling, read the canonical spec:

Duplicates

Duplicate names at the unit root are preserved in encounter order — this matches the handling of duplicate map keys. Interpreting duplicate statement names is an application/domain concern.

Struct field names are declared in the type, not in the value, so duplicates are caught at the type level.

Whitespace Rules

  • Whitespace around = is optional: name:str = 'x' and name:str='x' are equivalent.
  • Whitespace around : in type annotations is not permitted: name:int, not name : int.
  • Members are separated by commas, newlines, or both (SEP). At least one separator is required between members.
  • Consecutive newlines (blank lines) are ignored.
  • Indentation is insignificant — cosmetic only.

Structural Equivalence

Block and inline forms are semantically identical. A conforming formatter may freely convert between them:

# Block struct
deploy:{level:str, release:int} = {
'platform'
26
}

# Inline struct
deploy:{level:str, release:int} = { 'platform', 26 }
# Block tuple
version:(int, int, int) = (
3
45
5678
)

# Inline tuple
version:(int, int, int) = (3, 45, 5678)

Type Assertions

Type annotations in a PAKT unit are assertions by the producer. They are validated during parsing — a unit that violates its own assertions is malformed.

release:int = 26
status:|active, inactive| = |active

Future consideration: External spec files (.spec.pakt) and consumer projections may be added in a future version. These features are deferred until real-world usage patterns are better understood.

File Conventions

ExtensionPurposeMIME Type
.paktPAKT data unitapplication/vnd.pakt

Website: usepakt.dev