agentsclimarketplace

Skill

Skill anschnapp/djinnvim/src/djinnvim/skill

Edit files with the djinnvim CLI — vim-style, pattern-anchored keyhole editing that never reads whole files. Use for any file editing when djinnvim is installed, especially when file/shell tools are restricted or files are large.From its SKILL.md

Install
npx -y skills add anschnapp/djinnvim --skill skill

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 16 days oldThe repository was created 16 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

9.0 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

djinnvim: keyhole editing from the shell

You edit through small viewports, the way a vim user does: search by pattern, look at the echo, edit. Never read a whole file — every command returns the few lines around what it did, and that echo IS your verification (no re-reads needed).

Reach for it when finding or changing something would otherwise mean reading a whole file, when a change repeats across many sites, or when file and shell tools are restricted. Creating a file or rewriting one wholesale is not its job.

Setup — every command, two rules

  1. Pin the sandbox root in the same shell command (shell env does not persist between your calls):

    export DJINNVIM_ROOTS=/abs/path/to/project; djinnvim open src/app.py
    
  2. Pass each editor command as ONE quoted argument. Single-quote it; switch to double quotes only when the text itself contains a single quote:

    djinnvim edit 'at /old_name/ ciw new_name'
    djinnvim substitute ":%s/'eu-west'/'us-east'/"
    
  3. -f PATH names the file to work on, opening it if needed, so edit, substitute, print, matches and write need no separate open call: djinnvim edit -f src/app.py 'at /old/ ciw new'. Without it they use the active buffer. A switch is announced in the echo ([now on ... ]).

State (open buffers, cursor, registers, undo) persists across your shell calls via an auto-spawned per-session daemon — nothing to start or manage. djinnvim status shows it, djinnvim shutdown stops it (unwritten buffers die with it; only write touches disk). Exit codes: 1 = the editor said error: ... (read it — the buffer is untouched), 2 = usage/daemon problem.

The seven verbs

  • djinnvim open PATH — open/switch the active buffer and show its head. Optional, given -f above; use it when you want the file's metadata. Relative paths resolve against the root, not your cwd.
  • djinnvim motion CMD — move the cursor, one motion per call: /pattern (regex, forward), ?pattern (back), n/N (next/prev — n is ALWAYS forward, N ALWAYS backward, unlike vim), :80 (line), gg/G, fx/Fx (char on the cursor line). Search is strictly after the cursor and wraps, reporting match i of n (wrapped).
  • djinnvim matches PATTERN [-C 1] — grep-style listing of every match (capped at 50). Call this before any rename-like edit to see all sites and decoys.
  • djinnvim edit CMD — vim normal-mode edit (details below).
  • djinnvim substitute CMD — ex command (details below).
  • djinnvim print [CMD] — read-only window print (ed/vim :p), the reading tool: 'p' (current line, cursor stays), ':80 p' / ':/def load/ p' (cursor MOVES there, prints it), ':10,25 p' (range; cursor to its last line). Widen with above/below/around
    • tiny (8) / middle (25) / long (50) or a number — ':/def load/ p around middle'; around counts EACH side. Max ~100 lines per call; page by re-addressing a gutter line number.
  • djinnvim write — save the active buffer; reports lines changed. write --preview shows the full pending buffer-vs-disk ±diff without writing — the final review before committing.

edit

Anchored form (preferred): at /pattern/ <cmd> (regex) or at "literal text" <cmd> (matched literally — no escaping, use it when the anchor has parens, dots or other regex punctuation; it cannot contain a double quote). Ordinal and offset work on both: at 2nd /pat/ <cmd>. The anchor lands at the START of the match — anchor on the exact text to change: at /15\)/ ciw 60 changes the 15 in retries(15); at /retries=15/ ciw 60 would change retries. A +N/-N after the closing slash moves the anchor N whole lines (cursor at column 0): at /# Merge logic/-1 O text inserts above the line ABOVE the match — e.g. above a comment banner the match sits inside.

at each /pattern/ <cmd> applies one edit command at EVERY match (transactional: any failure changes nothing; one undo step; returns a ±diff). Text objects make it structural: at each /# obsolete/ dap deletes every marked paragraph whole — no line counting. To go match-by-match instead, reissue the same at /pat/ <cmd>; it anchors on the NEXT match each time.

