Stateful HTTP ingest + MCP server + terminal UI for Ray-style logs.
Raymon is:
- CLI-first: one binary, local-first defaults.
- MCP-first: a small set of tools with explicit schemas for agents/LLMs.
- Keyboard-first: a Ratatui TUI designed for fast filtering, yanking, navigation and export.
cargo install raymonbrew install bnomei/raymon/raymonDownload a prebuilt archive from the GitHub Releases page, extract it, and place raymon on your PATH.
git clone https://github.com/bnomei/raymon.git
cd raymon
cargo build --releaseYou can send from any compatible Ray App library such as PHP, Javascript, Bash, Ruby, Python, Go and Dart.
If you want a Rust-native way to send Ray-compatible payloads, use my companion library ray-dbg.
Run Raymon on the Ray default port:
raymon
# or
RAYMON_PORT=23517 raymonraymon --demo- Start your local HTTP with TUI listening to default port
23517
raymon- Add the local HTTP to the agents harness via MCP settings:
codex mcp add raymon --url http://127.0.0.1:23517/mcp{
"mcpServers": {
"raymon": {
"url": "http://127.0.0.1:23517/mcp"
}
}
}- Start Raymon (recommended: require + send auth)
export RAYMON_AUTH_TOKEN="change-me"
RAYMON_ALLOW_REMOTE=1 RAYMON_HOST=0.0.0.0 RAYMON_NO_TUI=1 RAYMON_AUTH_TOKEN="$RAYMON_AUTH_TOKEN" raymonRaymon will refuse non-loopback binds without RAYMON_AUTH_TOKEN unless you set RAYMON_ALLOW_INSECURE_REMOTE=1.
- Add it to your MCP client:
codex mcp add raymon --url http://<host>:23517/mcp --bearer-token-env-var RAYMON_AUTH_TOKEN{
"mcpServers": {
"raymon": {
"url": "http://<host>:23517/mcp"
}
}
}POST /: Ray ingest endpoint (Ray payload envelope).- If the request body looks like JSON-RPC (
{"jsonrpc":"2.0","method":...}), Raymon will treat it as MCP.
- If the request body looks like JSON-RPC (
POST /mcp: MCP Streamable HTTP endpoint.
Raymon exposes an intentionally small tool surface so it stays usable for agents.
Tools and their input/output shapes:
-
raymon.search- search stored entries (supportslimit+offset)Parameters:
{ "query": "string (optional; plain text or /regex/)", "types": ["string"], "colors": ["string"], "screen": "string (optional)", "project": "string (optional)", "host": "string (optional)", "limit": "number (optional)", "offset": "number (optional)" }Result:
{ "entries": [ { "uuid": "string", "received_at": "number", "project": "string", "host": "string", "screen": "string", "payload_count": "number", "payload_types": ["string"] } ], "count": "number", "limit": "number", "offset": "number" }countis the total number of entries matching the filters (ignoreslimit/offset). -
raymon.get_entries- fetch entries by UUID(s)Parameters:
{ "uuids": ["string"] }Fallback (legacy/single):
{ "uuid": "string" }Result:
{ "entries": [ { "uuid": "string", "received_at": "number", "project": "string", "host": "string", "screen": "string", "session_id": "string (or null)", "payloads": [ { "type": "string", "content": "any", "origin": { "project": "string", "host": "string", "screen": "string (or null)", "session_id": "string (or null)", "function_name": "string (or null)", "file": "string (or null)", "line_number": "number (or null)" } } ] } ] }
This repo includes a skill at skills/raymon/SKILL.md (an AI-facing runbook, not runtime code) that teaches an agent how to:
- generate Ray-style events using the official/community Ray libraries (PHP, JavaScript, Bash, Ruby, Rust, Python, Go, Dart),
- connect to Raymon locally or remotely (with auth) and add it as an MCP server, and
- use
raymon.search→raymon.get_entriesto triage logs and extract high-signal context (uuid, payload types, origin file/line).
The TUI is intentionally "editor-like" (vim-ish):
?opens keybindings/help.qquits (and shuts down the HTTP/MCP server).Spaceopens the pickers/filters modal./searches (fuzzy, message + file; path-like queries are literal),ropens regex search (message + file).:searches inside detail (jq).J/KorPageUp/PageDownscrolls the detail pane.ssnaps the color + type filters to the selected log entry.ppauses/resumes live updates.xarchives the current view (writes a new archive file).n(in the Archives pane) renames the selected archive file (confirm with Enter; Esc cancels; live cannot be renamed).d(in the Archives pane) deletes the selected archive (confirm required; live cannot be deleted).yyanks the selected list entry,Yyanks the detail pane.ztoggles JSON expanded/collapsed (default: expanded),Ztoggles raw JSON.uresets search + filters (screens/types/colors).Ctrl+ypastes the yank register into inputs.Ctrl+lclears the live log list (does not delete stored entries).1toggles color dot,2timestamp,3type label,4file,5message,6uuid (short).oopens the origin in your IDE (seeRAYMON_IDE),eopens the detail in$EDITORvia a temp file.- In the Archives pane,
Enterloads the selected archive; the green‣row returns to live (◼= active archive,◻= inactive).
Raymon sticks to the terminal's ANSI palette (16 colors + text attributes like bold/dim/reverse), so it inherits your terminal theme (light/dark, base16, etc)without implementing full app theming. You can also enforce a set of colors via an RAYMON_TUI_PALETTE environment variable.
Raymon is configured primarily via environment variables:
| Variable | Default | Meaning |
|---|---|---|
RAYMON_ENABLED |
true |
Enable/disable the server. |
RAYMON_HOST |
127.0.0.1 |
Bind address for the HTTP server. |
RAYMON_PORT |
23517 |
Bind port for the HTTP server. |
RAYMON_TUI |
true |
Enable the TUI. |
RAYMON_NO_TUI |
false |
Disable the TUI (takes precedence over RAYMON_TUI). |
RAYMON_IDE |
code |
IDE command used for "open origin" (for VS Code line jumps, use code --goto). |
RAYMON_EDITOR |
VISUAL/EDITOR/vim |
Editor command used for "open in editor". |
RAYMON_JQ |
jq |
jq command used for detail search. |
RAYMON_TUI_PALETTE |
unset | Optional TUI palette override: 18 comma-separated colors fg,bg,black,red,green,yellow,blue,magenta,cyan,white,bright_black,bright_red,bright_green,bright_yellow,bright_blue,bright_magenta,bright_cyan,bright_white as #RRGGBB (also accepts rgb:RRRR/GGGG/BBBB). |
RAYMON_PALETTE |
unset | Alias for RAYMON_TUI_PALETTE. |
RAYMON_MAX_BODY_BYTES |
1048576 |
Max size (bytes) for HTTP POST bodies. |
RAYMON_MAX_QUERY_LEN |
265 |
Max length (bytes) for search/command/picker queries. |
RAYMON_MAX_ENTRIES |
10000 |
Max number of entries kept in memory for the core state (MCP + resync). 0 disables eviction. |
RAYMON_STORAGE_MAX_ENTRIES |
100000 |
Max number of entries kept in data/entries.jsonl. When exceeded, Raymon rewrites the JSONL file keeping the newest entries. 0 disables retention. |
RAYMON_JQ_TIMEOUT_MS |
10000 |
jq timeout in milliseconds. |
RAYMON_ALLOW_REMOTE |
false |
Allow binding to non-loopback addresses. |
RAYMON_ALLOW_INSECURE_REMOTE |
false |
Allow binding to non-loopback addresses without auth (NOT recommended). |
RAYMON_AUTH_TOKEN |
unset | If set, requires Authorization: Bearer <token> or x-raymon-token: <token> on all HTTP requests. |
RAYMON_TOKEN |
unset | Alias for RAYMON_AUTH_TOKEN. |
Raymon also supports a ray.json config file (searched from the current directory upwards). Keys mirror env vars (e.g. host, port, tui, max_entries, storage_max_entries). CLI flags override env and file config.
MIT. See LICENSE.
