mod.json reference
Every mod folder holds a mod.json file. It names the mod, says how to start its program, and declares everything the mod may hear, draw and ask for. Syntic Code checks it strictly: an unknown key, event, slot or permission makes the whole file invalid, and the mod is listed as [broken].
Complete example
{
"name": "review-queue",
"version": "1.3.0",
"description": "Pane with the pull requests waiting for your review",
"command": ["python3", "main.py", "--max", "8"],
"events": ["session.start", "turn.end"],
"ui": ["pane", "status"],
"permissions": ["session.read"]
}Fields
| Field | Type | Required | Default | Meaning |
|---|---|---|---|---|
name | string | yes | The mod’s name. Must match its folder name. | |
version | string | no | "" | Shown by syntic mod list. Free text. |
description | string | no | "" | Shown by syntic mod list. |
command | string or string array | yes | The program to start, and its arguments. | |
events | string array | no | [] | Session events the mod may receive. |
ui | string array | no | [] | Slots the mod may draw in. |
permissions | string array | no | [] | API permissions the mod asks the user for. |
No other keys are allowed.
name
- 1 to 40 characters.
- Only lowercase ASCII letters, digits and
-. - Must not start with
-. - Must be exactly the same as the mod’s folder name under
~/.syntic/mods/.
Valid: turn-clock, pr2, build-status. Not valid: Turn-Clock, -clock, my_mod, ../x.
version and description
Plain strings for people. Syntic Code does not compare versions; it does not update mods.
command
How to start the mod’s program. Either one string (the program, no arguments):
"command": "./run"or an array of the program followed by its arguments:
"command": ["sh", "run.sh"]Arguments are passed as given; there is no shell, so quotes, * and $VAR are not expanded. The program must not be empty.
The first entry is resolved like this:
| Form | Example | How it is found |
|---|---|---|
| Absolute path | /usr/local/bin/my-mod | Used as is. |
Path with a separator (/ or \) | ./run, bin/my-mod | Relative to the mod folder. It must not contain .., and its real location (after following symlinks) must be inside the mod folder. |
| Bare name | python3, node, sh | Looked up on a cleaned PATH that never includes folders inside the opened project. |
The program is checked when you run syntic mod enable, and again each time a session starts it. It always runs with the mod folder as its working folder.
events
The events the mod may receive. Allowed values:
| Value | Sent when |
|---|---|
session.start | The session’s mods have started |
session.end | The session is closing |
turn.start | The agent starts answering |
turn.end | The agent finishes answering |
mode.change | The permission mode changes |
Duplicates are dropped. At run time a mod can narrow this list with a subscribe message, but never extend it. Details and payloads are on the Events page.
ui
The slots the mod may draw in. Allowed values:
| Value | Slot | Size |
|---|---|---|
status | Footer item | 40 characters |
band | Rows above the prompt | 2 rows of 200 characters |
pane | Box at the right of the conversation | 12 rows of 60 characters, 30-character title |
Duplicates are dropped. Drawing into a slot not listed here is refused and counts as a bad line. See Screen areas.
permissions
The API permissions the mod asks for. Allowed values:
| Value | Lets the mod | Shown to the user as |
|---|---|---|
notes | Call note.post | post short notes into the conversation view |
session.read | Call session.state | read the session id, model, mode, turn count and folder |
Duplicates are dropped. Asking is not the same as having: the user grants these when they run syntic mod enable. The hello message’s granted list says what the mod actually has. See Mod API.
Ask only for what you use. A mod that only draws needs no permissions, and syntic mod enable will say it asked for none.
Where things live
| Path | Holds |
|---|---|
~/.syntic/mods/<name>/mod.json | The manifest |
~/.syntic/mods/<name>/ | The mod’s program and files; also its working folder |
~/.syntic/mods.json | Which mods are on and what each was granted, written by syntic mod enable/disable |
~/.syntic/mod-data/<name>/ | The mod’s private data folder ($SYNTIC_MOD_DATA) |
When SYNTIC_CONFIG_DIR is set to an absolute path, all of these live under that folder instead of ~/.syntic.
The state file looks like this. Do not edit it by hand; use the commands.
{
"mods": {
"turn-clock": { "enabled": true, "granted": ["notes"] }
}
}syntic mod commands
| Command | Does |
|---|---|
syntic mod list | Lists installed mods with version, [on], [off] or [broken], description, granted permissions and any new permissions an update asks for. |
syntic mod enable <name> | Checks the manifest and program, switches the mod on and grants every permission it asks for. Prints what was granted, which slots it draws in and which events it hears. |
syntic mod disable <name> | Switches the mod off and drops its grants. Says so if it was already off. |
enable and disable exit with code 1 on failure. All three take effect from the next interactive session.
Environment variables
| Variable | Read by | Meaning |
|---|---|---|
SYNTIC_DISABLE_MODS | Syntic Code | Keeps every mod off when set to anything other than empty, 0, false, no or off. |
SYNTIC_CONFIG_DIR | Syntic Code | An absolute path that replaces ~/.syntic, including the mods folder. |
SYNTIC_MOD_NAME | The mod | Its name. |
SYNTIC_MOD_DIR | The mod | Its folder. |
SYNTIC_MOD_DATA | The mod | Its private data folder. |
SYNTIC_MOD_PROTOCOL | The mod | The protocol version, 1. |
Limits at a glance
| Limit | Value |
|---|---|
| Name length | 40 characters |
| Line length from a mod | 64 KB (longer lines are dropped) |
| Bad lines allowed before the mod is stopped | 20 (the 21st stops it) |
| Messages queued for a mod | 64 (newer events are dropped when full) |
| Note length | 500 characters |
| Notes per mod | 5 per 60 seconds |
Time to exit after bye | 0.5 seconds |
| Narrowest conversation area that shows panes | 90 columns |