Skip to content

Monghoul v1.9.2

Latest

Choose a tag to compare

@Kontsedal Kontsedal released this 25 Aug 08:14

Monghoul 1.9.2

Improved

  • A detached window respects the interface zoom — a tab detached while the interface was at 125% opened a window at 100%, with no zoom keyboard shortcut and no scroll gesture to change it. Zoom is one app-wide level now: a detached window opens at the level in effect, can change it, and the other open windows follow.

  • A collection can be opened from the keyboard — Space on the focused row in the connection tree opens it in a query tab, the same action a double click performs. Enter still expands and collapses. The sidebar's most-used action needed a mouse until now.

  • Monghoul gives back the disk it stopped using — the app database never returned deleted pages to the filesystem and its write-ahead log never shrank once it had grown, so a long-running install could reach hundreds of megabytes while holding a couple of megabytes of actual data. Startup now caps the log and compacts the database when it is overwhelmingly empty space. An ordinary database is left untouched.

  • The theme you get on a fresh install is now yours to keep — Monghoul picked light or dark from the system on first launch and then never wrote the choice down, so it re-derived it at every start: changing the operating system's appearance later silently moved the app with it, even though the theme picker offers concrete themes and no "System" entry. The first launch records the theme it picked, and it stays until you change it in the app.

Performance

  • Switching to a query tab opens its connection ahead of the first query — the connection was established by the query itself, so on a remote server the first run of the day paid a TLS handshake and authentication on top of its own time. That now happens in the background when you switch to the tab. It only runs on a deliberate switch, so reopening a saved workspace still connects to nothing until you ask it to, and a connection waiting on its session password is left alone rather than prompting because you clicked a tab.

  • A large JSON import no longer has to fit in memory — importing JSON read the entire file into a string and then into a document array, which cost roughly ten times the file size in memory and made the app refuse anything over 500 MB. It is streamed now: memory stays flat at about 120 MB whether the file is 150 MB, 300 MB or 600 MB, where before a 300 MB dump peaked at 3.1 GB and a 600 MB one was refused outright. JSON arrays, NDJSON, concatenated JSON and gzipped dumps all stream; progress counts bytes of the file instead of documents, and a document that will not parse is now skipped and counted rather than failing the whole import. Excel imports are unchanged and still read the whole workbook.

  • A large CSV import no longer has to fit in memory — importing a CSV read the entire file into memory first, so the largest file Monghoul could import was bounded by RAM rather than by patience. It is streamed now: memory stays flat at about 140 MB whether the file is 230 MB or 464 MB, where before it tracked the file size. Excel imports are unchanged and still read the whole workbook. The progress bar counts bytes of the file instead of documents, since a streaming read cannot know the row total without reading the file twice.

Interface

  • Search matches are one colour everywhere, and it is no longer the selection colour — the table and tree result views drew a match in the same colour as a selected row, so a match inside a selection was nearly invisible; the sidebar, command palette and logs modal drew it in the warning colour instead. All five now use a dedicated highlight colour that custom themes can set. A theme that does not set it keeps the colour it had.

Accessibility

  • The tab strip's "all tabs" button has a name — the button that lists every open tab was an icon with no label, so a screen reader announced only "button" and the one route to a tab scrolled out of view was unidentifiable. It is named now, and reports whether its menu is open.

Fixed

