Research Tree
Research is a graph. Your logbook shouldn't be a flat file.
Research Tree maps scientific and engineering work as a directed acyclic graph
(DAG). Every node is a unit of research — an idea, a claim, an experiment, a
decision — connected by epistemic edges (parent, continuation, supersession).
It replaces linear research logs (logbooks, lab notebooks, markdown dumps)
with a structured, queryable, and auditable knowledge graph.
Stack: Go standard library + cobra (CLI).
Storage: .research/ directory — no database, no server, no daemon.
License: MIT. See LICENSE.
Project status
Research Tree is released as-is.
- It is used in real technical research workflows.
- The CLI and ABI are intended to be integrated by both humans and agents.
- There is no support or maintenance commitment.
- Bug reports and patches may be reviewed opportunistically.
If you need a stable local dependency, vendor it or fork it.
See SUPPORT.md for the maintenance policy.
Why this exists
Linear logs break down the moment research branches. You start with a
hypothesis, run an experiment, pivot, fork, abandon a path, revisit it three
weeks later. A flat text file can't answer:
- Which claims are still provisional? Which have been invalidated?
- What experiment produced this result, on which host, with what command?
- What did this node look like before I changed my mind?
- What depends on this assumption?
Research Tree gives you a DAG, not a timeline. Every node knows its parents,
its children, its continuations, and its replacements. You navigate the
structure of your thinking, not the order you typed it in.
It was born from tracking 19+ sequential log files during LLM prompt
research. When backtracking to a three-week-old experiment took longer than
running it again, the tool became necessary.
Five minutes to your first graph
# 1. Start a research project
rt init
# 2. Create a research node
rt node create --title "Hypothesis: larger context windows improve recall"
# 3. Claim hardware and log an experiment run
rt resource add --id ctx-gpu0 --label "gpu-node-3 gpu0" --kind gpu \
--endpoint gpu03.int.lab --endpoint-kind dns --tags cuda,24gb
rt resource claim 1 ctx-gpu0 --by codex --note "longqa baseline"
rt node logrun 1 \
--resource-id ctx-gpu0 \
--endpoint gpu03.int.lab \
--endpoint-kind dns \
--cmd "python eval.py --ctx 8192 --dataset longqa" \
--outdir /tmp/run-001 \
--seed 42 \
--note "baseline: 8k context, standard attention"
# 4. Validate the claim with evidence
rt node close 1 --outcome success \
--append-body "8k context improved recall by +12% over 4k baseline."
# 5. See what happened
rt feed --hours 24
rt resource history ctx-gpu0
rt tree
rt status
That's the core loop: hypothesis → experiment → evidence → conclusion.
Every step is a node. Every connection is explicit. Nothing is lost.
The mental model
| Concept |
What it means |
| Node |
A unit of research: claim, experiment, decision, or observation |
| Parent |
What prior work does this depend on? (epistemic dependency) |
| Claim |
A falsifiable statement. Starts provisional, ends validated, invalidated, or superseded |
| Run |
A concrete experiment execution: resource, endpoint, command, outdir, seed, validity |
| Resource |
A declared machine/GPU/cpu-slot with stable id, human label, and technical endpoint |
| Lease |
A live occupancy claim from one node to one resource |
| Artifact |
A file or dataset attached to a node (linked or embedded) |
| Supersede |
A claim replaced by a better one — preserves both, with a traceable edge |
| Continue |
A long investigation split across nodes — keeps the thread alive |
A node with continued_by=[7] says "this work isn't done, node 7 picks it
up." A claim with superseded_by=[12] says "this conclusion was valid at the
time, but node 12 has a better one." No information is destroyed.
Key features
- DAG, not a tree. A node can have multiple parents from different
branches. Ideas merge, and the graph reflects that.
- Claims with lifecycle.
provisional → validated | invalidated →
superseded. Every transition is evidence-gated.
- Experiment runs. Structured run records with resource, endpoint, command, outdir,
seed, ETA, cost, and validity.
- Resource coordination. Explicit inventory plus active leases prevent
agents from double-booking the same machine or GPU.
- Revision history and diffs. Every update creates a revision.
rt node diff 42 --rev-a 3 --rev-b 7 shows exactly what changed.
- Chronological feed.
rt feed --hours 24 --status done gives you a time-
sorted activity view without losing the graph structure.
- JSON output. Every command supports
--json for scripting, dashboards,
and agent integration.
- Zero dependencies at rest. Everything is a directory on disk. No
database, no server, no daemon. Back up with
rsync.
- Agent-ready. Both a Go ABI (
pkg/retree) and a structured CLI for
external tooling. Designed to be embedded.
Install
From source:
go install ./cmd/rt
Binary lands in $GOPATH/bin/rt. Add it to your PATH.
To build locally:
make build # -> build/rt
make libretree.so # -> build/libretree.so + build/libretree.h
Research Tree has two primary integration surfaces:
build/rt — standalone CLI for humans and shell automation
build/libretree.so + build/libretree.h — C ABI for embedding into other software
Quick reference
rt init # create .research/ in current dir
rt status # dashboard: active, done, paused, claims, hotspots
rt status --matrix # status × outcome matrix
rt tree # visualize the DAG
rt tree --depth 2 # limit depth
rt tree --color always | grep '★' # inspect golden milestones in the graph
rt feed --by modified --hours 24 # recent activity
rt golden --verbose # list frontier/champion nodes
rt timeline --days 7 # activity grouped by day
rt changes --since 72 # nodes changed in last 72h
# Nodes
rt node create --title "..." --parents 1,2 --tags a,b,c
rt node create --title "..." --milestone-class golden --milestone-kind breakthrough --milestone-reason "..."
rt node show 42
rt node show 42 --agent --json # compact handoff for other agents
rt node edit 42 --title "better title" --add-tags urgent
rt node edit 42 --milestone-class golden --milestone-kind champion --milestone-reason "best lineage artifact"
rt node edit 42 --append-body "new findings"
rt node close 42 --outcome success
rt node close 42 --outcome failure
rt node delete 42 --force
rt node diff 42 --rev-a 3
rt node ancestors 42
rt node descendants 42
# Experiments
rt resource claim 42 gpu-node-0 --by codex
rt node logrun 42 --resource-id gpu-node-0 --endpoint 10.0.0.14 --endpoint-kind ip --cmd "..." --outdir /tmp/run --seed 7
rt node link 42 --commit auto --artifact /tmp/run --host gpu-1
# Resources
rt resource add --id gpu-node-0 --label "GPU Node 0" --kind gpu --endpoint 10.0.0.14 --endpoint-kind ip
rt resource list --free
rt resource report
rt resource history gpu-node-0
# Queries
rt node list --status active
rt node list --tag benchmark
rt node list --claim-status invalidated
rt node list --milestone-class golden
rt node list --milestone-class golden --milestone-kind champion --sort-by modified --order desc
rt node list --body-contains "perplexity"
rt node list --created-after 2026-06-01T00:00:00Z --sort-by created
Golden milestones
Golden milestones are a first-class metadata axis for frontier-significant nodes.
- Canonical storage/query fields:
milestone_class=golden
- optional
milestone_kind=champion|breakthrough|pivot
- required
milestone_reason
- Canonical query:
rt node list --milestone-class golden
- Human shortcut:
Golden milestones are orthogonal to status, outcome, and claim_status.
A node is not golden merely because it is done, success, or validated.
Use golden metadata when the node breaks a ceiling, becomes the lineage champion,
or materially shifts the bottleneck/roadmap.
Research Tree exposes two integration surfaces:
1. Go ABI (pkg/retree)
import "github.com/frudas24/research-tree/pkg/retree"
store, _ := retree.Open(".research")
node, _ := store.CreateNode(retree.Frontmatter{
Title: "Hypothesis: ...",
Parents: []retree.NodeID{1},
Tags: []string{"benchmark", "llm"},
})
store.CloseNode(42, retree.OutcomeSuccess, "conclusion text")
2. CLI with JSON
rt status --json
rt node show 42 --agent --json
rt node list --tag benchmark --json
rt feed --hours 24 --json
Parse the JSON from any language. No library needed.
Design principles
- Epistemic edges, not organizational ones. A parent edge means "this
depends on that claim or result," not "this belongs to that project."
- Evidence before conclusions. Claims must cite runs. Invalidated claims
must cite a refuter node.
- The graph preserves history. Nothing is overwritten. Every revision is
stored. Every superseded claim stays visible.
- Simplicity over features. Three statuses. Three outcomes. Four claim
states. If a concept doesn't earn its place in the graph, it doesn't go in.
- Portable by design.
.research/ is a directory. Move it, back it up,
version it. No migrations, no servers, no lock-in.
Documentation
| File |
Content |
AGENT.md |
Project overview and conventions |
AGENT_INSTRUCTIONS.md |
Operational runbook for agents and contributors |
docs/cli.md |
Full CLI reference |
docs/AGENT_INSTRUCTIONS.md |
Extended agent guide |
docs/abi.md |
Go ABI reference |
docs/architecture.md |
Architecture overview |
docs/data-model.md |
Data model and types |
docs/storage.md |
.research/ persistence design |
docs/development.md |
Development guide |
docs/testing.md |
Testing guide |
docs/binary-codec.md |
Binary codec specification |
docs/e2e-simulator.md |
End-to-end simulator guide |
Release model
This repository is published as a usable infrastructure artifact, not as a managed product.
- License: MIT. Do what you want. Credit is appreciated, not required.
- Maintenance: best-effort only. See
SUPPORT.md.
- ABI / CLI: intended to be integrable, but releases are still opinionated and pragmatic.
- Philosophy: build tools that respect how technical thinking actually works — branching, invalidation, reruns, and evidence-driven course correction.
Contributing
Small, well-scoped fixes are preferred over broad feature expansion.
If you send a patch, include tests where practical and keep the DAG / provenance-first model intact.