Releases: fvonbredow/NEOS-releases
Release list
NEOS 0.99.1
Fixed
- SSH tunnels never delivered the answer. A local (-L) or dynamic (-D) forward carried
your request to the target and then went quiet: the reply sat unread in the SSH channel,
so a browser through the tunnel hung, and so did anything else. The two halves of a
forward only read while the other half can take the bytes, and the SSH half asks to read
the instant its channel opens — at which point the local half is still being attached and
therefore counts as unable to take anything. That first read was parked, and nothing ever
woke it, because waking it required the local connection's writability to change and it
had been writable all along. Remote (-R) forwards set their two halves up in the opposite
order, which is why only those worked. Joining a half to the pair now wakes a waiting
partner. Forwarding has been unusable since it was introduced in 0.1.107 (July); it was
never noticed because only the SOCKS parser and the interface had been tested, never
traffic. All three kinds now run end to end against an SSH server in the test suite. - SSH channels are opened on the connection's own thread. The terminal, the file browser
and SCP fetched the SSH handler out of its event loop and opened their channel from
outside it, which the library forbids — its channel bookkeeping takes no lock, and the
loop touches the same list when authentication completes. No failure could be produced in
34 connections or under Thread Sanitizer; the ordering NIO happens to impose covers almost
every case, leaving a narrow window at the moment authentication finishes. Correct by
construction now rather than by luck.
Changed
- Builds with Xcode 27 and Swift 6.4 against the macOS 27 SDK, and the 48 warnings that
came with the new compiler are gone rather than silenced: the SSH tunnel's handler is
bound to its event loop, the SOCKS negotiation states the thread it runs on, the MCP
server's receive path says it is not on the main actor, and the FTP transfer's running
byte count travels as a parameter instead of living in a variable its callbacks shared.
Each was safe in practice and unprovable to the compiler; a later Swift would have
refused them. - SNMPv3 key derivation now uses CryptoKit's
Insecure.MD5andInsecure.SHA1instead of
CommonCrypto's deprecated MD5. Same bytes — the RFC 3414 test vectors now guard them,
which nothing did before.
Added
- Terminal tabs can be dragged into a different order on macOS 27. On macOS 15 and 26
the tab bar behaves exactly as before. Dropping a tab onto itself leaves it where it is,
rather than flinging it to the end — which is what the straightforward version did until
a test said so. - Tests for the parts that had none and are hard to reach: SSH channel opening (terminal,
SFTP subsystem, SCP exec), all three kinds of port forward with real traffic, an FTP
upload and download round trip, and the SNMPv3 vectors. They run against an SSH server
and an FTP client inside the test process — no Keychain, no~/.ssh, no system settings,
nothing left behind.
The “Source code (zip / tar.gz)” archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.99.0
Added
- A local command line, and a real one. NEOS has been able to open a shell on the Mac
since early on — ⌘T did it — but it was labelled "New Terminal Tab", which reads like a
container for a connection rather than a prompt on your own machine, so it went unnoticed.
It is now called what it is, and it does what Terminal does:ping,dig,curl,
git,ansibleand vendor tools are reachable without leaving the window. - Any installed shell. "New Shell With…" lists what this Mac actually has — zsh, bash,
fish, Nushell and PowerShell (pwsh), including Homebrew's versions alongside Apple's.
PowerShell is started the way PowerShell expects (-Login), not with the POSIX
convention, which would have silently skipped its profile. - ⇧⌘T opens another shell in the same directory as the active one. The directory is
read from the shell process itself, so it works without any shell integration — macOS's
own hook for this only fires for Apple's Terminal. - Drag a file from the Finder into a terminal to insert its path, quoted for the shell
that tab is running. - ⌘+ / ⌘− / ⌘0 for terminal text size.
- The shell is called NEOS Shell and lives under "Sessions", at the top of the
sidebar, where the things you connect to are. Hovering it reveals a menu of every
installed shell. It is not a saved session — it has no host, user or credentials — but
it is the one you always have, so it belongs in the list rather than behind a keystroke. - A shell is ready as soon as NEOS starts, unless something else claimed the window
first — a file handed over by the Finder keeps the foreground. The home dashboard stays
one click away on the house button. - A colour scheme can apply to the whole app or to the terminal alone. Settings →
Profiles → "Apply scheme to". Homebrew's green on black is right at a prompt and barely
readable as a sidebar; "Terminal only" keeps the interface on NEOS Dark or Light while
the terminal wears whatever you like. - Settings → Terminal now holds the default shell, the login-shell switch and the start
directory.
Fixed
- A local shell had a crippled PATH. It was started as a plain shell, not a login
shell, so~/.zprofileand/etc/pathsnever ran. A GUI application inherits launchd's
environment —/usr/bin:/bin:/usr/sbin:/sbinand nothing else — which meant Homebrew,
and thereforeansible,terraform,kubectl,pwshandbrewitself, were missing
from a shell that looked entirely normal, while the same commands worked in Terminal.
Shells now start as login shells, as Terminal does. - A local shell opened in
/, the working directory a GUI application inherits. It now
opens in the home directory, or wherever configured. $SHELLinside a tab now names the shell that tab is running, instead of always naming
zsh;TERM_PROGRAMidentifies NEOS.- Leaving a shell with
exitnow says so in the tab instead of leaving it silent, and the
child process is reaped rather than left as a zombie. - An exported draw.io topology was titled
topo.title— a text key that was never
defined, shipped verbatim as the diagram's page name. A new check sweeps all 1,800-odd
text lookups in the application against the string table, so a missing key fails the
build instead of reaching a user. - Settings → Keys said "No keys configured" to everyone, as a hard-coded line, above an
"Import Key…" and a "Generate Key…" button that did nothing. It now lists the key pairs
in~/.sshwith algorithm, fingerprint and whether a passphrase protects them — read
only, since sessions pick their key by path and NEOS never copies key files. - The + and − above the colour schemes did nothing. Schemes are built in and there was
nowhere to store a copy. The pair is gone; a check now fails the build on any button
whose action is empty. - ⇧⌘T would have taken an SSH session's remote directory and started a local shell in
it — harmless when the path does not exist here, and quietly wrong when it does. - Opening the settings window replaced your colour scheme. Under the new "terminal
only" scope the scheme list seeded its selection from the interface's fallback rather
than from your choice, and wrote it straight back — so merely looking at the preferences
turned Homebrew into NEOS Light. The "Default" badge had moved to the wrong row for the
same reason. Found by opening the window twice during testing, not by a test. - The shell chooser's arrow in the sidebar was drawn in the system's grey rather than the
scheme's colour: a borderless menu paints its own label and ignores the style set inside
it.
The “Source code (zip / tar.gz)” archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.98.0
Added
- The Security Check now audits what a device is configured to do, not only what
version it runs. It could already say "this firmware has known CVEs" and "this port is
a bad idea" — both true of a class of device, neither looking at the box in front of
you. Fourteen checks now read the loaded configuration: management exposed on
internet-facing interfaces, cleartext management, SNMP communities left at their
defaults, administrators without trusted hosts, super admins on one password,
certificates expiring, SSL-VPN sharing port 443 or running on a factory certificate,
SAML servers missing the identifiers that make a login possible, no time
synchronisation, a cluster that does not fail back.
Every finding names what to do about it, with the vendor command where there is one.
And every check that could not run says so with its reason — a report that lists three
problems is otherwise indistinguishable from one that only managed three checks. The
result exports as Markdown or JSON for a ticket, masked when anonymisation mode is on. - The audit is about networks, not about FortiOS. The checks read a vendor-neutral
snapshot, so the same code answers for a UniFi controller and for a FortiGate — which
runs SSIDs and managed switches as well as firewall policies, and is therefore just as
capable of a flat network as anything else. That brings five findings that only exist
because there is more than one vendor: wireless that is open or on WEP, a guest SSID
without its own VLAN, a network with no tagged segments at all, mixed firmware across a
fleet of access points and switches, and port forwards onto services with a bad history.
Adding another vendor is one adapter, not a second set of checks. - The Wi-Fi Survey evaluates the scan instead of only drawing it. Eight sections all
presented and none judged, so the arithmetic was left to whoever was reading the channel
chart. Now: how many audible networks share a channel (per band, ignoring anything too
weak to matter in practice), your own radios sitting off 1/6/11 in 2.4 GHz, your own
access points talking over each other, 80 MHz channels in a crowded band, weak security
on your own SSIDs, uneven fast roaming read from the beacons the scanner already
captures, and access points disagreeing about the country. Plus a proposed 2.4 GHz
channel per radio — deliberately 2.4 GHz only, because there the answer is arithmetic
and a confident wrong answer about 5 or 6 GHz costs more than none.
Other people's networks are never judged. A neighbour on your channel is a fact to
plan around; a neighbour on WEP is none of your business, and reporting it teaches you
to skim. - API Console — saved HTTP requests, under "Edit". Method, URL, headers, body, send,
read the answer formatted. The reason it is in NEOS rather than left to Postman is
narrow and real: a request can inherit a configured device's credentials, so no
token is ever copied into a second tool where it then sits in plain text, and rotating
a credential takes effect here too. It inherits the device's certificate policy along
with its identity, which is what makes it work against appliances at all.
Reads go straight out; anything that can change something is marked in the list, in
the editor, and confirmed once with the method and target in the question — a method
NEOS does not recognise counts as changing. Variables use the same{{name}}spelling
as the Command Library. Assertions (status, status class, text, JSON path, maximum
duration) turn a saved request into a check you can re-run, and a failure shows what was
actually there. An OpenAPI or Swagger document imports as a collection, which closes the
dead end where API Discovery could find an endpoint and offer nothing to do with it. - Topology: layers and segments, as a choice next to the existing views. Layers make
height mean role — edge, core, access, endpoints — with the tier decided by hop distance
from the gateway rather than by a hostname; a device with no known link lands in access
rather than the core, because drawing it as the core would be a claim with no evidence.
Segments make position mean subnet, which is what shows you the thing in the wrong
place. Neither answer replaces the other, which is why it is a choice. - Export the map as a draw.io drawing. The
.drawiofile carries the nodes at the
positions you are looking at, real network shapes from draw.io's own library, and the
links — turning a snapshot into a document you can keep editing and hand to a customer.
Reading draw.io stencils is deliberately not offered: it would buy icons NEOS draws
better itself, and the common sets carry vendor licences. - Findings over MCP, and resources. Two new tools return the reasoning NEOS has
already done — a device's configuration audit and the Wi-Fi evaluation — rather than a
third way to dump raw material, and both spell out which checks did not run. A third,
fortigate_raw_read, reads any FortiOS REST path (GET only,/api/v2/only) for the
questions the typed tools do not cover. NEOS also answersresources/listand
resources/readnow, offering the network map, the audit across every device and the
component list; before this a client that asked at startup got "Method not found" and
concluded there were none.
Fixed
- Certificate expiry never worked.
valid_toarrives from FortiOS as an integer
epoch, and NEOS decoded it as a string — so every certificate came back without a date
and the check reported "not checked" on a device whose dates were sitting right there.
Found by asking the device instead of the documentation, which is what the new raw-read
tool is for. - Segments were read from the wrong place. A FortiGate's own VLANs are interfaces, not
FortiSwitch VLANs, so the segmentation check reported "not loaded" on a device with
three of them. - Findings are grouped rather than repeated. A FortiGate with 52 interfaces produced
fourteen near-identical "interface offers management access" rows plus five more for
HTTP — nineteen findings for two decisions, burying the three that mattered.
The "Source code (zip / tar.gz)" archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.97.2
Added
- NEOS can be the application that opens a file. Double-click a
.txt,.conf,
.licor similar, pick NEOS under “Open With”, or drop the file on the app icon — it
arrives as a document in the editor. If NEOS is not running it launches first and the
file follows: files handed over during launch are queued until the app is ready rather
than dropped, which is the failure that looks like “it opened but my file isn't there”.
Until now none of this was possible, because the app never declared what it can open —
so macOS did not list NEOS under “Open With” at all and “Change All…” had nothing to
point at. It is offered for text in the broad sense: plain text, source code and
scripts, JSON, XML, YAML, CSV, logs, Markdown,.conf,.cfg,.ini, and.pem/
.crt. For everything else the existing default is left alone — NEOS registers as an
alternative, and stays an alternative until you choose it in Finder → Get Info → Open
with → Change All. The two exceptions are its own file types,.licand MikroTik's
.rsc, where it is the default from the start because nothing else claims them.
The “Source code (zip / tar.gz)” archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.97.1
Fixed
- Opening an SFTP/SCP browser crashed NEOS. Reported by @crayt90 (issue #9). The
window died the moment it was drawn, before any connection was attempted — so it looked
like an SCP fault and was not one. Two correct modifiers in the wrong order: the mode
banners are placed beside the view in a stack rather than around it, so applying the
environment first and the banners second left the banners outside the environment they
read, and a missing@Environmentvalue in SwiftUI is a hard trap, not a fallback.
The same line was in three more windows — the detached terminal, the security check and
every detached device window — all of them since the banners arrived in 0.96.0. There
is now one call that does both in the right order, so there is no order left to get
wrong, and a test that rejects the old spelling anywhere in the app. - Ports were shown with a thousands separator. In a German locale port 2222 read
2.222, in the sidebar, both session lists, the tunnel picker and every device
dashboard header — and in the iperf3 command NEOS offers you to copy, where-p 5.201
simply does not work when pasted.Text("… \(port)")is not string interpolation:
the literal is aLocalizedStringKey, and an interpolated integer gets formatted for
the locale. Twelve places, all corrected, with a guard against the next one.
The “Source code (zip / tar.gz)” archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.97.0
Added
- MCP in both directions — NEOS can now use other people's servers, not just be used
by them. Until now an assistant could connect to NEOS and read the network through
its tools; NEOS itself could not connect to anything. It can now: a local program
speaking over its own pipes (how most MCP servers ship), or a server over HTTP. A
ticket system, a documentation store, a vendor's own MCP server — so what NEOS knows
about a network can meet what the rest of the toolchain knows.
Their tools become available to the local investigating agent, prefixed with the
server's name —tickets__search, notsearch, because all tools share one namespace
and a foreignpingwould otherwise shadow the native one and route a call to the
wrong side. Each connected server can be browsed and any of its tools tried by hand,
for the same reason the agent has a "try it" button: nobody should be asked to rely on
a connection whose answers they have never seen.
A foreign tool counts as changing something until its server says in so many words
that it is read-only. Missing information is not permission — a server that does not
describe itself contributes nothing to the agent. Foreign tools are not passed onward
to assistants connected to NEOS: such an assistant speaks MCP too and can reach those
servers directly, so putting NEOS in between would only hide whose access was used.
What a foreign server returns is data from elsewhere, never an instruction; NEOS tells
the model so explicitly and shows a server's own instructions as its quotation rather
than blending them into NEOS's words. HTTP tokens live in the Keychain. Connecting is a
click, and at launch only the servers you marked — starting a foreign program because
an app opened is not something to do unasked. - Command Library — one command to many devices, and an answer instead of twelve
blocks of text. Under "Edit". Pick a command, pick the devices, run: NEOS sends it
over the same SSH path the broadcast uses and then evaluates what comes back rather
than printing it side by side. Identical answers collapse into one group, the largest
group is the majority, and every other group is shown as its difference from that
majority — so the result reads "same on six, different on one, no answer from one",
and the one that differs shows exactly the line that differs.
Real output is never byte-identical, which is what makes the naive version useless:
get system statuscarries a serial number and an uptime, so comparing raw text gives
twelve groups of one. The per-device fields are therefore blanked for the comparison —
blanked, not dropped, so a device missing the line entirely still lands elsewhere — and
the difference shown to you is the real one, not the four differences that are
guaranteed on any two devices. A device that answered nothing gets "No answer", not a
diff proving it is missing every line.
The library ships filled: twelve read-only FortiOS commands you actually run, one of
them with a{{placeholder}}so the mechanism is visible without reading the help. The
shipped entries cannot be edited — duplicate one to adapt it — which keeps later
improvements to them available to everyone. Your own entries are stored separately.
Anything that begins withset,config,delete,executeand the like is flagged
as changing the device, warned about visibly, and confirmed a second time before it
goes: this feature sends one command to every selected device at once, and aset
broadcast to twelve firewalls by accident is the failure it is built to prevent.
In anonymisation mode the device names and the output are masked —get system statusprints the device's own hostname, which otherwise stood unmasked in the middle
of a presentation.
Changed
- The example network is now a fleet. It had three devices and no SSH among them, so
the two areas that are about many devices at once — the broadcast and the new command
library — showed "0 of 0 devices" in demo mode and could not be demonstrated at all.
Six branch firewalls were added, one of them a firmware version behind and one that
does not answer, with fabricated command output that carries per-device serial numbers
and uptimes just like the real thing. The grouping shown is the real evaluation of
invented answers, not a picture of one.
The “Source code (zip / tar.gz)” archives below are attached automatically by GitHub to every release. They are archives of this download hub and contain only its README — NEOS itself is closed source.
NEOS 0.96.0
Added
- An anonymisation mode, for showing your screen to someone who should not see the
network behind it. Tools → "Anonymise what is shown" (⇧⌘A) replaces device and
session names, addresses, MAC addresses and SSIDs everywhere NEOS draws them — for
a customer presentation, a screenshot, a bug report, a training session. It is
display only: stored data and everything sent to a device are untouched, and
switching back brings the real values straight up again. Within a session the
masking is consistent, so the same MAC yields the same pseudonym everywhere and the
topology map, the heatmap and the device list still agree with one another. The
mapping is reissued on each activation and never written to disk — one that survived
restarts would be a pseudonym database, which is the thing the mode exists to avoid.
Addresses land in the ranges reserved for documentation (RFC 5737, RFC 3849) but
keep their subnet grouping and host octet, so the.1still reads as the gateway;
MAC addresses keep the vendor prefix and lose the half that identifies the device.
Addresses buried in prose are caught too, as are CSV and JSON exports, the clipboard
and the window titles — a title reaches further than its window, into the Window menu
and Mission Control. While the mode is on, an amber bar sits at the top of every
window with a switch-off button in it: believing it is on while it is off is the
mistake that costs something. What is not masked is named in the help — the
connections themselves, terminal contents, and names that come out of a device's own
configuration such as VPN tunnels and policies. - An example network, for the help pages and a first look. Help → "Show example
network" fills topology, the Wi-Fi survey, sessions and the device list with invented
data: addresses from the documentation ranges, locally administered MAC addresses,
made-up names. Nothing in it ever touched a network. Your own sessions and devices
are overlaid rather than replaced — nothing is written, and switching off brings your
own set back unchanged. Unlike anonymisation it does not survive a restart: an app
that quietly showed invented data at launch would be a hard deception to notice.
Both modes can be on at once.
Fixed
- Detached windows now say which display mode they are in. The indicator existed
only in the main window, so anyone presenting a detached device dashboard had no sign
of the mode and no way to switch it off from there. All four kinds of window — device
dashboards, the detached terminal, the SFTP browser and the security centre — now
carry the bar, and all four take their environment from one shared place. That
removes the shape behind three separate crashes (Settings in 0.93.0, SFTP in 0.95.x,
the device windows in 0.95.11), where a window that listed its own environment values
by hand missed one and trapped on open.
NEOS 0.95.11
Fixed
- Opening a device window no longer quits NEOS. Clicking a FortiGate in the SDN
Suite ended the app on the spot:EXC_BREAKPOINTin the environment lookup. A
window opened throughNSHostingControllerstarts with an empty environment —
@Observablevalues from the main scene do not cross a scene boundary — and the
device overview reads the app coordinator, while only theme and language were
handed over. A missing@Environmentvalue in SwiftUI is not a fallback, it is a
trap. Latent for a long time, because the embedded view worked and only the
detached window died. Affected all three device types. - Devices no longer vanish from the SDN Suite. Swift applies no default values
when decoding: a non-Optional property with a default still throwskeyNotFound.
fortiAuthMethodis declared exactly that way, so every device stored before it
existed had become unreadable, the list read as empty — and the next save
overwrote the data for good. Only theidis required now and everything else
falls back; the list decodes entry by entry, so one damaged record cannot cost the
others; and when nothing can be read at all, the original bytes are kept under
their own key instead of being overwritten. A device list is work, not a cache. - Devices belonging to a newer version survive being opened in this one. Both
version lines share a single stored device list, and this one does not know the
FortiManager and FortiAnalyzer entries a later version writes — so it read an
empty list, and adding one device overwrote the rest. Records with an unfamiliar
vendor are now set aside while loading and written back untouched while saving.
They are deliberately not displayed: a FortiManager shown as a FortiGate and
re-saved as one is worse than a device that is temporarily missing. - A missing CPU reading no longer looks like nought percent. A failed fetch was
presented as a confident "0 %", indistinguishable from a genuinely idle firewall.
The display branches on whether a reading exists rather than on the number: with
none it shows "—", and a true zero names the most recent peak ("idle · last peak
5 %"), so you can see the figure is alive. - The save button on the device sheet stays reachable. The sheet had a width but
no height, so with the SSH section expanded it grew taller than the screen and the
footer slid off the bottom. A sheet cannot be moved, which left no way to save.
NEOS 0.95.10
NEOS 0.95.10 — die Glocke läutete bei jedem Enter
Reported by @crayt90.
Fixed
- The bell no longer rings on every Enter. BEL means two different things
depending on where it appears: a bell on its own, and the terminator of a window
title sequence. The parser decided before looking at the context, so the
ESC ] 0 ; user@host: ~ BELthat a standard Debian/Ubuntu prompt sends before
every prompt was taken for a bell. - A few characters after a window title no longer disappear. The same mistake
meant the title sequence never ended, so the parser kept swallowing what followed
until the next escape sequence pulled it out — usually the colour codes of the
prompt, which is why the loss stayed small enough to go unnoticed. Both halves
are the same one-line cause; the bell was simply the audible one.
The cause dates back to the first import, not to the recent bell work — but until
0.95.6 nothing listened for the bell, so it never showed. A feature nobody listens
to hides the bugs behind it.
NEOS — Network Engineer Operating Suite. A network workbench for macOS.
Installation: download the DMG, then drag NEOS into your Applications folder.
The build is signed and notarised by Apple.
NEOS 0.95.8
NEOS 0.95.8 — Ergebnis eines QA-Durchlaufs
Fixed
- Session logging finally does what the settings say. The switch was never
read — logging could only be started by hand from the inspector — the log
directory shown in the settings was ignored because the path was hardcoded
elsewhere, and the "Change…" button beside it had an empty body. Enabling the
switch now starts recording for every kind of session (SSH, local shell and
serial), into the directory you choose. - Ten German texts no longer appear in the English interface. They sat where
the earlier translation pass could not see them: one branch of a ternary while
the other branch was translated, and four cases of a switch whose other eighteen
were. Affected the topology map, the network tools, the FortiGate dashboard, the
packet analyzer's recommendations and one CVE error message.
Changed
- Two settings that promised something NEOS cannot do are gone. "Word
Separators" configured a double-click word selection that does not exist in the
terminal, and "Enable Compression" could never work: the SSH library negotiates
no compression at all. Better absent than misleading.
Installation: DMG laden, NEOS in den Programme-Ordner ziehen. Der Build ist
signiert und von Apple notarisiert.