Safety

  • A crash during startup now leaves its reason in the log file — the log was opened in the background, so a failure that happened before that finished wrote nothing at all and then printed an unrelated internal error on top of the real one. Exactly the report that is hardest to diagnose lost the one line that explained it.

  • Write protection is enforced at the database driver, not just read off the query text — the check was a scan for .deleteMany( and similar spellings in the code, so a destructive call the scan could not see ran without a word: bracket notation, a method reached through an alias or a variable, or a raw db.command({ drop: … }). Those are refused when they run now, naming the operation, the target and the connection. A raw db.command on a protected target is limited to commands known to be reads.

  • The aggregation builder's stage preview honours write protection on the server — it asked before previewing a pipeline ending in $out or $merge, but the answer never left the app: the sidecar ran whatever it was sent, so a preview on a protected connection wrote whether or not you agreed. Cancelling now stops the write on both sides, and confirming is what allows it.

  • A protected collection can no longer be emptied through a previewPreview and Explain ran their code with no write-protection check at all.

  • Exporting a query's results honours write protection — the export re-runs the query's code, and it was the one path that skipped the check, on the assumption that the code had already run once as a query. It had not necessarily: exporting does not require the query to have been run, so a query written but never executed — which is what the AI assistant's review mode produces — would execute on Export. Reads export exactly as before.

Interaction

  • The keyboard position in the connection tree survives clicking a chevron — expanding a row with the mouse cleared the keyboard cursor even though focus was still inside the tree, so the next arrow key jumped back to the first row. Arrow keys resume where you were.

  • Middle-clicking a tab no longer leaves the autoscroll cursor behind — closing a tab with the wheel button started the browser's scroll-drag cursor at the same time, because the suppression ran a moment too late. The tab closes and nothing else happens.

Export

  • A CSV export opens correctly in Excel — exported files carried no encoding marker, so Excel decoded them in the system codepage and any accented or non-Latin value opened as mojibake: Львів became ÐÑвÑв. The data on disk was always right, which made it look like an export bug when it was a reading one. CSV exports now begin with a UTF-8 byte-order mark, and the collection-export dialog has a switch to leave it out for tools that read it as part of the first column name. A gzipped CSV carries it inside the archive, and Monghoul's own import reads it back unchanged.

Import

  • A large integer no longer arrives off by one — importing Extended JSON, a $numberLong above 9,007,199,254,740,992 was read as an ordinary JavaScript number and stored rounded: an id or a counter written as 9007199254740993 landed as 9007199254740992, with nothing to indicate it. Those values now arrive exactly, and a field written as $numberLong is stored as a 64-bit integer rather than widened to a float. Ordinary integers in ordinary JSON are unchanged.

  • A huge JSON file in a dump directory no longer takes the app down without a word — importing a whole directory read each JSON file into memory with no size limit, so one oversized file killed the sidecar mid-import. Single-collection imports already refused a file over 500 MB; both paths share that limit now, a compressed .gz is measured by what it inflates to rather than its size on disk, and the message says what to do instead of recommending NDJSON, which was read the same way and hit the same wall.

  • A JSON or CSV file that starts with a byte-order mark now imports — files written by Notepad, by PowerShell's Out-File / Set-Content -Encoding utf8, or exported from Excel as "CSV UTF-8" begin with an invisible marker character. A JSON import refused the file outright with a parse error naming a character nothing displays. A CSV import was quieter and worse: it succeeded, reported every row imported, and named the first column with the marker still attached — a field that looks exactly like id on screen and that no query for id will ever match. The marker is stripped on read now, in both formats and in a gzipped file.

  • A failed import no longer empties the collection it was going to fill — under the drop-then-insert strategy the collection was cleared before the file was opened, so a missing, corrupt or oversized file left you with neither the old data nor the new. The file is read first now, in every format.

Query and Results

  • A chart that plots the same field twice draws two series instead of one broken one — picking one field in two Y-axis rows collapsed both into a single series carrying twice as many points as there were labels, which also silently disabled "sort by value" and left a dual-axis assignment pointing at a series that no longer existed. The two are told apart now, the second labelled field (2).

  • Editing a value inside a nested array now updates the row you edited — a cell in an array of arrays saved to the database and reported "Saved", but the table and tree went on showing the old value until the next run of the query. The two halves of the save disagreed about how to read the path: the update named the right field, the on-screen refresh looked for a field whose name contained the brackets and found nothing.

  • Searching a result no longer redraws the rows it is drawing attention to — with a search term active, a matched cell rendered a different value than the same cell renders unsearched: an object collapsed from its inline preview to Object{3}, a date lost its display format and its relative suffix for a raw timestamp, a string lost its quotes, and both lost their type colours. Matches are now marked inside the normal rendering, in the table and the tree, which also means a match inside an object preview is highlighted for the first time.

Cluster Monitor

  • A Cluster Monitor tab explains itself after a downgrade instead of looking broken — when a Pro subscription ends with a monitor tab still open, the tab showed "Failed to fetch server status" with a Retry button that could never succeed, and kept retrying in the background. It now says the feature is Pro, offers to upgrade, and stops polling.

Themes

  • A theme file saved by a text editor now imports — importing a theme whose file begins with a byte-order mark failed with "Failed to import: Unexpected token", pointing at a character that renders as nothing. Notepad and PowerShell both write one by default, so a theme exported from Monghoul and then edited by hand could stop importing.

AI (MCP)

  • An AI-initiated query can no longer reach the network — query code runs with fetch available, so a document whose contents were written to be read as instructions could turn "read this collection" into "read this collection and post it somewhere". A query the assistant runs itself no longer has fetch at all; calling it says so and points at review mode. Queries you run yourself are unchanged.

  • Review mode is on when you first enable the MCP server — it started off, so the act of switching MCP on handed an assistant the ability to run query code against every saved connection with nobody reading it first. A new installation now asks you to approve each query until you turn that off. An installation that already has a setting keeps it.

  • An AI naming a connection that does not exist is told so in review mode too — the check ran only on the path that executes immediately, so in review mode a query was filed against a missing connection and reported as awaiting your approval.

  • The MCP token no longer has to travel in the URL — every generated client config put it in ?token=, which is a bearer secret in shell history, in a config file that gets committed, and in any proxy log on the way. The setup snippets now send it as an Authorization header for every client that supports one; the URL Monghoul shows you carries no token at all. Codex has no flag for a request header, so its snippet still uses the URL and says so. An existing config keeps working — the query form is still accepted.

  • The MCP port no longer answers to any website you happen to have open — it replied to every request with a wildcard cross-origin header, so a page that guessed the port could read its responses; and because that header is not a gate, such a page could issue a write and simply not read the reply. Requests from a browser are now accepted only from Monghoul itself and from localhost, and the token is compared in constant time.

  • An assistant is told when it names a connection that does not existpin_collection and save_favorite_query passed the unknown id through to the database and surfaced its raw FOREIGN KEY constraint failed; unpin_collection deleted nothing and reported "Collection unpinned"; create_query_tab built a tab bound to the missing connection and left it in the workspace for you to close. The five sidebar tools — the three navigate_to_* and expand_in_sidebar / collapse_in_sidebar — answered "Navigated to collection" without looking anything up at all. All nine now name the connection they could not find, which is what every other tool already did.