Install
$ agentstack add skill-frane-agented-skill ✓ 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.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
agented (binary: ae)
ae is a stateful editor controlled by command-line verbs. State persists across sessions in a SQLite-backed workspace (.agented/state.db). Every edit is versioned in an undo tree — you can branch, jump to any past state, and never lose work.
Use this tool when
- You need to edit one or more files in a repo across multiple steps and want a durable history.
- You want to leave notes for your future self or other agents (annotations) attached to specific files.
- You want safe multi-file refactors with all-or-nothing semantics (transactions).
Don't use this tool for
- Reading repo overview / architecture (use plain
cat/grep). - Single one-shot edits where you don't care about history (use the platform's built-in editor).
- Anything that isn't text (no binary file support).
How the editor enforces correctness for you
Every read returns a state_token. Pass it to your next write with --expect. If the file changed under you, the write is rejected (exit code 3) and the response includes the new content and the new token. Retry with the new token.
You don't need to "view before write" — the editor will tell you if your assumption is stale. You don't need to "branches before undo" — undo's error includes the branches if there's ambiguity. You don't need to "status before edit" — every operation's response carries the state you'd want to check.
The default is concurrency.require_expect: warn: writes without --expect succeed and emit a stderr warning. For multi-agent setups, set require_expect: writes in .agented/config.json to enforce strict pre-write checks. In either mode, an actual conflict (a stale --expect value) is rejected with exit 3 and the recovery payload — the tree never silently loses work.
Short forms are the default in agent contexts. Long forms exist for documentation and human readers; agent calls should use the shorter form to save tokens. ae s foo.go -r 12:14 -w "..." -x ab12cd34 is the canonical shape, not ae replace foo.go --range 12:14 --with "..." --expect ab12cd34.
For multi-line content, pipe via -i (--from-stdin) or use -f (--text-file). Stdin is auto-detected when piped, so cat patch.txt | ae s foo.go -r 12:14 -i and echo "..." | ae i foo.go -A 0 -i work without quoting tricks.
The first-touch rule
The first time you touch a file in a session, do it through ae open . Not Read, not Edit, not cat. The response is the input to the rest of the session.
ae open returns six things: the file's id, line count, headeditid, contenthash, statetoken, and any active annotations inline. Treat that response as authoritative. Annotations were left by a prior session for you to read. Read them. The statetoken threads forward into your next write. The linecount tells you whether your assumptions about the file's shape match.
ae open is also the file-creation primitive. If the path doesn't exist on disk, ae creates an empty file there and registers it in the workspace. No touch first, no --create flag. The new-file flow is ae open foo.go → ae i foo.go -A 0 -i (insert content from stdin) → ae w foo.go. The same call covers "open this existing file" and "create this new file"; the response shape is identical either way.
Skipping this step costs you. If you Read first, the agent runtime has the bytes, but the editor doesn't know you've seen the file. Subsequent writes through ae will treat your context as a fresh actor and may surface conflicts that wouldn't have happened otherwise. If you read via ae open, the editor knows your starting point, your writes thread cleanly, and the workspace history shows your session as a coherent sequence of edits rather than a stranger's drive-by.
The trained habit ("read before write to be safe") doesn't apply here. ae reports drift via full-content rejection payloads. Read once at session start. Edit forward.
Round-trip economy: don't over-fetch
Most LLMs were trained on Read → Edit → Read → Edit and reach for the same shape with ae. Don't. ae's contract eliminates almost every "look first to be safe" round-trip. Specific anti-patterns:
- Don't
ae viewbeforeae replace/insert/delete. You already know the line range fromae open(orae search). If you're wrong, the write rejects with the current content attached (exit 3); you reconcile and retry. One trip on success, one trip on conflict. View-first burns a trip every time, success or not. - Don't
ae viewbeforeae search. Search returnsline\tcol\ttextper match. That's the answer. View only after if you need surrounding context. - Don't
ae loadbefore reading. Auto-load on drift is on by default. Every write verb stat-s the file and reconciles disk changes itself.ae loadis only for the rare case where you specifically want to capture a disk snapshot as an edit without modifying anything else. - Don't
ae statusjust to refetch a state_token. Every write returns the new token in the result. Thread it forward. The only reason to callae statusis when you explicitly need workspace-level info (open files, dirty flags, current actor). - Don't
ae openmore than once per file per session. The first-touch rule covers the registration. Subsequent reads/writes auto-resolve the same FileInfo. Auto-open also kicks in transparently if you forget —ae search foo.goregisters the file silently when needed.
- Don't pipe ae output through
| head/| tail/| grep. Every read verb has--range,--limit, or--patternto bound output server-side, and--rangeaccepts Python-slice syntax:1:10for first 10,-10:for last 10,5:-5for middle slice (skip first 5 and last 5),:20for first 20,-50:-20for the lines 50-from-end through 20-from-end. Pipe-trimming after the fact wastes the round trip's setup cost. - Don't append
2>&1. ae uses exit codes — 0 success, 3 conflict (with full content payload on stdout), 1/2 for errors. Stderr is ae's own diagnostic noise; merging it into stdout means you parse around it. Just read stdout.
Translation: the canonical loop is open → search/find → replace/insert/delete → repeat. Three calls per logical edit, sometimes two. Not five.
What this editor does that Read/Edit/Write can't
These are the operations that motivate reaching for ae over the built-ins.
- Read once, edit forever. Your local model of the file (built from the
ae openresponse and every subsequent edit) is the source of truth. The editor reports drift via full-content rejection payloads, not via "Read before every Write" rituals. Verb:ae open, then any number of writes without re-reading. - Branching tree, not stack. Walking back is
ae undo; jumping to any prior state isae head -e. Both branches stay addressable; the wrong path is never lost. Verb:ae brto list leaves,ae head -eto jump. - Three-way merge. Reconcile two diverged branches with structured conflict responses. Auto-resolve via
--prefer a|b; resolve specific ranges via--resolve start:end=a|b|"text". Verb:ae merge -l -l. - Atomic batches.
ae applyconsumes JSON-lines on stdin and applies every operation inside one transaction. Replaces N Edit calls with one. Verb:cat ops.jsonl | ae apply. - Atomic move.
ae movecuts a range and inserts it elsewhere — same file or cross-file — in one transaction. No partial-success risk. Verb:ae move --from S:E --to N(same-file) or--to-file --to-line N(cross-file). - Atomic extract.
ae extractcuts a range out of one file and writes it to another, creating the destination if absent and optionally saving both files in one call. The canonical refactor primitive. Verb:ae extract -r S:E --to [--to-line N] [--save]. - Regex replace with capture groups.
ae replace --patterndoes sed-style replacement in a single tool call. Verb:ae s -p '' -w '' [-L ] [-n]. Always single-quote-wwhen using$1/$2backrefs — bash expands$1as the first positional arg (empty in most shells), so-w "$1.foo"silently inserts an empty string. Single quotes (-w '$1.foo') pass$1through to ae, which expands per Go regexp.ExpandString semantics. - Range-based addressing. Every write targets a line range or insertion point, not a string. Edit's "string appears multiple times" failure mode doesn't exist here. Verb: any of
ae s/i/dwith-r S:E. - Annotations as cross-session memory. Per-file notes that persist across processes and across agents. Verb:
ae an a -t "..."to write; reading is automatic onae open. - Transactions with auto-rollback.
ae beginopens a logical group;ae commitfinalizes;ae rollbackreverts. Forgotten transactions auto-rollback after the configured idle window. Verb:ae begin / ae commit / ae rollback. - Cross-agent shared state. A Claude Code session and a Codex session both reading the same
.agented/state.dbsee the same head, branches, annotations, and marks. The workspace is the durable thing; the agent identity is incidental.
Reading verbs (idempotent, cheap)
Bound output server-side, always. Every read verb has --limit/-L, --range/-r, or --pattern/-p to cap the result set before it leaves the daemon. Do not pipe through head/tail/grep to truncate; the bytes are already on the wire by then. ae prints a stderr nudge when stdout is piped without a bound flag (silence: AE_NO_NUDGE=1 env or output.nudge_on_pipe: false in config). | Verb | Short | Args | Output (tab) suffix | Use when | |----------|-------|-------------------------------|---------------------------|---------------------------------------| | view | v | [--range S:E] [--raw] | state_token\t | Inspect a file or range. --range is Python-slice: 1:10 first 10, -10: last 10, 5:-5 middle slice, :20 first 20, 42:50 window. Multi-range in one call: comma-separated, e.g. --range 100:120,140:160 — output concatenates each window with ... between non-contiguous gaps and one trailing state_token. Two view trips collapse into one. --raw emits verbatim bytes (no line-num prefix, no token) for piping to another tool | | search | / | --pattern | state_token\t | Find matches; output line\tcol\ttext| | diff | df | [--from N --to M] | unified diff + token | Inspect what an edit changed | | log | - | [--limit N] | tab-delimited audit rows | See history of operations | | branches | br | ` | id\tts\tactor\tcmd\tishead | Discover alternative leaves | | list | ls | [--all|--closed|--stale] | per-file summary | What files are open | | status | st | [] | workspace or file summary | Get state_token for next write | | mark get | - | | name\tline\tsnapped\t...| Jump back to a known anchor | | annotate list | -| | id\tts\tactor\tcontent | Recall notes from prior sessions | | show | - | [--edit ] [--no-color] | colored, syntax-highlighted unified diff | Display a change to the user. NOT for tool result chains; lean tab format is the default everywhere else | | symbols | sy | [] [--kind ] [--pattern ] | sym\t\t::\t | List symbols (file or workspace). IDE mode only; falls through to lspunavailable when daemon is off | | diag | - | [] [--severity errors\|warnings\|all\|none] [--wait-ms N] | diag\t\t::\t\t | Pull LSP diagnostics on demand — one file, or the whole workspace when path is omitted. --wait-ms` polls past the LSP's async publish lag. IDE mode only |
Writing verbs (use --expect )
| Verb | Short | Args | Conflict response | Use when | |------------|-------|-----------------------------------------------|-------------------|----------------------| | replace | s | --range S:E --with TEXT --expect TOK | exit 3 + content | Change lines | | insert | i | --after N --text TEXT --expect TOK | exit 3 + content | Add lines | | delete | d | --range S:E --expect TOK | exit 3 + content | Remove lines | | save | w | ` | - | Write head to disk | | load | e | | - | Reload from disk | | move | mv | --from S:E --to N (or --to-file P --to-line N) | exit 3 + content | Move a range; cross-file dst auto-created | | extract | - | --range S:E --to [--save]` | - | Refactor a range into a sibling file (atomic) |
Every successful write prints edit_id=\thead_edit_id=\tline_delta=\tline_count=\tstate_token=. Use the new token for the next write. Auto-save and auto-load are on by default. Every write verb (replace/insert/delete/move/extract) and history verb (undo/redo/head) flushes the resulting head to disk in the same call. The result includes saved: true to confirm. Before the write, ae stat-s the file: if (mtime, size) match the stamp from our last save, the call proceeds; if disk was touched externally, ae loads the disk content as a new edit on the tree (so external changes are recoverable via ae undo/ae head) and applies your edit on top. The result includes loaded_from_disk: true and drift_reason when this happens.
Config knobs: concurrency.auto_save = clean | off | force (default clean), concurrency.auto_load_on_drift (default true). Env override: AE_AUTO_SAVE=off, AE_AUTO_LOAD_ON_DRIFT=false.
ae save and ae load still exist for granular control. They are not part of the normal write flow. ae save and ae load still exist for granular control: save flushes head when auto-save was off, load pulls disk content into the workspace as a new edit (useful when an external editor diverged the file). Neither belongs in the normal write flow.
History verbs
ae undo [--count N]— walk head pointer back N edits. Errors with branch info if ambiguous.ae redo— walk forward along the most recently created child.ae head --edit— jump to a specific edit (use afterbranchesshows alternatives).ae branches— list leaf edits (alternatives that exist in the tree).
Worked example: backtracking after a wrong direction
ae view foo.go --range 10:20 # state_token=A1B2
ae replace foo.go --range 12:14 --with "..." --expect A1B2 # state_token=B3C4
ae replace foo.go --range 18:18 --with "..." --expect B3C4 # state_token=C5D6
ae undo foo.go --count 2 # head moves back two; new state_token=A1B2-ish
ae replace foo.go --range 12:14 --with "DIFFERENT" --expect # creates branch B
ae branches foo.go # shows two leaves: original C5D6, and branch B's leaf
ae head foo.go --edit # jump back to original branch's leaf
Marks
Marks are named line anchors that survive edits. The editor recomputes a mark's line on every edit (deletes shift it down, inserts shift it up; if a delete includes the mark's line, it snaps to the start of the deletion and the snapped flag is set).
Worked example: mark a return point before a multi-edit refactor
ae open auth.go # state_token=T1
ae mark auth.go add return_point --line 240
ae replace auth.go --range 100:140 --with "..." --expect T1 # state_token=T2
ae mark auth.go get return_point # line is now 100+(new lines)-(40 deleted)
Annotations — durable cross-session memory
Annotations are how a session leaves context for the next one. They live in the workspace, not in your context window. ae open returns active annotatio
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: frane
- Source: frane/agented
- License: Apache-2.0
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.