AX.25 Terminal

Interactive AX.25 connected-mode sessions to BBSes, PMSes, and other live packet hosts — right in the browser

The AX.25 Terminal is a built-in connected-mode client. Open it, pick a radio channel, type the callsign of a BBS or another live station, and you get an xterm-style window into a live LAPB session over RF — no second program, no AGWPE bridge, no KISS-side TNC software. Graywolf speaks AX.25 v2.0 (modulo 8) and negotiates modulo 128 when the peer supports it, with automatic fallback if the peer answers SABME with DM.

AX.25 Terminal route showing a connected session to a BBS
A connected session to a BBS, with the telemetry side panel open

Prerequisite: set the channel mode

Connected-mode AX.25 is only enabled on channels whose Mode is set to packet or aprs+packet. APRS-only channels refuse new sessions — the pre-connect form on those channels switches to a read-only raw-tail view instead (see Raw-tail mode below). Set the mode on Radio Channels.

The mode column gates transmission, not reception. A packet channel still receives and demodulates everything — APRS frames keep flowing into the live map and packet log. The mode just refuses new outbound APRS beacons, digipeats, and iGate IS→RF, so the channel can be dedicated to a single LAPB conversation without other subsystems stepping on it.

Opening a session

Click Terminal in the sidebar. With no session active, you get the pre-connect form:

Channel Pick the radio channel to transmit on. Only channels with a packet-capable mode appear.
Local Callsign Your station, optionally with an SSID: K0SWE or K0SWE-3. SSID 0 through 15 is the AX.25 spec; pick a different SSID per concurrent session if you plan to run multiple links from the same callsign.
Destination Callsign The BBS or peer station, same format. For a typical W1AW BBS that would be something like W1AW-4.
Via path Optional comma-separated digipeater list (up to 8 hops). Leave blank for a direct connection.

Click Connect. The form swaps for the live xterm viewport as soon as the link reaches CONNECTED state. If the peer answers DM (busy / not listening), the form re-appears with the reason in red.

Advanced timer settings

The pre-connect form has an Advanced disclosure that opens to AX.25 protocol knobs. Operators almost never need to touch these — the defaults match what a Linux kernel ax25 stack would use — but they are exposed for the cases that do.

FieldDefaultWhat it does
mod 128 off Negotiate modulo-128 sequence numbers (SABME). Lets the link have up to 127 outstanding I-frames instead of 7. Falls back to mod-8 automatically if the peer answers DM.
paclen 0 (server picks) Maximum I-field bytes per outbound I-frame. 0 means use the kernel-default 256.
window 0 (server picks) Outstanding-I-frame window. 0 means 4 (mod-8) or 32 (mod-128).
N2 0 (server picks) Maximum retransmits before declaring the link down. 0 means 10.
T1 / T2 / T3 ms 0 (server picks) Retransmit / response-delay / link-idle timers. 0 leaves the kernel-default values in place; override only if your path RTT is unusual.
backoff linear Retry backoff curve: linear, exponential, or none. Exponential helps on noisy channels.

Defaults you set on Preferences (modulo and paclen) seed the form; per-session changes are not persisted — the next connection starts from the Preferences defaults again.

While connected

The connected view shows a fixed 80×24 xterm window with a status bar across the bottom: state, peer, RTT, and a small radio button that toggles the telemetry side panel. The telemetry panel updates once per second while CONNECTED and shows the live LAPB counters: V(S), V(R), V(A), retry count (N2), busy / peer-busy flags, and the RTT exponential moving average. It stops updating in any other state.

Type to send. Anything you type goes out as I-frame data; bytes from the peer come in and render in the viewport. The terminal uses xterm.js with disableStdin: false, so your keystrokes never echo locally — the BBS sees them, the BBS echoes them back, and you see what the BBS chose to display. This is the correct behavior for a real LAPB session: the peer is the authority on what gets shown.

Command bar

Press Ctrl-] to drop into the command bar at the bottom of the terminal. From there:

CommandEffect
disconnect Send DISC, wait for UA, close the link gracefully.
abort Send DM and close immediately. Use when the peer is unresponsive.
transcript on / transcript off Start or stop recording the session to the transcript store.

Esc closes the command bar without acting.

Macros

The macro toolbar above the viewport holds operator-defined buttons. Each macro has a label and a payload (text or arbitrary bytes); clicking the button sends the payload immediately as I-frame data. Edit macros from the gear icon — payloads are stored base64-encoded so they can hold control characters and non-printable bytes.

Macros are global (one set per station), not per-session.

Tabs

The tab bar above the macro toolbar lets you run up to six concurrent sessions. Each tab is its own LAPB link, so you can run a BBS session in one tab and a peer-to-peer keyboard-to-keyboard chat in another. The unread-bytes count in each tab’s label tracks bytes that arrived while the tab was not focused; the sidebar Terminal entry shows the same total across all backgrounded tabs.

Ctrl-PageUp and Ctrl-PageDown move between tabs from the keyboard.

Transcripts

Turning transcript on begins recording every byte and state-change to the transcript store. The recorder logs RX bytes, TX bytes, state transitions, and link errors; the Transcripts sub-route lists all completed sessions and lets you replay or delete them. Transcripts live in the SQLite config DB and are not size-bounded, so prune occasionally if you record a lot.

Transcripts capture the byte stream as the session saw it, including the BBS’s screen-clear sequences and form-feeds. Replays render in a styled monospace viewer rather than a live terminal — expect to see escape sequences as text, not as cursor moves.

Saved profiles and recents

Successful CONNECTED transitions are upserted into a recents list under the pre-connect form. Click any recent to populate the form with its channel, callsigns, via path, and timer settings. Pin a recent (the pin icon turns it into a saved profile) and it stays at the top of the list permanently — pinned profiles never get trimmed; unpinned recents top out at 20 entries.

Raw-tail mode (APRS-only channels)

If you open the Terminal page on an APRS-only channel, the pre-connect form is replaced with a raw-packet viewer instead. It subscribes to the same packet-log fan-out the Monitoring page uses and shows every RX and TX frame on that channel as it happens, in TNC2 text format. There is no LAPB session in this mode — the raw-tail view is for watching APRS traffic live; switch the channel mode to packet or aprs+packet first if you want to open a session.

Defaults and theming

Preferences has an AX.25 Terminal tab where you can set:

Scrollback rows How much history the terminal viewport keeps. Larger values use more browser memory.
Cursor blink On / off. Off is easier on the eyes for long sessions.
Default modulo Pre-fills the Advanced → mod 128 checkbox on every new session.
Default paclen Pre-fills the Advanced → paclen field.
Theme preset classic, phosphor-green, or phosphor-amber. The terminal palette is resolved from CSS variables, so the preset also tracks the global graywolf theme.

Out-of-scope

The terminal is an outbound-only client. It does not:

For a hosting-side BBS or a NET/ROM node, run a dedicated package (LinBPQ, JNOS, etc.) alongside graywolf and connect to it through the KISS interface.