API Reference¶
Straw's IPC API allows programmatic interaction with the daemon.
Overview¶
The daemon exposes a JSON-RPC API over Unix Domain Sockets (or named pipes on Windows). The TUI client uses this API to communicate with the daemon.
Connection¶
Socket Location¶
Default socket paths by platform:
| Platform | Default Path |
|---|---|
| Linux | ~/.config/straw/straw.sock or /tmp/straw.sock |
| macOS | ~/Library/Application Support/straw/straw.sock |
| Windows | \\.\pipe\straw |
Connecting¶
Go Example:
conn, err := net.Dial("unix", "/tmp/straw.sock")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
Python Example:
import socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/tmp/straw.sock")
Protocol¶
JSON-RPC 2.0¶
All communication uses JSON-RPC 2.0 format:
Request:
Success Response:
Error Response:
Methods¶
GetStatus¶
Get the current daemon status.
Request:
Response:
{
"jsonrpc": "2.0",
"result": {
"status": "running",
"version": "1.0.0",
"uptime": 3600,
"watches": 3,
"rules": 10
},
"id": 1
}
GetEvents¶
Get recent file system events.
Request:
{
"jsonrpc": "2.0",
"method": "GetEvents",
"params": {
"limit": 50,
"since": "2024-01-01T00:00:00Z"
},
"id": 2
}
Response:
{
"jsonrpc": "2.0",
"result": {
"events": [
{
"timestamp": "2024-01-15T10:30:00Z",
"type": "created",
"path": "/home/user/Downloads/file.pdf",
"rule": "Organize PDFs",
"action": "move"
}
]
},
"id": 2
}
GetRules¶
Get all configured rules.
Request:
Response:
{
"jsonrpc": "2.0",
"result": {
"rules": [
{
"name": "Organize PDFs",
"enabled": true,
"matches": 42,
"match": {
"extension": ".pdf"
},
"actions": [
{
"type": "move",
"target": "~/Documents/PDFs"
}
]
}
]
},
"id": 3
}
AddRule¶
Add a new rule dynamically.
Request:
{
"jsonrpc": "2.0",
"method": "AddRule",
"params": {
"name": "New Rule",
"enabled": true,
"match": {
"extension": ".txt"
},
"actions": [
{
"type": "move",
"target": "~/Documents/Text"
}
]
},
"id": 4
}
Response:
RemoveRule¶
Remove a rule by name or ID.
Request:
Response:
EnableRule / DisableRule¶
Enable or disable a rule.
Request:
Response:
ReloadConfig¶
Reload the configuration from disk.
Request:
Response:
GetWatches¶
Get all watched directories.
Request:
Response:
{
"jsonrpc": "2.0",
"result": {
"watches": [
{
"path": "~/Downloads",
"recursive": true,
"active": true
}
]
},
"id": 8
}
TriggerAction¶
Manually trigger an action on a file.
Request:
{
"jsonrpc": "2.0",
"method": "TriggerAction",
"params": {
"file": "/home/user/test.pdf",
"action": {
"type": "move",
"target": "~/Documents"
}
},
"id": 9
}
Response:
Error Codes¶
| Code | Message | Description |
|---|---|---|
| -32700 | Parse error | Invalid JSON |
| -32600 | Invalid Request | Invalid request object |
| -32601 | Method not found | Unknown method |
| -32602 | Invalid params | Invalid method parameters |
| -32603 | Internal error | Internal daemon error |
| -32000 | Config error | Configuration error |
| -32001 | Watch error | Filesystem watch error |
| -32002 | Action error | Action execution error |
Example Client¶
Go Client:
package main
import (
"encoding/json"
"fmt"
"net"
)
type Client struct {
conn net.Conn
}
func NewClient(socketPath string) (*Client, error) {
conn, err := net.Dial("unix", socketPath)
if err != nil {
return nil, err
}
return &Client{conn: conn}, nil
}
func (c *Client) Call(method string, params interface{}) (map[string]interface{}, error) {
req := map[string]interface{}{
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1,
}
encoder := json.NewEncoder(c.conn)
if err := encoder.Encode(req); err != nil {
return nil, err
}
var resp map[string]interface{}
decoder := json.NewDecoder(c.conn)
if err := decoder.Decode(&resp); err != nil {
return nil, err
}
return resp, nil
}
func main() {
client, err := NewClient("/tmp/straw.sock")
if err != nil {
panic(err)
}
defer client.conn.Close()
result, err := client.Call("GetStatus", nil)
if err != nil {
panic(err)
}
fmt.Printf("Status: %+v\n", result)
}
WebSocket Bridge¶
For browser-based clients, a WebSocket bridge can be used:
See examples/websocket-bridge/ for a complete implementation.