Test a mod
A mod is an ordinary program that reads JSON lines and writes JSON lines. That makes it easy to test without starting Syntic Code at all: feed it the messages a session would send, and check what it writes back. Once the program behaves, enable it and try it in a real session.
This page covers three levels of testing:
- Check the manifest.
- Drive the program by hand or from a script.
- Try it in a live session.
Check the manifest
syntic mod list reads every folder in ~/.syntic/mods/ and validates its mod.json:
syntic mod listMods in /home/sam/.syntic/mods
turn-clock 0.1.0 [off] Footer clock for the current turn and a pane with recent turn times
pr-pane [broken]
mod.json names `pr-panel` but the folder is `pr-pane`A [broken] mod is never started. The line under it says why. Common reasons are covered in Troubleshoot a mod.
syntic mod enable <name> goes one step further: it also checks that the program in command can be found. A relative path must exist inside the mod folder; a bare name must be found on the cleaned PATH.
Folders whose name is not a valid mod name (for example My_Mod), and folders without a mod.json, are skipped silently by syntic mod list. If your mod is missing from the list entirely, check the folder name first.
Drive the program by hand
Run the program from its folder and type messages yourself. Start with hello, then send events:
cd ~/.syntic/mods/turn-clock
sh run.shPaste these lines one at a time:
{"type":"hello","protocol":1,"mod":"turn-clock","events":["turn.start","turn.end"],"ui":["status","pane"],"granted":["notes"]}
{"type":"event","event":"turn.start","data":{"turn":1}}
{"type":"event","event":"turn.end","data":{"turn":1,"seconds":130}}
{"type":"bye"}You should see the mod’s replies right after each line, for example:
{"type":"draw","slot":"status","text":"turn clock ready"}
{"type":"draw","slot":"status","text":"turn 1 running"}
{"type":"draw","slot":"status","text":"turn 1 took 130s"}
{"type":"draw","slot":"pane","title":"Turn times","lines":["turn 1: 130s"]}
{"type":"call","id":1,"method":"note.post","params":{"text":"Turn 1 took 130s."}}If a reply only shows up after you press Ctrl+D, your program is buffering its output. Flush after every line.
Script a test
Put the input in a file and check the output with any tool you like. This example uses jq to make sure every output line is valid JSON with a known type:
cat > /tmp/turn-clock.in <<'EOF'
{"type":"hello","protocol":1,"mod":"turn-clock","events":["turn.start","turn.end"],"ui":["status","pane"],"granted":["notes"]}
{"type":"event","event":"turn.start","data":{"turn":1}}
{"type":"event","event":"turn.end","data":{"turn":1,"seconds":7}}
{"type":"bye"}
EOF
sh run.sh < /tmp/turn-clock.in > /tmp/turn-clock.out
jq -e 'select(.type != "draw" and .type != "call" and .type != "subscribe")' /tmp/turn-clock.out \
&& echo "unexpected message type" || echo "all lines ok"
grep -c '"slot":"pane"' /tmp/turn-clock.outThings worth testing:
| Case | Input to send | What to expect |
|---|---|---|
| Normal start | hello with all grants | A first draw, if the mod shows something at start |
| Missing grant | hello with "granted":[] | No call to methods that need a permission |
| Unknown fields | an event with extra keys in data | No crash; extra keys ignored |
| Missing fields | turn.end without seconds | A sensible fallback, not a crash |
| Error results | {"type":"result","id":1,"ok":false,"error":"too many notes; try again in a minute"} | The mod keeps running |
| Shutdown | bye | The program exits quickly (under half a second) |
| End of input | close standard input without bye | The program exits |
Also check the size of what you draw. Text over the slot limits is cut with an ellipsis, which may hide the part you care about. See Screen areas for the limits.
Match the real environment
In a session, a mod starts with almost no environment variables and runs in its own folder. A mod that works in your shell may fail there because it relied on a variable or a tool from a project folder. Reproduce the real start-up on Unix with env -i:
cd ~/.syntic/mods/turn-clock
env -i HOME="$HOME" PATH=/usr/bin:/bin \
SYNTIC_MOD_NAME=turn-clock \
SYNTIC_MOD_DIR="$PWD" \
SYNTIC_MOD_DATA="$HOME/.syntic/mod-data/turn-clock" \
SYNTIC_MOD_PROTOCOL=1 \
sh run.sh < /tmp/turn-clock.inThe real PATH is your own PATH with unsafe entries removed (relative folders, missing folders and anything inside the opened project), plus standard system folders. The full list of variables is on the Mod API page.
Try it in a live session
Enable the mod
syntic mod enable turn-clockStart a session
synticMods start right after the session is set up. If a mod fails to start, a warning line in the conversation says so and gives the reason.
Exercise each event
- Send a prompt to trigger
turn.startandturn.end. - Change the permission mode to trigger
mode.change. - Exit the session to trigger
session.endandbye.
Check each slot
Widen the terminal to at least 90 columns to see panes. Narrow it to confirm the mod is still useful when panes are hidden.
Log while you debug
Standard error is discarded in a session, so write logs to a file in your data folder:
log() { printf '%s\n' "$*" >> "$SYNTIC_MOD_DATA/debug.log"; }Then follow it from another terminal:
tail -f ~/.syntic/mod-data/turn-clock/debug.logRemove or quiet the logging before you share the mod.
Next steps
- Troubleshoot a mod: common failures and their messages.
- Mod API: the exact messages to fake in tests.