Active mode
Mirrored from the format repository — docs/spec/SPECIFICATION_EN.md, SYNX 3.7.4. Changes are made there.
3.1 What Is It
By default a .synx file contains static data. Just keys and values, like JSON.
But if the first line of the file says !active, the file becomes a live config — enabling:
- Functions (
:random,:calc,:env, etc.) - Constraints (
[min:3],[type:int], etc.)
!active
port:env PORT
greeting:random
- Hello!
- Welcome!Without !active — markers :random, :calc and square brackets [] are completely ignored. The parser reads the file as plain text:
// No !active — functions DO NOT work
port:env PORT // key = "port:env", value = "PORT" (just a string)
greeting:random // key = "greeting:random", value = {} (object)💡 This is a security feature: a static file will never execute code, access environment variables, or run commands.
3.2 Full List of Functions (:)
Functions are written with a colon immediately after the key name: key:function value.
:random — Random Selection
Selects one element from a list on each parse.
Equal chances (no percentages):
!active
battle_cry:random
- Time to win!
- Ha-ha-ha!
- For the Syndicate!Each item has a 33.3% chance.
Weighted random (with percentages):
!active
// Percentages go after :random separated by spaces
// Order of percentages matches order of items
loot:random 70 20 10
- Common Chest
- Rare Chest
- Legendary ChestHere:
- "Common Chest" drops with 70% chance
- "Rare Chest" — 20%
- "Legendary Chest" — 10%
Percentage rules:
| Situation | Behavior |
|---|---|
| No percentages | All items are equally likely |
| Sum = 100 | Used as-is |
| Sum ≠ 100 | Automatically normalized (proportions preserved) |
| Fewer percentages than items | Remainder is split evenly among items without a percentage |
| More percentages than items | Extra percentages are ignored |
Normalization example:
!active
// 2 + 1 = 3, normalized: ~66.7% and ~33.3%
class:random 2 1
- Warrior
- MagePartial percentages example:
!active
// First gets 80%, remaining 20% split between two: 10% each
drop:random 80
- Nothing
- Sword
- Shield:calc — Expression Evaluation
Evaluates an arithmetic expression. Can reference other keys by name.
!active
price 100
tax:calc price * 0.2
total:calc price + taxResult:
price 100
tax 20 // ← your program receives this value
total 120 // ← your program receives this valueAs a JSON file:
{
"price": 100,
"tax": 20,
"total": 120
}Supported operations: +, -, *, /, % (remainder), (, ).
⚠️ Arithmetic only. No arbitrary code. The parser uses a safe evaluator, not
eval().
:env — Environment Variable
Substitutes the value of a system environment variable.
!active
port:env PORT
home_dir:env HOMEIf the variable is not found — the value will be null.
With a default (via :default):
!active
port:env:default:8080 PORTIf PORT is not set → returns 8080.
Keeping text as text. The variable's value is cast like any literal (8080 → int). Values that only look numeric — 64-bit ids, zero-padded codes — keep their text with a (string) hint or a [type:string] constraint; the same rule applies to the :default fallback:
!active
discord_app_id[type:string]:env DISCORD_APP_ID
zip(string):env:default:007 ZIP
api_key[type:string]:secret:env API_KEYSince 3.7.4
[type:string]keeps the text too. Earlier only(string)did: the value was cast first, so[type:string]rejected the resulting number withCONSTRAINT_ERR. A:secretvalue satisfies[type:string].
:alias — Reference to Another Key
Copies the value of another key. Does not duplicate data — references it.
!active
admin_email alex@example.com
complaints_email:alias admin_emailResult:
{
"admin_email": "[email protected]",
"complaints_email": "[email protected]"
}:secret — Hidden Value
The value is readable by your program but not shown in logs, during freeze, or when serialized to JSON. Protects against accidental leaks.
!active
api_key:secret sk-1234567890abcdef
db_password:secret P@ssw0rd!With console.log(data), print(data), JSON.stringify(data) — shows "[SECRET]".
To get the real value, use the .reveal() method:
// JavaScript / TypeScript
const key = data.api_key; // SynxSecret object
console.log(String(key)); // "[SECRET]"
console.log(JSON.stringify(key)); // '"[SECRET]"'
console.log(key.reveal()); // "sk-1234567890abcdef" ← real value# Python
key = data['api_key'] # SynxSecret object
print(key) # [SECRET]
print(key.reveal()) # sk-1234567890abcdef ← real valueSince 3.7.2 the mask also holds for
util.inspect/console.logof a whole object, object spread andObject.entries(TypeScript), for{:?}(Rust), and for the payload handed to WASM marker plugins.
⚠️ Important: Never log the result of
.reveal(). This method is intended only for passing the value to APIs, database connections, etc.
:default — Default Value
Sets a fallback if the main value is empty or not found. Most often combined with :env.
!active
// If PORT env var is not set — will be 3000
port:env:default:3000 PORT
// Just a default value (if value = null or empty)
theme:default dark:unique — Remove Duplicates from List
Keeps only unique elements.
!active
tags:unique
- action
- rpg
- action
- simulation
- rpgResult: ["action", "rpg", "simulation"]
:include — Include Another File
Inserts the contents of another .synx file into the current one. Path is relative to the current file.
!active
// Pull database settings from a separate file
database:include ./db.synxWhere db.synx:
host localhost
port 5432
name mydbResult:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "mydb"
}
}:geo — Value by Geolocation / Region
Selects a value based on user region (determined by IP or system locale).
!active
currency:geo
- US USD
- EU EUR
- GB GBPThis function requires runtime support. The parser passes the current region to the engine.
:template — String Interpolation
Substitutes {placeholders} with values from other keys. Supports dot-path for nested access.
!active
first_name John
last_name Doe
greeting:template Hello, {first_name} {last_name}!Result: "Hello, John Doe!"
With nested references (dot-path):
!active
server
host localhost
port 8080
db_url:template http://{server.host}:{server.port}/dbResult: "http://localhost:8080/db"
:split — Split String into Array
Splits a string by a delimiter into an array of items. Auto-casts values if they look like numbers.
Default delimiter (comma):
!active
colors:split red, green, blueResult: ["red", "green", "blue"]
With delimiter keyword:
!active
// Space delimiter
words:split:space hello world foo
// Pipe delimiter
flags:split:pipe read write executeSupported delimiter keywords: space, pipe, dash, dot, semi, tab
Auto-casting:
!active
numbers:split 1, 2, 3Result: [1, 2, 3] (auto-detected as integers)
:join — Join Array into String
Joins array elements into a string with a delimiter.
Default delimiter (comma):
!active
tags:join
- action
- rpg
- adventureResult: "action, rpg, adventure"
With delimiter keyword:
!active
path:join:slash
- home
- user
- documentsResult: "home/user/documents"
:ref — Reference and Chain
Resolves a key by name and passes the value to subsequent markers in the chain. Similar to :alias, but designed for chaining with :calc and other transformations.
!active
base_rate 100
adjusted:ref:calc:*2 base_rateResult: adjusted = 200. The shorthand :ref:calc:*2 base_rate resolves base_rate → 100, then computes 100 * 2.
:i18n — Internationalization
Selects a translated value based on the runtime locale. Child keys are language codes; the engine picks the one matching options.lang (defaults to en).
!active
greeting:i18n
en Hello
ru Привет
de HalloPluralization — append the count field name: :i18n:count_field
!active
items_label:i18n:item_count
en
one {count} item
other {count} items
ru
one {count} предмет
few {count} предмета
many {count} предметов
other {count} предметовPlural categories follow CLDR rules (en: one/other, ru: one/few/many/other). {count} is substituted with the referenced field's value.
:clamp — Numeric Range Clamping
Clamps a numeric value to a minimum–maximum range.
!active
volume:clamp:0:100 150
# → 100
brightness:clamp:0:255 -10
# → 0Error if MIN > MAX.
:round — Numeric Rounding
Rounds a numeric value to N decimal places.
!active
price:round:2 19.999
# → 20.00
pi:round:4 3.14159265
# → 3.1416
whole:round:0 42.7
# → 43Default: 0 decimal places (rounds to integer).
:format — Printf-Style Formatting
Formats a value using a printf-style pattern.
!active
price:format:%.2f 19.9
# → "19.90"
code:format:%04d 42
# → "0042"Supported patterns: %.Nf (float), %d (int), %0Nd (zero-padded). Max width/precision: 4096/1024.
:map — Lookup Table
Maps a value through a lookup table. Child list items are lookup_value result_text pairs.
!active
status_labels
200 OK
404 Not Found
500 Internal Server Error
result:map:status_labels
- 200
- 404
- 500Result: ["OK", "Not Found", "Internal Server Error"]. If no match found, returns null.
:once — Generate Once, Cache
Generates a value once at first parse and caches it in a .synx.lock sidecar file for subsequent reads.
!active
instance_id:once:uuid
# → "550e8400-e29b-41d4-a716-446655440000" (stable across parses)
created_at:once:timestamp
# → "2026-04-01T12:00:00Z" (frozen at first parse)Types: uuid, timestamp, random.
:version — Version Comparison
Compares a value against a semantic version constraint. Returns a boolean.
!active
app_ok:version:>=:1.0.0 1.2.3
# → true
engine_ok:version:>=:2.0.0 1.9.5
# → falseOperators: >=, <=, >, <, ==, !=. Parses semver (x.y.z…).
:watch — Read External File
Reads an external JSON or SYNX file at parse time and injects its content as the value.
!active
all_flags:watch ./flags.synx
db_host:watch:database.host ./infra.jsonOptional key path after :watch: extracts a specific nested value. Max depth: 16, max size: 10 MiB. Path-jail enforced.
:fallback — File Fallback
If the primary source file is missing, uses the fallback path instead.
!active
config:fallback:./defaults.synx ./overrides.synxAlso applies if the value is null or empty.
:spam — Rate Limiting
Limits how many times a value can be accessed within a time window.
!active
api_endpoint:spam:5:60 https://api.example.com/data
# Max 5 accesses per 60 secondsWindow defaults to 1 second if omitted. The counter lives in process memory and resets on restart.
:prompt — LLM Prompt Label
Formats a subtree as a labeled code fence for LLM consumption.
!active
config_block:prompt:AppConfig
app_name MyCoolApp
version 2.1.0Output: `AppConfig (SYNX):\n```synx\n...\n````
:vision — Image Metadata (pass-through)
Marks a value as an image reference for vision model input. No engine transformation — applications detect via metadata.
!active
diagram:vision ./docs/architecture.png:audio — Audio Metadata (pass-through)
Marks a value as an audio reference for audio model input. No engine transformation — applications detect via metadata.
!active
recording:audio ./meetings/standup.mp3:import — Alias for :include
Identical to :include. Use whichever reads more naturally.
!active
db:import ./config/db.synx:inherit — Object Inheritance (Mixin)
Inherits all fields from one or more parent objects. Child fields take priority.
!active
base
host localhost
port 8080
debug false
production:inherit base
host prod.example.com
debug falseResult: production = { "host": "prod.example.com", "port": 8080, "debug": false }. Parents are merged left to right, then child overrides. Resolved in a pre-pass before other markers.
3.3 Functions Summary Table
| Function | Description | Example |
|---|---|---|
:random | Random item from list | phrase:random |
:random N N N | Weighted random (percentages) | loot:random 70 20 10 |
:calc | Arithmetic evaluation | total:calc price * 1.2 |
:env | Environment variable | port:env PORT |
:alias | Reference to another key | copy:alias original |
:secret | Value hidden from logs | password:secret abc123 |
:default | Default value | theme:default dark |
:default:X | Fallback (in combination) | port:env:default:8080 PORT |
:unique | List deduplication | tags:unique |
:include | Include external file | db:include ./db.synx |
:import | Alias for :include | db:import ./db.synx |
:geo | Value by region | currency:geo |
:template | String interpolation | greeting:template Hello, {name}! |
:split | String → array | colors:split red, green, blue |
:join | Array → string | tags:join |
:ref | Resolve and chain | adjusted:ref:calc:*2 base_rate |
:i18n | Translation by locale | greeting:i18n |
:clamp | Numeric clamping | volume:clamp:0:100 150 |
:round | Numeric rounding | price:round:2 19.999 |
:format | Printf-style formatting | price:format:%.2f 19.9 |
:map | Lookup table | result:map:status_labels |
:once | Generate once, cache | id:once:uuid |
:version | Version comparison | ok:version:>=:1.0.0 1.2.3 |
:watch | Read external file | flags:watch ./flags.synx |
:fallback | File fallback | cfg:fallback:./default.synx ./custom.synx |
:spam | Rate limiting | api:spam:5:60 endpoint |
:prompt | LLM prompt label | ctx:prompt:system Your instructions |
:vision | Image metadata | img:vision ./photo.png |
:audio | Audio metadata | snd:audio ./clip.mp3 |
:inherit | Object inheritance | prod:inherit base |
Chaining functions — via : chain:
!active
port:env:default:8080 PORT3.4 Constraints ([]) — Data Validation
Constraints are written in square brackets between the key and the function (or value). They only work in !active mode.
General syntax:
key[constraint1:value, constraint2:value]:function valuemin / max — Minimum and Maximum
For numbers — restricts the value range.
For strings — restricts the length (character count).
!active
// String from 3 to 30 characters
app_name[min:3, max:30] TotalWario
// Number from 1 to 100
volume[min:1, max:100] 75
// Minimum only
password[min:8] mypassword123required — Required Field
The parser will throw an error if the value is empty or missing.
!active
api_key[required]:env API_KEY
name[required, min:1] Wariopattern — Regular Expression
The value must match a regex pattern.
!active
country_code[pattern:^[A-Z]{2}$] US
phone[pattern:^\+\d{10,15}$] +12025551234enum — Allowed Values
The value must be one of the listed options.
!active
theme[enum:light|dark|auto] dark
region[enum:EU|US|GB|AS] USreadonly — Read Only
The value cannot be changed via API / hot-reload of the config. Only manual file editing.
!active
version[readonly] 2.0.03.5 Constraints Summary Table
| Constraint | Description | Syntax |
|---|---|---|
min | Minimum (length in characters, or value) | [min:3] |
max | Maximum (length in characters, or value) | [max:100] |
type | Data type | [type:int] |
required | Required field | [required] |
pattern | Regex validation | [pattern:^\d+$] |
enum | List of allowed values | [enum:a|b|c] |
readonly | Modification forbidden | [readonly] |
A string's length is its number of Unicode characters (scalar values): мир and 東京都 are 3, 😀 is 1. Until 3.7.4 the Rust engine counted UTF-8 bytes.
A failed constraint replaces the value with a CONSTRAINT_ERR: … string. Constraints are also collected by field name across the whole document — the strictest declaration wins — and checked against every field of that name once all markers are resolved. A pattern that nests one quantifier inside another (^(a+)+$) is skipped rather than run, so a hostile document cannot stall the parser.
Constraints can be combined with commas:
!active
password[required, min:8, max:64, type:string] MyP@ssw0rd3.6 Directives
Directives are top-level lines that begin with ! or #!. They control the document's mode and metadata. A directive must appear before any key-value lines.
| Directive | Description |
|---|---|
!active | Enable markers, constraints, and validation (see §3.1) |
!lock | Mark document as read-only (metadata flag) |
!include | Include another SYNX file at the document root level |
!tool | Reshape output as a tool-call envelope (name + params) |
!schema | Export a JSON Schema Draft 2020-12 from the document structure |
!llm | Annotate document for LLM consumption (metadata-only) |
!lock — Read-Only Hint
Sets the locked flag on the parse result. The data tree is unchanged — it is advisory metadata for tooling.
!lock
name Alice
role admin!include — Document-Level Include
Includes another SYNX file and merges its contents at the root level. An optional alias assigns the included tree to a named key.
!include ./db.synx
!include ./auth.synx auth_config
name MyAppMaximum depth: 16. Path-jail security prevents .. escapes.
!tool — Tool Call Envelope
Reshapes the output: the first key becomes the tool name, its children become parameters.
!tool
web_search
query rust async
lang en
results 10Output:
{
"tool": "web_search",
"params": {
"query": "rust async",
"lang": "en",
"results": 10
}
}!schema — JSON Schema Export
Causes the parser to emit a JSON Schema Draft 2020-12 object derived from the document's keys and constraints.
!schema
name[required, type:string]
port[type:int, min:1, max:65535]!llm — LLM Metadata
Metadata-only directive for LLM tooling. Does not change the parsed data tree.
!llm
persona Assistant
role You are a helpful coding assistant
tone professional and concise