Commands: ciw/caw TEXT, ci(/{/[/"/' TEXT (di/da delete), dip/dap (paragraph, delete only), dd, cc TEXT, D, C TEXT, x, r<char>, o/O TEXT (line below/above; multi-line OK), A/I TEXT (line end/start), i/a TEXT (before/after the cursor char), cs"' / ds" / ysiw" (surround). Changes need TEXT, deletes take none; everything after the first space is TEXT, verbatim. Newlines in TEXT must be real newline characters (one Enter each, vim-exact) — the two characters backslash-n are not translated, they stay as typed, so source like print("a\nb") inserts correctly. (This is the opposite of substitute, where \n in the replacement does produce a newline.) o/O are line-wise — to insert below a multi-line statement, anchor on its LAST line, not its first. dd deletes the cursor line; address it by pattern (at /pattern/ dd) — edit takes no ex addresses.

Indentation is vim autoindent. The line-wise inserts o, O and cc take the reference line's indent and your TEXT's own leading whitespace stacks on top, so pass only the indent BEYOND the anchor's: o x = 1 after a 4-space line lands at 6 spaces, and cc members = sorted(raw) inside an 8-space block stays at 8. o!/O!/cc! opt out and insert TEXT literally, for a block that is already absolutely indented. (substitute replacements are the other way round — always literal, so capture the indent there with ^( +) and \1.) o/O also echo pre-edit blank-line counts next to where they landed (2 blank line(s) above insertion point, 0 below) — read it to match a file's blank-line convention (e.g. 2 lines between top-level defs) without counting from the viewport.

Blank lines are ordinary edits, one call each: bare o/O with no TEXT inserts exactly one empty line, and at /pattern/ dd on a blank line removes one. Don't reach for substitute (:/pat/s/^/\n/, :N,Nd) to fix spacing — take the counts from the o/O echo and correct with a single anchored call.

Registers: yy / y<i|a><obj> yank, p/P paste. "name prefix composes with the anchor: at /def helper/ "fn dap cuts the function, "fn p pastes it (works across files). Only "name-prefixed deletes write registers; a wrong name on p lists them all.

u undoes the last buffer change (repeat to go further; crosses writes; no redo). Any bad echo → u reverts it whole.

substitute

Ex forms: :%s/old/new/g (file), :s/old/new/ (cursor line), :10,40s/foo/bar/, :/start/,/end/s/x/y/g, :g/pat/d (delete matching lines). Flags g, i. Regex and replacement are Python re syntax (\1 groups): escape parens in the PATTERN (send_request\(x\)) but write them plainly in the replacement. Both range addresses are inclusive; any address takes +N/-N — end on /pat/-1 for "up to but not including". Zero matches is a loud error, never a silent no-op. Numeric addresses go stale after every edit; prefer pattern addresses. To rewrite one line into several without retyping its indentation, capture it: :s/^( +)old_tail/\1new\n\1 second line/ (\n in the replacement inserts a line break). Replacements are always literal here — this capture is only needed in substitute; edit's o/O/cc supply the indent for you.

Line-shaped only: to remove whole blocks at every match use edit 'at each /pat/ dap', not hand-counted ranges. Register ranges for blocks text objects can't grab (function with internal blank lines): :/def helper/,/^def /-1d fn, then paste with at /def target/ "fn P.

Workflow

  1. open the file (echo shows size — you never need more than that).
  2. matches the symbols you'll touch: counts expose decoys (fetch_records vs fetch_records_cached → use \b...\b) and plan scoping before any edit.
  3. Edit smallest-first tool: one-site → anchored edit; many-line regex → substitute; many-site structural → at each.
  4. Read every echo. The diff/viewport is the verification; a wrong echo → edit u immediately. (The cursor line's prefix is exactly as wide as other lines' two-space prefix — indentation shown is exact. Where the caret appears it also states the line's indentation relative to the line above — read that instead of counting leading spaces.)
  5. write --preview for a final buffer-vs-disk diff, then write, and check the reported changed-line count against what you expect.
  6. Write before running anything against the file. Tests, linters, and file reads see only the disk — never unwritten buffer state. (A disk change under an open buffer fails loudly on the next edit/write; re-open to continue.)

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,835. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.