Repository navigation
Releases: FishInSalt/ink
Release list
ink-agent 0.4.0
[0.4.0] - 2026-10-11
Added
run_errorextension event. A top-level run that dies to a provider
throw (or a failed overflow-recovery/compaction) now firesrun_error
— exactly once per crashed run, mutually exclusive withrun_end,
never on aborts, never from subagent crashes (a child crash stays a tool
result). The payload is the crashmessage(first line, capped). The
shippedtask-timerextension stops its footer timer and paints
failed after M:SSinstead of ticking forever — previously a crashed
run leftrunning …on screen until the next run started (the
documentedrun_endasymmetry; that contract is unchanged).
Changed
- Clipboard pastes real file paths. Pasting a Finder/Explorer file
copy (Ctrl+V) now inserts the real file paths — read per-platform
(macOSpublic.file-url+NSFilenamesPboardType, Linux
text/uri-listviawl-paste/xclip, Windows FileDropList) and
joined with newlines; a bang draft shell-quotes and space-joins them.
Paste order becomes file paths → image → text, and a path containing
control characters drops the whole paste. A pasted absolute path at
line start now submits to the model instead of being mistaken for a
command (a candidate name containing/is never a command, except
theskill:prefix scheme).
Fixed
- Finder file copies no longer paste their icon. The defect behind
the change above: a Finder file copy used to insert a tmp path
whose bytes were the file's icon image — the path reader now runs
before the image leg, and a garbage-reading platform reader aborts the
paste instead of falling through to the icon image.
ink-agent v0.3.0
[0.3.0] - 2026-10-10
Added
-
Parallel read-only tools.
read,grep,findandlsare
concurrency-safe now: a run of consecutive independent calls issued in
one message runs in parallel behind the same five-slot window astask
calls. The system
prompt's tool catalog gains a derived line telling the model this roster
can run concurrently (roster names in parentheses while the roster has
at most six entries). -
Queued-call visibility. A concurrency-safe call's row shows as soon
as the call is issued —└─ queuedfor read-only tools,└─ queued #N
for task calls — with no timer until a slot admits it (the task row then
continues as└─ pending #N). Queue time never counts toward the call's
duration. -
/sessions prune: sweep orphaned child sessions (subagent transcripts
whose parent session file no longer exists) after an interactive
confirm — header.id matching (never filename), live-lease exemption
via child-lease semantics. -
Chinese README (
README.zh-CN.md): full translation of the root README
with a language switch on both; npm packs it automatically (README* rule),
so it ships with the package and the smoke allowlist admits it. -
GitHub Pages documentation site:
scripts/build-docs-site.mjsbuilds
_site/from the README and the ten docs pages (link rewrites, heading
anchors, sitemap);.github/workflows/pages.ymldeploys it to
https://fishinsalt.github.io/ink/, and the npmhomepagenow points there. -
Full Simplified-Chinese mirror of the docs site:
docs/zh-CN/(ten
pages) builds to/zh/with a per-page language switcher,hreflang
alternates, a translated sitemap, and a translations-may-lag footer
note; the npm package ships the mirror.scripts/check-docs.mjsnow
enforces mirror completeness, en↔zh structural parity (heading level
sequences, byte-identical code fences, link-target multisets), and
anchor mappability;test/docs-site.test.tsexercises the built site. -
Promotion assets:
assets/demo.tape+assets/demo-setup.shrecord the
README demo GIF, andassets/social-preview.html→
assets/social-preview.pngis the repository social preview card.
Changed
-
Concurrent tool scheduling: sliding window. Consecutive
concurrency-safe calls now run behind a sliding window of five slots — a
freed slot immediately admits the next call in issue order — instead of
fixed chunks in which every call waited for the slowest member of its
chunk. Results still settle in call order. -
Abort grace. After an interrupt, tool calls that ignore the abort
signal get a bounded ten-second wait; when it lapses the host synthesizes
the call's result (did not respond to the interrupt within 10s — result abandoned) and the run concludes — Ctrl+C no longer hangs on a
signal-ignoring tool. Only the post-abort wait is bounded, not tool
runtime in general. -
Login docs. README (both languages) leads with
/login— environment
variables second, the npx caveat block retired todocs/cli.md— and the
/loginlisting now states where keys are stored (six API-key rows →
~/.ink/auth.json, stored key beats the environment variable) with OAuth
scoped to the ChatGPT-plan row. -
Legacy
impVersionarm retired. Child-launch records must carry
inkVersion; a record still carrying the legacyimpVersionkey is
rejected outright (cross-version resume was already refused; no
migration is performed). -
Docs site: the wordmark cursor now blinks like a terminal cursor; the
animation is turned off underprefers-reduced-motion: reduce. -
README.zh-CN.md: the site link now points at the Chinese home
(.../ink/zh/), and its two shell blocks carry the English comments
byte-identical to README.md (the code-fence parity rule).
ink-agent v0.2.3
[0.2.3] - 2026-10-06
Added
- Self-documentation. The npm package now ships
docs/(ten
user-facing pages),examples/, andCHANGELOG.md; the default system
prompt carries a docs routing section (absolute install paths plus a
topic table) so the model can look up Ink's own documentation on demand.
ink --version/ink --helpverify an install non-interactively, and
this page is the published changelog. examples/README.md: an index of everything the examples directory
ships (six extensions, thescoutsubagent, theledgerskill).
Changed
- README restructured: getting-started first, the rename-from-imp section
retired (its facts live indocs/cli.md, this changelog, and the design
archive), npm/license/release badges, the full provider family list, and
an agent-friendly install path (verify, one-shot-p, uninstall,
no-lifecycle-scripts declaration, EACCES and trust-gate guidance). package.jsonfiles now publishdocs(with!docs/design),
examples,CHANGELOG.md; the package smoke allowlist admits them.- Design archive moved to
docs/design/— historical design documents
and review records no longer ship in the package. - web-search example README: reference sections compressed to summaries;
full contracts remain in the design document.
ink-agent v0.2.2
[0.2.2] - 2026-10-06
Changed
- Identifier follow-through (rename design Amendment A1, D1/D2). New
child launch records writeinkVersion(legacyimpVersionrecords stay
readable through a normalization arm; cross-version resume refusals are
unchanged), and the child lease machine-id file is.ink-machine-id
(orphaned.imp-machine-idfiles are never read, rewritten or deleted).
No migration is needed or performed. - Codex originator (Amendment A1, D3). Codex (ChatGPT plan) requests now
carryoriginator: "ink"instead of"imp".
ink-agent v0.2.1
[0.2.1] - 2026-10-06
Changed
- Repository renamed to
FishInSalt/ink. The GitHub repository moved from
FishInSalt/imp(old URLs redirect). Package metadata (repository,
homepage,bugs), the README andRELEASING.mdnow point at the new name,
and the README install commands useink-agent@latest. No runtime, CLI, or
extension behaviour changed other than the version string; this is a
metadata-only release, to be published from the reviewed tagged commit.
ink-agent v0.2.0
[0.2.0] - 2026-10-06
Added
-
guardian — the config-driven permission gate (#guardian). The
shipped gate example isexamples/extensions/guardian.mjsnow: rules are
plain text with*wildcards that span anything including newlines (or
regexfor full regular expressions), split into ordereddeny/ask
lists (denywins), with an optionalreasonshown to the human and
optionaltoolscoping —write/editrules match the resolved file
path, bash rules match the command. Anything unmatched runs; there is no
allowaction. A broken config keeps the last good rules (footer hint,
/guardian reload); every deny/ask outcome is audited to
~/.ink/guardian.log. The ask picker red-highlights the span the rule
matched (preview.warnSpans). An ask question left unanswered can now
time out (askTimeoutMs, a new optional host-side deadline on
api.confirm; the shipped template uses 10 minutes): the timeout counts
as declined, is audited astimeout, grants no session memory, and
reaches the model with its own wording, distinct from a manual decline.
While a deadline is set, the picker's question line carries the dim
countdown in parentheses right next to it (e.g.allow this bash command? (9:59), ticking down).
The template was rebuilt around portable, catastrophe-only rules
(whole-home and filesystem-root wipes, disk tools, the.sshfolder,
remote-destroying git / gh operations). Start from
examples/extensions/guardian.template.json; design and review log:
docs/guardian-design.md. -
Tool-name colors via extensions (#tool-name-colors). Tool names in the
TUI call header can carry a color now, through a new load-gated extension
registrationapi.registerToolColor(names, color)— one name, several, or
"*", with any of the 16 standard-16 tokens,"none"(bold-only), or an
absolute token:#rrggbb(truecolor) oransi256:N(0–255). Named
tokens follow the terminal theme; absolute tokens do not, by design.
api.suggestToolColor(names, color)is the author tier: a tool's own
extension suggests its default look, and any user registration outranks
any suggestion (resolution: user exact > user"*"> suggested exact >
suggested"*"). Nothing is colored by default; opt-in themes ship as
extensions (the owner's palette lives in
examples/extensions/tool-colors.mjs, which also doubles as the API
example). Exact names beat the wildcard, the first registration of a key
wins within its tier, hex is stored lowercased, and print/replay/legacy
surfaces are untouched. Colors never affect layout — spans are applied
after the row plan, so visible widths are unchanged; a colors-only theme
counts in the startup banner (— 8 colors), suggestions as their own
count (— 2 tools, 2 suggested colors). Design + three adversarial
review rounds + three amendments:docs/tool-name-colors-design.md.
Changed
-
Node support and CI coverage. The minimum Node version is now 22.19.0,
matching the pinned TUI dependency. CI checks that exact minimum and Node 24;
CI and release gates requirerg/fdinstead of silently skipping search tests. -
Ink rename (
ink-agent@0.2.0). The product is now Ink, an
open-source AI assistant and agent harness for the terminal. The sole
executable isink; there is noimpalias. Active configuration uses
~/.ink, project.ink, andINK_*, without automatic migration or
old-name fallback.ImpSettingsbecomesInkSettingsfor source consumers.
Ordinary session history can be preserved by a separately approved cutover;
historical child sessions remain inspectable but are not resumable. Saved
impVersionfields,.imp-machine-idleases, historical release records,
and actualFishInSalt/impURLs are retained. Publication uses new
INK_NPM_PUBLISH_ENABLED/INK_NPM_PACKAGEgates; dispatch is always
dry-run. Historical publishing capability needs separately approved
retirement, and the first Ink publication needs its own reviewed design. -
Task live view in its own header (#task-inline-live-rows). A running
taskcall's live overview (the└─ pending #N …line with the agent and
the elapsed time, plus itsN tool starts · last: …row) moved out of the
bottom activity region and into the transcript, directly under that call's
own● taskheader. Concurrent subagents therefore read top to bottom in launch order —
header, its own live line, its own result — instead of all headers stacked
above all overview rows. -
Confirm prompt surface, Phase 1 (#confirm-prompt). The guardian-style
approval ask is legible now: the transcript keeps one▪ confirm:record line
(the dim detail note is written only where no picker exists — readline,
no-host and print paths are byte-identical), the picker numbers its rows
(→ 1. Yes) on non-filterable pickers, digits1–9answer directly, and a
dim affordance line sits under the items
((↑/↓ move · enter select · esc cancel · 1-3 quick pick)). Filterable
pickers are untouched: digits stay query characters and no hint row is added.
Design + five adversarial review rounds:docs/confirm-prompt-design.md. -
Confirm prompt surface, Phase 2 (#confirm-prompt). Extensions can now say
it in two structured fields instead of prose:previewrenders the request in
the transcript's own call-header idiom (● bash rm -rf …, the risky fragment
alert-highlighted, never a completion suffix — the call has not run), and
rememberLabelnames what "don't ask again this session" will cover
(Yes, don't ask again this session (this command pattern)). The host
sanitizes both, so an extension can never inject terminal control sequences,
and shows the command exactly once on every surface — in the picker where one
exists, as one plain note line otherwise. Guardian passes both at its bash
gate and a memory label at its write gate, dropping thecommand:prefix
from its detail. Malformed values render nothing; hosts without a picker
ignore the styling and stay byte-stable. -
Confirm prompt surface, Phase 3 (#confirm-prompt). The approval moment now
says who is asking and reads as one piece. The host names the caller —
▪ confirm: guardian — allow this bash command?in the transcript, a faint
· guardianafter the picker title, andblocked by extension guardian:in
the block result — so extensions stop naming themselves (guardian drops its
[guardian]prefixes) without any new API surface: the label is host-derived
and cannot be spoofed. While a picker is open the activity region paints no
tool rows:tool_startprecedes the gate, so those rows used to claim
running Nsalthough nothing was executing, and repeated the gated command a
third time. Every picker now opens one blank row below the transcript, and the
line you decide on (the extension's reason) renders at normal weight instead of
faint — the(↑/↓ move …)affordance and the▪record lines stay faint.
Design + three adversarial review rounds + a mutation-verified implementation
check:docs/confirm-prompt-design.md§15. -
Confirm prompt surface, Phase 4 (#confirm-prompt). The picker title no
longer repeats the caller's name (allow this bash command?— the transcript's
▪ confirm: guardian — …record line already says who asks), and every picker
box now opens with a horizontal rule carrying that name in the middle:
──────────────── guardian ────────────────. The rule is host-drawn from the
same host-held name, so an extension cannot write a different one; the dashes
are faint and the label sits at normal weight. Unattributed pickers get plain
dashes, and the login dialog keeps its own frame. Design + two adversarial
review rounds + a mutation-verified implementation check:
docs/confirm-prompt-design.md§16. -
TUI tool-call duration (#tui-tool-elapsed). Completed tool calls in the
TUI transcript carry a marker — green✓for successes, red✗for
failures — with a dim wall-time suffix when the call took ≥1s
(● bash npm test ✓ 2.3s;1m03sminute form); sub-second calls show
the bare marker (amendments 2-3). Interruptions and replayed history carry
none; legacy and print rendering are unchanged. Design + adversarial
review:docs/tui-tool-elapsed-design.md. -
Loop health monitoring + uncapped children (#loop-health). Subagents no
longer stop at a 60-turn wall (CHILD_MAX_TURNSremoved; owner decisions
2026-09-29: no numeric valve, no prompt injection). A shared,
observation-only loop-health monitor now runs in both the subagent engine
and the main loop and detects three conditions from the existing event
stream: repeated identical tool-call turns, repeated failededit/write
attempts, and the child's
compaction-failure backstop. Child facts surface honestly (task-result
lines + ahealthfield on the TaskRecord); first fires render one dim
REPL note (▪ health: …;INK_HEALTH=0disables; thresholds overridable
viaINK_HEALTH_*env). Nothing is injected into any model context; print
mode gains no health output of its own (a fired signal's task-result text
change shows there only in the tool row's line count). Design + two-track
adversarial review (plus two folded post-merge review rounds):
docs/loop-health-design.md. -
Startup model resolution (#startup-model-resolution). A machine whose
only credential belongs to a non-anthropic family no longer demands a
manual/modelin every new session:- when the builtin startup default is unusable and exactly ONE credential
source exists (the shared-MOONSHOT_API_KEYpair counts once), Ink
resolves that family's curatedswitchHint(zai/glm-5.3, …) — one
▪note, never written to settings, seeded as a non-explicit session
model, print mode resolves silently; /loginauto-selects the fam...
- when the builtin startup default is unusable and exactly ONE credential
imp-agent v0.1.0
Initial public release of imp-agent.
- Interactive TUI (streaming, one-line tool status, queued steering and
follow-up runs) plus print mode (imp -p "...") and piped stdin - Agent loop with tool execution: abort, validation, error feedback,
steering hooks, and a compaction hook - Sessions: append-only JSONL message trees (
~/.imp/sessions/),
--continue/--resume <id>/imp sessions, the/treenavigator,
/fork - Auto-compaction: older turns are summarized into a checkpoint near the
context limit; the full history on disk is preserved - Tools:
bash,read(offset/limit, images),edit,write,grep,
find,ls,task(subagents); the search tools respect .gitignore - Providers: Anthropic, Z.AI (GLM), DeepSeek, Moonshot/Kimi, and OpenAI
(API key or ChatGPT-plan OAuth); credentials from environment variables
or/login - Extensions, skills, named subagents, MCP servers, markdown quick commands,
and custom system prompts (SYSTEM.md)
See the README's Status section for the full current capability list.