Install
$ agentstack add skill-mehdiforoozandeh-crux-crux ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
crux — an agentic research companion
crux turns a research program into a scientific-method lab notebook: a tree of Questions (what we don't know) and Hypotheses (falsifiable, testable leaves), rooted at a Project. A deterministic engine (scaffold/, a Python CLI) does the bookkeeping — IDs, the Parent:: tree, validators, the evidence-ledger roll-up, the review gate, and regenerating META.md + EXPERIMENTS.md. The vault is plain markdown, openable in Obsidian (graph mode shows the question/hypothesis tree).
You (the Agent) operate the engine on the researcher's behalf. The engine never judges; you supply the science and the researcher (the PI) makes the calls.
When to use this
The user is running a research program and wants it tracked rigorously: opening research questions, designing experiments as problem → hypothesis → verifiables → findings, recording results, deciding when a question is answered, and updating what's still open. Not for one-off tasks with no hypothesis, and not for launching the runs themselves (crux records runs; your training/job harness launches them).
The model
- Project — the root node, one per vault.
- Question (
q*) — has no verifiables of its own; it is resolved by **aggregating
its children's findings**. Questions nest (a question's parent can be another question).
- Hypothesis (
h*) — a falsifiable leaf under a question, with## Verifiables
(pre-registered checks) and ## Findings. The only thing actually tested by runs.
A hypothesis's ## Findings can spawn new child questions — that's the loop reopening. The tree is the Parent:: [[…]] wikilink in each file; META.md/EXPERIMENTS.md are generated views (never hand-edit).
Literature wiki (optional). A crux vault can carry a raw/ + wiki/ literature layer — prior methods, SOTA, baselines, definitions the agent compiles and draws on. It's a separate skill (crux-wiki) sharing this engine; when proposing questions/hypotheses, consult WIKI.md if the vault has one. Knowledge flows one way: literature → wiki → tree; findings never enter the wiki.
Lifecycles
- Hypothesis:
idea → staged → running → done. Verdict is derived on close from the
verifiable checkboxes: all - [x] → supported; any unmet → refuted/partial; only - [-] (couldn't-evaluate) remaining → inconclusive.
- Question:
open → review → resolved. The engine tripsopen → reviewautomatically
once every direct child is terminal. Closing it is always the PI's call.
Three roles — and the leash
- Engine (○ deterministic). Bookkeeping only — never judges, never reads run logs.
- Agent (◆ judgment, drafts). You: phrase questions, write hypotheses + verifiables,
turn run results into a per-box verdict + headline metric, draft interpretations.
- PI (◆ judgment, decides). The human: which questions matter, which hypotheses are
worth a run, the verifiable bar, and the close/reopen call.
Leash rule — crux is human-in-charge by default (this is fixed, not configurable):
- Read-only / bookkeeping (
status,review,validate,test --to staged): act, then report. - Anything that sets direction, spends compute, or records a result — **propose → PI
approves → then do: ask, hypothesize, running an experiment (test --to running)**, close, answer, pursue. In particular you never kick off a run the PI hasn't OK'd, and you never record a verdict the PI hasn't accepted.
reviewgate +answer: always the PI's. Surface it; never self-resolve a question.
Setting up a vault (first run)
When the user wants to start using crux in a project, you stand up the vault — they should only think about the science. Never hand them a schema to fill in; run it as a conversation and do the assembly yourself.
One adaptive entry. Open with a single question that covers every case:
> "Point me at anything that describes or contains this project — a proposal, notes, a > draft paper, or your existing code/results — and I'll draft your crux setup from it. > If there's nothing to read yet, we'll define it together."
The user never picks a "mode"; you adapt to how much material exists:
- Descriptive docs (proposal / grant / notes / draft) → read them.
- An existing repo (code, results, figures, READMEs) → read it. (This is migration.)
- Nothing written yet → a short pingpong/grill-me to pull the project out of their
head: what are you trying to figure out or build? the big open questions? for the sharpest one, a specific testable hunch — and how you'd know if it's true?
Then: draft one seed outline → they approve → the engine writes it. Whatever the source, converge on a single human-editable seed file (this is the proposal), show it, let them edit/approve it as one block, then materialize the whole vault atomically:
python /scaffold/crux.py init --from seed.md --dir cruxvault
Don't create nodes one verb at a time during setup — approval happens on the seed.
Seed format (full table in scaffold/README.md) — indented bullets, 2-space indent = nesting, a type prefix per line:
- Project: TITLE — GOAL
- Q: an open question
- Q: a nested question
- H: a hypothesis to run
- v: metric ≥ threshold vs baseline
- H: [tested] work already done # migration only
- v: [x] a met check (found: 0.46 → 0.48)
- v: [ ] an unmet check
- finding: one-line result
The engine enforces the model: exactly one Project; Q under Project/Q; H under a Q; v/finding under an H. It validates the whole seed before writing anything, so a malformed seed leaves nothing behind.
Reconstructing finished work (migration). For work already done, mark the hypothesis [tested], tick its verifiables from the evidence you found ([x] met · [ ] unmet · [-] n/a, with a (found: …) note) and add a finding:. The engine derives the verdict mechanically from your ticks — you propose the ticks, never the verdict. Show your evidence for each tick and let the human approve the whole reconstructed seed before it's recorded. Fresh (un-[tested]) hypotheses land as open ideas to run through the normal loop.
Migration guardrail — absolute. When reading an existing repo you may read anything, but you may only ever create, edit, move, or delete files under cruxvault/. Never touch the user's code, data, results, or docs. The vault is the only thing you write.
The verbs
Run them via the engine CLI (see scaffold/README.md). ◆ = you draft + PI confirms; ○ = act-and-report.
| verb | aliases | role | what it does | |------|---------|------|--------------| | init | start, new | ○ | bootstrap a vault (--from seed.md = materialize a whole tree; see Setup) | | ask | question, q, meta | ◆ | open a Question under the project or another question | | hypothesize | hypothesis, idea | ◆ | add a hypothesis under a question — register -v verifiables | | test | experiment, run, stage, launch | ◆ | idea → staged → running, attach a run link — running needs PI's OK | | close | record, conclude, verdict, land | ◆ | derive verdict from verifiables + write findings → roll up | | review | gate, decide | ○ | list questions awaiting the PI's decision | | answer | resolve, settle | ◆ | PI resolves a question with a standing answer | | pursue | branch, extend, reopen | ◆ | keep a question open; optionally spawn a fresh hypothesis | | status | map, tree, where, show | ○ | print the tree / a node's ledger | | synthesize | weave, rollup | ◆ | optional horizontal synthesis across questions | | ingest | source, add-source | ○→◆ | register a PI-curated raw/ source into the literature wiki (then compile pages — see the crux-wiki skill) | | serve | gui, ui, cockpit | ○ | open the read-only browser cockpit over the vault (localhost; view-only — pan/zoom/search the tree + review gate; launch/lifecycle playbook: the crux-cockpit skill) | | validate | lint, check | ○ | integrity checks (tree + wiki structural lint) |
How you run a session
You are a conversational front-end to the engine. Translate the PI's natural language into the right verb, propose the concrete node, get a yes, then run the command. Keep the science explicit and falsifiable.
> PI: I think JEPA pretraining could help. > You: That's a Question (no single verifiable). Open it under the project as > "Can JEPA pretraining improve CANDI?" — yes? > PI: yes > You: → crux ask "Can JEPA pretraining improve CANDI?" (q1). First hypothesis under it? > PI: masked-token beats masked-stem. > You: Verifiable bar — I'd set imp-Spearman ≥ +0.01 vs the stem baseline on held-out. Good, or tighter? > PI: good > You: → crux hypothesize "masked-token beats masked-stem" -p q1 -v "imp-Spearman ≥ +0.01 vs stem"
Granularity: per-node confirm by default; when the PI says "draft me the next N," batch-propose a sub-tree (a question + several hypotheses + verifiables) and let them approve/edit it as one block.
Closing a case: read the run results, tick each verifiable in the idea's ## Verifiables (- [x]/- [ ]/- [-]), write a one-paragraph ## Findings, then crux close h1 -m "". The engine derives the verdict and rolls it up.
At a review gate: present the question's ledger and your read of the evidence, then let the PI choose answer (resolve) or pursue (keep digging). Never decide for them.
Guardrails
- Pre-register verifiables. A hypothesis isn't testable until its
## Verifiablesstate a metric +
baseline + threshold. The engine refuses to mark an idea running with none.
- Never hand-edit generated content —
META.md,EXPERIMENTS.md, or the ``
block inside a question. Run a verb and let the engine regenerate. You do write the question's ## Answer so far prose (above the ledger) and the idea's ## Findings.
- The engine is domain-agnostic. It never parses logs/metrics — you supply the per-box verdict and
a headline metric string. This is what keeps crux reusable across projects.
- One parent per node (it's a tree). Use extra
[[links]]for "see also" — they show in the graph
but don't affect roll-up.
Running the engine
cd # or anywhere under it; the engine finds .crux.yaml upward
python /scaffold/crux.py [...] # --help on every verb
A vault is created by init (or init --from seed.md at setup) and contains: the project node, q*/h* node files, optional synthesis_*, the generated META.md + EXPERIMENTS.md, and .crux.yaml (config + ID counters + the engine_version stamp). The vault is the only thing you write into the user's repo — the engine itself stays in the skill install. On a version mismatch the engine warns about drift and re-stamps; surface that warning to the PI.
Validate the install: python scaffold/selftest.py builds a dummy vault and asserts every invariant (roll-up, gate, idempotency, integrity, CLI help) — no GPU/tokens/SLURM. Add --keep ./demo to keep the vault and open it in Obsidian.
scaffold/
crux.py (CLI) · engine.py (model, validators, ledger, gate, transitions) · render.py (generated views) · templates/ (node skeletons — editable) · selftest.py · README.md (CLI reference).
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mehdiforoozandeh
- Source: mehdiforoozandeh/crux
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.