Quick start
Spoke turns rows like who → did what → to what into an interactive graph.
Each row becomes an arrow (an edge) between two things (nodes).
- Open Samples (top right) and choose Insider risk.
- Click the jsmith node. Its whole chain lights up and the Details panel lists everything jsmith did, in time order.
- Click a name in the Details panel to jump to it. Click empty space to clear.
Click a sidebar heading to collapse or expand that section; a collapsed section shows a one-line summary of its settings (a purple dot means the filter or time window is hiding something). Map columns tucks itself away after you build a graph. The ⟨ button at the top left (or [) hides the whole sidebar for more graph space.
Everything runs in your browser. Files you load are never uploaded anywhere.
1. Load data
- CSV or Excel (.xlsx, .xlsm, .xlsb, .xls, .ods). The first row must be column headers.
- Workbooks with several sheets: pick one from the Worksheet list, or choose
All matching sheets to combine every sheet with the same columns. A
sheet column records where each row came from; summary or README tabs are skipped.
- Samples (top right): Process tree (a hierarchy), Insider risk (a web of activity),
Endpoint activity (a noisy Excel export to practise filtering on) and
EDR export (shows why combined keys matter).
2. Map columns
- Source and Target: the two things each row connects, e.g.
user → file or parent process → child process. Required.
- Relationship: the label on the arrow, e.g.
downloaded, spawned.
- Source type / Target type: optional; colours nodes by type (user, host, file…) and fills the legend.
- Time column: when each row happened. Drives the time bar and the order of the activity list.
- The app guesses all of these from your column names. Check them, then click Build graph.
Combining columns into one node
If a name alone isn't unique (there are many cmd.exe processes), use
+ Combine with another column to add more columns to the key. For example,
ProcessName + ProcessId + Hostname gives cmd.exe (3400, WS-01).
The preview underneath shows what IDs will look like.
- Map source and target the same way, so a process is the same node whether it's a parent or a child.
- Name/ID pairs like
ProcessName/ProcessId are suggested automatically, plus the host column when there are several machines, because process IDs repeat across machines.
- If your data has a
ProcessGuid, mapping on that alone is the most reliable key.
3. Filter
Type a regular expression to cut a large graph down. It applies as you type.
- Match against: Node names, the Relationship label, or Any column of the row (e.g. severity, user, command line).
- Hide removes matches. Use it to strip out routine noise.
- Show only keeps just the matches. Include then adds context around them:
Matches only, +1 to +3 hops (neighbours, their neighbours…), or the entire connected group.
The actual matches are outlined in purple.
- Matching ignores upper/lower case unless Case sensitive is ticked. The line under the filter shows how much is still visible.
Try it on the Endpoint activity sample
svchost|chrome|teams|onedrive|msmpeng | Node names · Hide | 224 nodes down to a few dozen, and the attack chain on WS-07 stands out |
high|critical | Any column · Show only · Matches only | Just the serious events |
rundll32 | Node names · Show only · +1 hop | One process and everything it touched |
Regex cheat sheet
cmd | contains “cmd” anywhere |
cmd|powershell | either one |
^cmd | starts with “cmd” |
\.dll$ | ends with “.dll” (\. means a literal dot) |
\(3400\) | literal brackets, e.g. a process ID in a combined key |
WS-0[1-3] | WS-01, WS-02 or WS-03 |
\d+\.\d+\.\d+\.\d+ | looks like an IPv4 address |
^(?!.*corp).*$ | does not contain “corp” |
An invalid pattern turns the box red and says why. Nothing is filtered until it's fixed.
Time window
When the data has a time column, a time bar appears under the graph. Its histogram shows how many events happened when, so bursts of activity stand out.
- Drag across the histogram to pick a window, or click a bar to zoom to that slice of time.
- Fine-tune with the slider handles or type exact start / end times. Reset shows everything again.
- Relationships outside the window disappear, along with anything left with no connections. Nodes stay where they are, so you can scrub back and forth and watch activity come and go.
- Fade instead of hide keeps out-of-window items as faint ghosts for context.
- Keep undated keeps rows with no time (like an org-chart link) visible whatever the window.
- UTC / Local switches how every time in the app is shown and typed. Times in your file that have no time zone are read as your computer's local time.
- The time window and the regex filter work together: something is shown only if it passes both. Exports of CSV/JSON include only what's in the window.
Recognised formats: ISO 8601 (2026-10-18T22:14:00Z), 2026-10-18 22:14, 10/18/2026 22:14, Unix epoch seconds or milliseconds, and Excel dates. Rows whose time can't be read are counted as “unreadable” in the time bar and treated as undated.
Try it on the Insider risk sample
Click the tall bar on the evening of 18 Oct: the window narrows to that hour and the graph shows just the late-night downloads and USB copies.
4. View and navigate
- Pan by dragging empty space; zoom with the scroll wheel or trackpad; drag nodes to tidy up.
- Click a node to highlight its full chain (everything upstream and downstream); everything else fades. Click an edge to highlight just that relationship.
- Layout: Process Tree for hierarchies (parent → child); Relationship Web for everything else.
- Search outlines matching nodes in orange without hiding anything.
- Edge labels: On hover / click keeps big graphs readable by showing labels only around the node you're looking at.
- Fit to screen (or F) brings everything back into view.
- Theme: the Auto / Light / Dark switch is at the top right.
Details panel
- Node: its type, how many connections it has, and an Activity list of every relationship, oldest first. Each row shows the time, severity and any extra columns (IP, command line, notes…).
- Edge: the full original row from your file.
- Click a blue name to jump to that node, or an activity row to select that relationship.
- A
severity, risk or priority column is colour-coded. Close the panel with × for more room; it reopens when you click something.
5. Export
- PNG / JPG images at 1×, 2× or 4× resolution (4× is good for print), or SVG, which stays sharp at any size in slides and reports.
- Whole graph or just the current view.
- CSV: the original rows behind what's visible. It loads back into this app, which is handy for sharing a trimmed dataset.
- JSON: visible nodes and edges with their full records and the filter used.
- Send to CyberChef opens the visible rows (CSV, or JSON if selected) in CyberChef in a new tab, ready for decoding, extracting or reformatting.
- Exports match the screen: filtered-out items are left out, and any highlight is kept. Click empty space first for a plain picture.
Share links and loading from a URL
Like CyberChef, Spoke can carry data in the link itself, after the #. Browsers never send that part of a link to any server, so the data still stays on the computers that open it.
- Copy share link (in 5. Export) packs the loaded file, compressed, together with your column mapping, layout, filter and time window. Whoever opens the link sees the same view.
- Anyone with the link can see the data, and links are saved in browser history. Treat a link like the file itself.
- If you're using the single-file version, your link points to the file on your computer. Recipients open their own copy of Spoke and paste the link into Or paste a share link under 1. Load data. Links from a hosted copy open directly.
- Browsers limit links to about 2 MB, and chat or email tools may cut long ones short. For big datasets, share the file (or a filtered CSV export) instead.
Linking from other tools and scripts
Put base64 of a CSV or Excel file after #input=, for example spoke.html#input=cGFyZW50LGNoaWxk…. Standard or URL-safe base64 both work, with or without padding, and the data may be gzip-compressed. Optional settings go before it:
src, tgt | Source/target column, or a JSON list to combine columns: ["ProcessName","ProcessId"] |
rel, stype, ttype, time | Relationship, source type, target type and time columns |
layout | tree or web |
re, scope, mode, depth, case | Filter: pattern; node/edge/any; hide/show; 0–3 or all; 1 for case-sensitive |
from, to, undated, fade | Time window (ISO times); undated=0 hides undated rows; fade=1 |
name, sheet | Display name; worksheet (or __all__) |
Values must be URL-encoded. Anything left out is guessed as if you'd opened the file normally.
Keyboard shortcuts
| ? | Open this help |
| / | Jump to the filter box (opens it if collapsed) |
| [ | Hide / show the sidebar |
| F | Fit the graph to the screen |
| Esc | Clear the selection (or close this help) |