github iwe-org/iwe iwe-v0.33.0
v0.33.0

latest releases: iwec-v0.33.0, iwes-v0.33.0
2 hours ago

A stability release: formatting with normalize and in the editor now leaves your documents as you wrote them — escaped characters, link titles, block quotes, code inside lists, frontmatter and djot content all survive repeated runs. Deleting, renaming, extracting and inlining documents no longer leave broken links behind or overwrite other files, and normalize now refuses to run outside an IWE project unless you pass -k.

iwe

Changed

  • normalize without -k fails outside an IWE project instead of rewriting every markdown file under the current directory with the default settings (normalize -k still works anywhere)

Fixed

  • init --okf schema accepts datetimes such as 2026-09-23T00:00:00Z in stale_after, sources[].last_modified and usage_window, as the OKF spec requires (previously only plain dates passed)
  • delete with several matched documents now removes every link to them; previously only the links to the last one were cleaned up when they shared a parent
  • inline of a document into itself fails with an error instead of crashing
  • find, update and delete filters with an empty mapping such as status: {} match only documents whose field is an empty mapping (previously they matched every document)
  • delete no longer treats a fragment-only link such as [Intro](#intro) in a child document as a link to the parent document
  • Links with a percent-encoded # in the path (%23) resolve to the right document
  • normalize no longer turns escaped characters into markup, such as \# or \> in a list item becoming a heading or quote, or \[[x]] becoming a wiki link
  • normalize writes a lone * in a paragraph that also has emphasis as \*, so existing documents may change once on the next run
  • normalize keeps indentation inside a code block that starts a list item
  • normalize keeps two-space line breaks inside block quotes
  • update with $insertAfter on an empty $section inserts after the section instead of nesting the new block inside it
  • normalize of djot documents keeps an escaped < literal
  • update with $delete of every item in a list no longer leaves an extra blank line
  • normalize keeps frontmatter that is not valid YAML as written instead of replacing it with {}, and update --set or --unset on such a document fails instead of dropping the old fields
  • normalize no longer treats a --- block in the middle of a document as frontmatter, which replaced the real frontmatter and dropped the text between the dashes
  • rename and extract keep the original document when the new file cannot be created (previously the original was already deleted)
  • rename to a name that differs only in letter case from another document fails instead of overwriting that document on case-insensitive file systems
  • new --key, rename and extract reject keys with an empty segment or a segment starting with ., such as dir/ or ., which created hidden files that disappeared from the workspace
  • rename and extract fail instead of overwriting a file that exists on disk but is not part of the loaded workspace
  • normalize of djot documents keeps a code block that contains a backtick fence (previously it broke on the second run)
  • normalize of djot documents keeps empty task items and the text of description list terms and table captions (previously dropped)
  • internal claude session commands fail instead of replacing a session record they cannot read, so rejected proposals are not offered again
  • An invalid date or time format in the config is reported as a config error instead of crashing new and create --template, and init --date-format rejects an invalid format
  • squash stops at a link back to a document it is already expanding, so cyclic references finish quickly instead of repeating content
  • update with $replace or $insertAfter on $header acts on each header instead of the whole section when every block under it also matches, so $replace no longer deletes the subsections
  • inline that deletes the inlined document also removes the other links to it from the source document instead of leaving them dangling
  • normalize keeps escaped &amp;-style entities, \<https://...>, \![alt](...) and \[ before a link literal, and keeps non-breaking spaces instead of turning them into plain spaces
  • normalize keeps two adjacent lists separate instead of merging them into one on the second run
  • normalize of djot tables no longer adds a backslash before | inside code spans on every run
  • normalize of djot documents keeps escaped list markers such as \(1) and escaped \::: literal, and keeps raw blocks such as =latex as raw blocks instead of turning them into code blocks
  • squash keeps content in its original order and writes headings deeper than six levels as level six instead of plain text
  • update and delete with --dry-run check the document-level --expect count and fail on a mismatch, like the real run and like block-level expect
  • export with the default --depth 0 follows links to every level, as documented, instead of exporting only the top documents without edges
  • export DOT output escapes backslashes in titles, so a title ending in \ no longer produces an invalid file
  • stats markdown output shows the block and inline reference counts instead of empty lines
  • find --fuzzy ignores letter case like --lexical, so a query with capitals such as Project matches project plan (previously it matched nothing)
  • normalize keeps the title of external links and images instead of dropping it

iwes

Fixed

  • Inline code action on a reference to the same document no longer crashes the server
  • Completion, hover and link text no longer show a document title after the edit that removed it
  • Formatting no longer turns escaped characters into markup, such as \# or \> in a list item becoming a heading or quote, or \[[x]] becoming a wiki link
  • Formatting writes a lone * in a paragraph that also has emphasis as \*, so existing documents may change once on the next format
  • Formatting keeps indentation inside a code block that starts a list item
  • Link action and link completion write # in a document name as %23, so the link points to that document instead of a fragment
  • Formatting keeps two-space line breaks inside block quotes
  • Formatting keeps frontmatter that is not valid YAML as written instead of replacing it with {}
  • Formatting no longer treats a --- block in the middle of a document as frontmatter, which replaced the real frontmatter and dropped the text between the dashes
  • Rename to a name that differs only in letter case from another document is refused instead of overwriting that document on case-insensitive file systems
  • Rename and extract actions refuse keys with an empty segment or a segment starting with ., which created hidden files that disappeared from the workspace
  • Formatting of djot documents keeps a code block that contains a backtick fence
  • Formatting of djot documents keeps empty task items and the text of description list terms and table captions (previously dropped)
  • An invalid date or time format in the config is reported when the server starts instead of crashing a code action later
  • A request that fails inside the server, such as one for an untitled: document, gets an error response instead of leaving the editor waiting forever
  • Inline code actions that delete the inlined document also remove the other links to it from the current document
  • Formatting keeps escaped &amp;-style entities, \<https://...>, \![alt](...) and \[ before a link literal, and keeps non-breaking spaces
  • Formatting keeps two adjacent lists separate instead of merging them into one
  • Formatting of djot tables no longer adds a backslash before | inside code spans on every format
  • Formatting of djot documents keeps escaped list markers and \::: literal, and keeps raw blocks such as =latex as raw blocks
  • A document change with several full-text changes keeps the last one instead of the first
  • Link completion after a [ or [[ glued to the preceding text replaces only from the bracket, so the text before it, such as CJK text without spaces, is kept
  • Rename on a wiki link reads the new name from the workspace root, like wiki links themselves, instead of from the current document's folder, and an empty name is refused instead of renaming the target to the folder name
  • Open, change, save and delete notifications for files outside the workspace or with another extension are ignored instead of adding documents under made-up keys that point to files that do not exist
  • Formatting keeps the title of external links and images instead of dropping it

iwec

Fixed

  • iwe_query delete with several matched documents now removes every link to them; previously only the links to the last one were cleaned up when they shared a parent
  • Inline tool on a reference to the same document returns an error instead of crashing
  • iwe_query filters with an empty mapping such as status: {} match only documents whose field is an empty mapping (previously they matched every document)
  • Tools that report document titles no longer show a title after the document stopped having one
  • iwe_query update with $insertAfter on an empty $section inserts after the section instead of nesting the new block inside it
  • iwe_query update with $delete of every item in a list no longer leaves an extra blank line
  • iwe_query update that changes fields fails on a document whose frontmatter is not valid YAML instead of dropping the old fields
  • Rename and extract tools keep the original document when the new file cannot be created (previously the original was already deleted)
  • Rename tool to a name that differs only in letter case from another document fails instead of overwriting that document on case-insensitive file systems
  • Create, rename and extract tools reject keys with an empty segment or a segment starting with ., such as dir/ or ., which created hidden files that disappeared from the workspace
  • Rename and extract tools fail instead of overwriting a file that exists on disk but is not in the loaded graph
  • An invalid date or time format in the config is reported when the server starts instead of crashing a tool call later
  • Squash tool stops at a link back to a document it is already expanding, so cyclic references finish quickly instead of repeating content
  • iwe_query update with $replace or $insertAfter on $header acts on each header instead of the whole section when every block under it also matches
  • Inline tool that deletes the inlined document also removes the other links to it from the source document
  • Squash tool keeps content in its original order and writes headings deeper than six levels as level six instead of plain text
  • Fuzzy search in iwe_find and iwe_retrieve ignores letter case, so a query with capitals still matches
Library crates (liwe, diwe)

liwe

Added

  • delete_all operation deletes a set of documents and cleans up the links to all of them in one pass
  • Graph::has_unparsed_frontmatter, check_frontmatter_parsed and EvalError::UnparsedFrontmatter report documents whose frontmatter is not a valid YAML mapping
  • Key::has_hidden_or_empty_segment tells whether a key would be written to a hidden file or a path with an empty segment
  • locale::is_valid_date_format checks a strftime format string

Changed

  • List item whose first block is a quote, code block, table or HTML holds that block as one Inline::RawInline with format flattened-block (previously its text was split into Str words)
  • Djot raw blocks other than HTML are held as Node::Raw with the language =format (previously the bare format, which wrote them back as code blocks)

Fixed

  • inline returns InvalidTarget when a document references itself instead of overflowing the stack
  • Filter with an empty mapping such as status: {} matches only documents whose field is an empty mapping (previously it matched every document)
  • is_document_url is false for a fragment-only link such as #intro, so a standalone paragraph with such a link is no longer read as a block reference to the parent directory
  • Percent-encoded # in a link path (%23) is part of the document key instead of starting a fragment, and Key::link_url writes it back encoded
  • Document title is cleared when an update removes the title, instead of keeping the old one
  • Markdown writer keeps escaped characters literal in more places: block markers inside quotes and list items, * and _ inside emphasis, [ and ] in link text and image alt text, [[ and HTML tags split by escapes, ~~~ fences, a trailing # in headings, and markers at the start of a line after a preserved line break
  • List item whose first block is a quote, code block, table or HTML keeps that block's text exactly, including indentation inside code (previously whitespace was collapsed)
  • Markdown writer keeps two-space line breaks inside block quotes
  • Block update $insertAfter on a $section with no content inserts after the section instead of nesting the new block inside it, also when the $section is inside $and or $or
  • Djot writer escapes < so text such as \<http://example.com> is not turned into a link
  • Markdown writer closes math with $ and $$ delimiters (previously only the opening one was written)
  • Sequential document ids skip ids that are already taken instead of reusing them
  • Block update $delete of every item in a list removes the list without leaving an extra blank line
  • Frontmatter that is not a valid YAML mapping is kept as written instead of being replaced with an empty mapping
  • Markdown reader treats only a --- block at the very start of a document as frontmatter, so a later --- block stays in the body instead of replacing the frontmatter
  • rename returns AlreadyExists when the new key differs only in letter case from another document, which would be the same file on case-insensitive file systems
  • rename and extract return InvalidTarget for a key with an empty segment or a segment starting with ., which would be written to a hidden file the loader never reads
  • Djot writer makes a code block fence longer than any backtick run inside the code, so code that contains a fence is kept
  • Djot reader keeps empty task items, and keeps the text of description list terms and table captions as paragraphs instead of dropping it
  • squash does not expand a reference to a document that is already being expanded, so a cycle no longer repeats content or takes exponential time
  • Block update on $header targets only the header itself even when every block under it also matches (previously the whole section was replaced or used as the anchor)
  • inline that deletes the target also removes the other links to it from the source document
  • Markdown writer escapes & before an entity name, < before an autolink, ! before a link, and [ whose ]( would form a link, and keeps non-breaking spaces
  • Markdown and djot writers give a list that directly follows another list of the same kind the other marker (* or )), so the two lists no longer merge on the next read
  • Djot writer no longer escapes | inside code spans in table cells, which added a backslash on every write
  • Djot writer keeps escapes for list markers such as (1), a. and (iv) and for ::: at the start of a paragraph, so the text does not turn into a list or a div
  • squash keeps an expanded reference before the later subsections of its section instead of moving it to the end, and inlines a reference without headers where it stood
  • Markdown and djot writers write headings deeper than six levels as level six instead of a line of seven or more # that reads back as a paragraph
  • Markdown writer keeps the title of external links and images, such as [text](https://example.com "Title"), instead of dropping it

Don't miss a new iwe release

NewReleases is sending notifications on new releases.