scry.nvim

Scry your software.

Your project's feature list.

vim.pack.add { "vim-pro/scry.nvim" } ⧉ needs conjurer.nvim · ripgrep · a lua treesitter parser · nvim 0.10+
The glass one change, from a sentence to a passing check
 
scry://glass   conjurer.nvim
SCRY .scry/map.scry   1:1

Operators, one noun up

you already know the grammar

Vim's bargain is operators × text objects.

d2w, ci", >ap — small orthogonal verbs applied to precisely addressed nouns, repeatable with ., fannable with :g. That grammar is why vim outlived every editor that set out to replace it.

conjurer.nvim ported the grammar to generated edits: ~{motion} is an operator whose effect is rewrite this region toward an intent. Same verbs, same nouns, a new effect.

conjurer ~ap a region in a file
→
scry ~ a capability, across every file it is made of

scry raises the noun from a region in a file to a capability.

Put the cursor on Tailor a checklist to your own situation, press ~, say what you want. The change lands across compile.ts, c/[slug].astro, copy.astro and c/index.astro. Four files, one intent, and you never opened one.

. repeats it on the next feature. :g/^feature.*export/normal ~ fans it across every capability that matches. Nothing new to learn.

Adding a capability is the same verb, because an address exists before the file does: route print names src/pages/print.astro whether or not anything is there yet. Write the feature you want with the members it should have, and cast — absent members are files to create.

The rest of scry keeps that map accurate: the checks say whether what you asked for actually landed, and the kinds say where a member's file lives.

What the glass shows

features are the line you scan · claims are the evidence under them
Done
the product does what you said it does
✓ doneevery piece of evidence under this feature holds
✓ present (file)the route, endpoint or module is on disk
✓ definedthe named definition is there, in the file you said
✓ no matches (rg)the rule holds
✓ passing (ran 4m ago)the behavior holds, as of moments ago
To do
what you've named and not yet made
✗ not yeta feature with nothing holding under it
◐ 2 of 5real progress — some evidence holds
✗ absentone claim: named, not yet real

An absent claim is work to do, written in the same file as everything that already holds. ~ on the feature takes it from here.

Broken
the product stopped doing what you said — with proof
✗ broken (1 of 4)a feature that regressed; outranks everything else
✗ VIOLATEDa rule was broken — with the line that broke it
✗ FAILINGa behavior regressed — with the failure in hand

A broken rule comes with the line that broke it. An intact one only means the pattern didn't match.

Unknown
what nothing has answered — never counted as done
– uncheckedthe glass can't read this part yet
– unrunnobody has asked for proof yet
– stalethe proof predates your latest change
– vacuous?it passes while proving nothing
– unscopeda rule on a feature that locates nothing yet
And one number that isn't about any feature. A map whose features all read ✓ done can still describe a fraction of the product, so the header counts the files no feature claims — 12 of 58 files undescribed — and :ScryUnclaimed lists them. Each one is a decision: give it to the feature that owns it, or name the feature nobody wrote down. Without it, "everything done" could just mean a small map.

One change, end to end

a feature or a fix, without leaving the glass
name it
Describe the change as part of the product.
It surfaces as work to do, in the same file as everything the product already does.
the check comes first
Before any code, you get the test.
Short, readable, and it fails — the feature doesn't exist yet. Reading it is how you check the machine understood you, while it's one page instead of a diff.
let the conjurer type
The code arrives knowing the product — and your rules.
The feature's never-rules ride along, because a rule you want followed is a rule you state. The test is kept from it: a model that can see the test writes to pass the test; one that never saw it, checked after, actually proved something.
and it holds
The check passes, and the map says so.
The feature reads ✓ done, and the rules were re-checked against what actually landed — not taken on trust.

Keys, then commands

zero config works · :h scry is the manual
In the glassDoes
~Cast an intent across the whole feature under the cursor. The verb.
+Fill in what is missing here — again to stop a pass.
<Tab>Show or hide what a feature is made of.
<CR>Open what this line is about — the code, or the evidence.
]d [dNext or previous feature that needs attention.
g?Explain what this buffer is telling you.
CommandDoes
:ScryOpen the glass. Everything is checked the moment you look.
:ScryCheckLook again — fresh verdicts from what's on disk.
:ScryConjureWhat ~ does, as a command.
:ScryExerciseRun the specs. The only command that executes your code.
:ScryTestsFind the tests that exercise your features, from their imports.
:ScryUnclaimedList the files no feature describes, in the quickfix list.
:ScryDiscardDrop the last cast's unsaved changes.
:ScryTidyGather every block of a re-opened feature into one.
:ScryLintFlag feature names that are hard to read — never a verdict, the wording is yours.
defaults
require("scry").setup({
  map_path = ".scry/map.scry",
  resolver = "",       -- "" = treesitter + rg
  test = { cmd = {} },  -- one spec; path appended
  sources = {},         -- what counts as claimable
})

Limits

what the verdicts do and don't assert
A draft is ordinary text. A model may draft the description, but it lands in the buffer — checked like anything you typed, discarded with u, saved only by you.
Done means accounted for, not right. The glass says the product matches its description — not that the description is right.
Every ✓ names its evidence, and never claims more than what was actually seen. The full ladder of what each label does and doesn't assert is a chapter of the manual.
A rule can be dodged in ways a text match can't see. A broken rule is proof; an intact one is only evidence.
The glass reads saved work. What you haven't written yet is invisible, and every answer says when it looked.
Withholding the test is request-level only. The glass never puts a spec's path in a code request; a generator that reads your whole repo will still find it.
The conjurer chooses placement. The glass knows which file the work belongs in, not where in it. Review is yours.
Start with :Scry.
vim.pack.add { "vim-pro/scry.nvim" } ⧉
MIT · requires conjurer.nvim · ripgrep · nvim 0.10+