Skip to main content

IPC API

TwiLite exposes a local Windows named-pipe IPC API for external tools that need to inspect or control running clients.

Each client instance owns a separate named pipe. This avoids a shared discovery file being overwritten when many clients are running.

Discovery

Enumerate Windows named pipes under:

\\.\pipe\

TwiLite IPC pipe names start with:

twilite-ipc-

The full pipe path looks like:

\\.\pipe\twilite-ipc-12345-550e8400-e29b-41d4-a716-446655440000

The number after twilite-ipc- is the process id. The suffix is the client instance id.

Authentication

The IPC token is stored in:

%USERPROFILE%\twilite\secrets\ipc-token.properties

Every request must include the token in the JSON body:

{
"token": "<token>",
"command": "health"
}

Request Format

The pipe protocol is one JSON request and one JSON response per connection.

Open the named pipe, write a UTF-8 JSON object, read the UTF-8 JSON response, then close the pipe.

All requests use:

{
"token": "<token>",
"command": "<command>"
}

All successful responses include:

{
"ok": true,
"sentAt": "2026-05-27T21:00:00Z"
}

Errors use:

{
"ok": false,
"code": "unauthorized",
"message": "Missing or invalid IPC token.",
"sentAt": "2026-05-27T21:00:00Z"
}

Health

Command:

{
"token": "<token>",
"command": "health"
}

Returns:

{
"ok": true,
"version": 1,
"instanceId": "550e8400-e29b-41d4-a716-446655440000",
"pid": 12345,
"pipe": "\\\\.\\pipe\\twilite-ipc-12345-550e8400-e29b-41d4-a716-446655440000"
}

List Plugins

Command:

{
"token": "<token>",
"command": "plugins"
}

Returns all loaded plugins with source and active state.

{
"ok": true,
"plugins": [
{
"id": "marketplace:auto-gauntlet",
"name": "Auto Gauntlet",
"source": "Marketplace",
"active": true,
"configName": "marketplace:auto-gauntlet:autoGauntlet"
}
]
}

Use id for unambiguous plugin control.

Active Sessions

Command:

{
"token": "<token>",
"command": "sessions"
}

Returns active/running plugins only.

{
"ok": true,
"sessions": [
{
"id": "local:com.example.ExamplePlugin",
"name": "Example",
"source": "Local",
"active": true
}
]
}

Start Plugin

Command:

{
"token": "<token>",
"command": "startPlugin",
"id": "marketplace:auto-gauntlet"
}

You can also use a display name and optional source:

{
"token": "<token>",
"command": "startPlugin",
"plugin": "Auto Gauntlet",
"source": "marketplace"
}

Starting a plugin reloads local and marketplace plugin jars first. This supports replacing plugin code and then restarting it through IPC.

Returns:

{
"ok": true,
"changed": true,
"action": "start",
"plugin": "marketplace:auto-gauntlet",
"source": ""
}

Stop Plugin

Command:

{
"token": "<token>",
"command": "stopPlugin",
"id": "marketplace:auto-gauntlet"
}

Returns the same shape as start, with "action": "stop".

Player State

Command:

{
"token": "<token>",
"command": "player"
}

Returns the current local player snapshot.

{
"ok": true,
"loggedIn": true,
"world": 301,
"name": "player",
"coord": {
"x": 3200,
"y": 3200,
"floor": 0
},
"stats": [
{
"name": "ATTACK",
"base": 99,
"experience": 13034431
}
]
}

PowerShell Example

$tokenProps = Get-Content "$env:USERPROFILE\twilite\secrets\ipc-token.properties"
$token = ($tokenProps | Where-Object { $_ -like 'token=*' }) -replace '^token=', ''
$pipe = [System.IO.Directory]::GetFiles('\\.\pipe\') |
Where-Object { [System.IO.Path]::GetFileName($_).StartsWith('twilite-ipc-') } |
Select-Object -First 1

$client = [System.IO.Pipes.NamedPipeClientStream]::new(
'.',
[System.IO.Path]::GetFileName($pipe),
[System.IO.Pipes.PipeDirection]::InOut
)
$client.Connect(2000)

$request = @{ token = $token; command = 'sessions' } | ConvertTo-Json -Compress
$bytes = [System.Text.Encoding]::UTF8.GetBytes($request)
$client.Write($bytes, 0, $bytes.Length)
$client.Flush()

$buffer = New-Object byte[] 1048576
$read = $client.Read($buffer, 0, $buffer.Length)
$response = [System.Text.Encoding]::UTF8.GetString($buffer, 0, $read)
$client.Dispose()

$response | ConvertFrom-Json