Skip to content

Repository files navigation

NMT PuTTY

Customization and extension boundaries are documented in docs/CUSTOMIZATION.md. The release evidence required for feature-complete status is defined in docs/ACCEPTANCE.md.

NmTputty includes persistent nested terminal docking: drag a session tab to any pane edge to create a split, resize local branches with their splitters, and restore the same per-tab layout on restart. See Docked terminal layouts for the interaction model, persistence format, migration behavior, and isolated-desktop verification checklist.

The full definition of feature parity, current evidence, release blockers, and interactive acceptance cases is tracked in MTPuTTY parity and acceptance.

NMT PuTTY is an independent, open-source Windows session manager inspired by MTPuTTY. It hosts normal PuTTY processes inside one modern tabbed workspace, so existing PuTTY sessions, protocols, keys, Pageant integration, and terminal configuration continue to work.

This repository is a greenfield implementation. It does not contain MTPuTTY source code, assets, or binaries, and it does not bundle PuTTY.

Current state

The first runnable vertical slice is complete:

  • SSH, Telnet, Rlogin, Raw, and Serial profile models
  • folders, accessible server search with direct-result and ancestor-folder highlighting, drag/drop organization plus a keyboard-accessible path-aware Move dialog, recursive duplication, checked-server multi-connect, and recursive Connect on a selected folder
  • schema-validated server/folder copy and paste through a private clipboard format
  • quick connect and bounded connection-source refresh from the current user's PuTTY and KiTTY registry sessions; stable source provenance prevents same-named records from different sources from colliding
  • real cross-process PuTTY and KiTTY window hosting in a resizable, chromeless tab
  • persistent tabbed, grid, side-by-side, and stacked terminal layouts with resizable pane proportions
  • accessible Reset Layout that converts skewed odd/even dock trees into equal-area, minimum-depth panes without replacing terminal processes
  • bounded per-profile automatic reconnect for unexpected exits, with persisted attempt and backoff settings, cancelled by close, detach, manual reconnect, or shutdown; independent normal and unexpected close/keep-tab preferences apply when retry is not active
  • isolated, bounded startup/discovery/hosting failures with backend-native window-class validation and responsive themed Retry/Close panes
  • theme-aware tab state indicators for connecting, connected, reconnecting, disconnected, and failed sessions, with the same semantic state and status exposed to accessibility tools
  • optional bounded synchronization of tab names with validated PuTTY/KiTTY window titles
  • restored window/sidebar placement and user-editable foreground-scoped hotkeys; compact always-visible actions open the editor and reliably return keyboard focus across process/thread boundaries to the selected terminal
  • a bounded, searchable 35-command palette available from Tools, the always-visible status bar, and configurable Ctrl+Shift+P; unavailable actions remain discoverable with an explanation, while Run delegates to the same existing shell action as menus and toolbar controls
  • planner-driven quit confirmation that cancels pending reconnects, ends owned terminals, and detaches externally owned PuTTY/KiTTY windows
  • close, reconnect, detach, duplicate/rename tab, unique names, and optional session restore that preserves stable tab identity, renamed titles, ordering, active selection, and layout; the compact accessible rename action persists immediately and rolls back its live title if the workspace save fails
  • an accessible open-session tab list whose visible order and active selection can be inspected independently of the native terminal panes
  • a themed, accessible Sessions navigator for direct switching when many tabs are open, synchronized with tab selection and controlled by a persisted appearance preference
  • drag-reorderable tabs plus accessible Move Left/Right commands whose restored stable-ID order and active selection are persisted through one save/rollback transaction
  • optional tab close buttons whose visibility persists through restart; button and middle-click close share the same confirmation and lifecycle transaction
  • discovery and explicit attachment of standalone PuTTY/KiTTY windows as temporary tabs through an always-visible accessible Attach action
  • PuTTY's own system menu from a dedicated session-header control, the Session menu, or a tab right-click
  • a direct, accessible Change terminal settings action that resolves PuTTY or KiTTY's enabled native command at runtime, without a hard-coded command ID
  • standalone PuTTY Configuration from Tools, with explicit invalid paths kept visible for repair instead of silently launching another installation
  • per-profile startup scripts and a generation-bound multi-session automation pipeline with bounded UTF-8 file load/save, cancellation, and per-target results
  • an always-visible accessible Send Script action plus a special-key selector covering Enter, Escape, Tab, Backspace, navigation/editing keys, and F1–F12
  • per-tab Send Script target choices that save immediately by stable session identity, survive a full application restart, and safely default to checked when an older workspace is upgraded
  • genuinely concurrent automation delivery workers that leave the WPF caller responsive and isolate a slow or timed-out terminal from healthy targets
  • deterministic reconnect/docking stress, a real 64-cycle invisible HWND soak, and a separate-desktop exact-package run that rendered four nested PuTTY layouts and replaced owned PuTTY processes 32 times with stable post-warm-up handles and no surviving process or native child
  • _SLEEP:milliseconds and _KEY:name script directives, including navigation, Insert, and F1–F12 keys
  • exact CR, LF, and CRLF script termination: every source terminator submits one line, blank lines remain blank submissions, and an unterminated final line never synthesizes Enter
  • direct capability-gated sending of navigation, editing, and function keys without opening the script dialog
  • optional one-shot or Windows Credential Manager-backed credential delivery from the selected session, plus explicit per-profile automatic login with a bounded readiness delay; secrets never enter workspace JSON
  • bounded checked-server credential replacement with target preview and rollback reporting
  • bounded, atomic, human-readable JSON storage with portable mode
  • serialized saves, a previous-workspace backup, and explicit corrupt-file quarantine/recovery
  • versioned server-tree import/export with hierarchy and ID validation that always disarms automatic login on external transfer
  • bounded MTPuTTY mtputty.xml/exported-tree migration with a merge preview; credential, command-line, script, layout, and application-setting fields are deliberately ignored
  • System, Light, Dark, and validated user-defined color palettes, selectable from the always-visible, accessible Appearance dialog and reflected by exclusive checks in the View menu
  • explicit retain/forget choices for stored credentials when deleting profiles

The executable baseline has been exercised with live local Raw sessions: NMT PuTTY launched and embedded owned PuTTY 0.84 HWNDs, resized them with the custom shell, followed remote titles, delivered targeted text and special keys, and cleanly closed only owned processes. A disposable credential run also proved Windows Credential Manager store/send/forget and ordered automatic login after restart without writing its synthetic canary to workspace or command-line metadata. A two-profile run also proved checked-server credential preview, independent vault targets, and credential-first automatic delivery to both connections. Deterministic immediate-exit, no-window, and wrong-window fixtures also proved that failed sessions clean up without disturbing a connected PuTTY sibling. The bounded loopback fixture and captured evidence are documented in native development acceptance. That authorized interactive development run does not replace the dedicated-desktop release matrix. The current worktree passes the containerized full-solution Release build with zero warnings, formatting and source-safety checks, all 28 Core scenario groups, all 30 named Core checks, the Windows adapter suite, and the complete Windows package/hash gate. Acceptance H06/B08/E02/D05/E06/F16/F01/F02/F03/F12/C07/C08/E03/H07/C03/C05 additionally passes against the exact 0.1.0-retry-exhaustion-final package on a separate Windows desktop. That 34-connection run includes selected/broadcast terminal automation, explicit external detach/reattach, owned/external tab-close decisions, mixed-ownership quit cancellation/confirmation, bounded reconnect exhaustion, accessible manual recovery, and restart.

The exact 0.1.0-command-palette-final package separately passes G16 on an isolated Windows desktop. With the menu, toolbar, sidebar, Sessions navigator, and start page hidden, its status action exposed all 32 commands, explained a disabled Close Session command, routed Appearance and Add Server into their existing dialogs, returned a bounded no-match state, changed no profile or session data, launched no PuTTY process, and exited without residue.

The exact 0.1.0-toolbar-actions-final package passes G17. Its themed editor removed a preserved unavailable command, added About, reordered three actions, and saved server.add, help.about, tools.appearance. The rebuilt toolbar routed Appearance through the existing dialog and restored the same order in a fresh process. The run used no global input, focus activation, or desktop switch and left no NMT or PuTTY process.

The exact 0.1.0-connection-sources-final-v2 package passes G18. The current 35-command catalog exposed the independently composed PuTTY and KiTTY sources by display text and stable IDs. Schema 6 persisted no data during the discovery-only run, and the application exited without starting PuTTY or leaving a process. Disposable-registry adapter checks separately prove secret-free read, legacy adoption, refresh, rollback, and source isolation.

The exact 0.1.0-credential-providers-final package supplies G19 evidence while repeating H06/B01. Credential storage is composed through a stable, bounded provider catalog instead of a shell-owned Windows implementation. Core and adapter checks select a custom provider and prove every credential UI string follows its metadata; the packaged Windows default rendered its composed name during profile deletion. The same isolated run completed four native layouts, 12 reconnects, create/edit/delete, and three restarts without global input, focus activation, desktop switching, or a surviving process.

The 0.1.0-automation-providers-final source and package add the G20 source-level automation extension boundary. Stable directive descriptors and a bounded catalog compose _SLEEP, _KEY, or custom directives into the same text/key/delay plan used by the executor. Providers cannot introduce a second execution model: output is capped at 16 existing typed steps, provider failures are redacted, compiled text is capped at 1 MiB, and the executor independently revalidates the completed plan. The exact 0.1.0-script-files-final package then repeated selected-only and broadcast _SLEEP/_KEY delivery through real PuTTY receivers; both transcripts matched expected byte counts and hashes, all controlled processes and disposable sessions were removed, and no global input was used.

The 0.1.0-terminal-adapters-final-v2 package adds the G21 source-level terminal engine boundary. MainWindow now receives one bounded adapter catalog, and profile preview, launch, reconnect, capability routing, the catalog-driven Settings executable list, and external-window attachment all resolve through the selected registration. PuTTY and KiTTY use the same adapter path as a custom engine. Adapter metadata is captured once; duplicate IDs, ambiguous native window classes, unsafe executable names, oversized previews, and hosts without lifecycle authority are rejected. The exact 0.1.0-script-files-final package exposed the dynamic PuTTY/KiTTY Settings rows, launched and reconnected real PuTTY generations, preserved PID/HWND through native settings, and attached, detached, and reattached one controlled external HWND. Passing split summaries used no global input, focus activation, or desktop switch and left only the protected pre-existing processes.

The exact 0.1.0-script-files-final package closes the remaining headless script-file gap. Load accepts only strict UTF-8 with an optional UTF-8 BOM, preserves line endings, and enforces 1 MiB byte/character limits. Save emits UTF-8 without a BOM and uses a unique same-directory staging file, flush-before-replace, cancellation/failure preservation, and cleanup. The current suite now passes 28 Core scenario groups and all 30 named checks.

See product status for the full reference-feature matrix and architecture for the design. The current requirement-by-requirement verdict and remaining external evidence are tracked in the completion audit. Existing MTPuTTY users should also read the migration guide.

Requirements

  • Windows 10 or later
  • .NET 8 Desktop Runtime for the framework-dependent package; the portable and installer packages are self-contained
  • PuTTY installed separately

For development, install the .NET 8 SDK or a later SDK capable of targeting net8.0-windows.

Build and run

dotnet build nmtputty.sln -c Release
dotnet run --project src/NmTputty.App/NmTputty.App.csproj

Portable mode stores nmtputty.json beside the application:

dotnet run --project src/NmTputty.App/NmTputty.App.csproj -- --portable

Published portable builds include portable.marker, so they select local storage automatically without arguments. Both binary variants include LICENSE.txt.

Without --portable (or the MTPuTTY-compatible /P switch), configuration is stored in:

%LOCALAPPDATA%\NMT PuTTY\workspace.json

Run the dependency-free core checks with:

dotnet run --project tests/NmTputty.Core.Tests/NmTputty.Core.Tests.csproj -c Release

The headless Docker gate can run without launching any Windows UI:

docker build --tag nmtputty-gate:local .
docker run --rm nmtputty-gate:local

The image pins its .NET 8 SDK base and cross-compiles the complete Windows solution, verifies formatting and forbidden-API/async safety scans, executes all Core scenario groups and checks, then cross-publishes and validates the three-file self-contained win-x64 payload. Its default command reruns the Core suite. Linux containers cannot execute the Windows adapter suite or validate WPF, HWND hosting, PuTTY process ownership, focus, DPI, or visual behavior.

Run the Windows adapter checks (these create only a message-only HWND and a temporary isolated current-user registry fixture, with no visible window or input injection) with:

dotnet run --project tests/NmTputty.App.Tests/NmTputty.App.Tests.csproj -c Release

The remaining literal pointer, physical-hotkey, and mixed-DPI checks use the passive physical-input acceptance recorder. Its --self-test mode is headless; the attended mode never launches until the operator explicitly types START.

Create a self-contained portable ZIP, a smaller framework-dependent folder, and a per-user Windows Setup package:

./scripts/package.ps1 -Version 0.1.0

The replaceable application-icon master is src/NmTputty.App/Assets/nmtputty-icon.png. After replacing that square, transparent PNG, regenerate its nine Windows icon sizes with:

./scripts/build-icon.ps1

The application project embeds the resulting nmtputty.ico. The package script supplies the same icon to Setup and rejects a candidate unless the 32-pixel icon extracted from every application publish and Setup matches that source ICO.

Package output is written beneath artifacts/packages/<version> and the script refuses to overwrite an existing version directory. Publishing is staged until the portable, framework-dependent, and pinned Velopack installer variants validate. The completed version directory includes SHA256SUMS.txt for every Setup, update-index, package, ZIP, and application payload.

Installer candidates are unsigned by default. A release build can supply the code-signing arguments without editing the script:

$env:NMT_VELOPACK_SIGN_PARAMS = '<signtool arguments>'
./scripts/package.ps1 -Version 0.1.0

The installer creates a Start-menu shortcut and uses per-user installed storage; it does not bundle PuTTY or copy the portable marker.

Repository layout

src/NmTputty.Core/       Profiles, persistence, command and script parsing
src/NmTputty.App/        WPF UI and ITerminalHost-based Win32 PuTTY adapter
tests/                   Core checks, fixtures, isolated and manual acceptance
docs/                    Product scope, architecture, and decisions

Security

NMT PuTTY never stores credentials in workspace files or places them on command lines. Optional saved credentials use a bounded protected-provider contract; the default Windows adapter stores stable per-profile targets in Windows Credential Manager, and portable bundles do not copy them. Prefer key files, Pageant, agent integrations supported by PuTTY, or interactive authentication where possible. Automatic login is disabled by default, runs once per connected lifecycle generation, and does not run the startup script if credential delivery is incomplete.

Extra PuTTY arguments are an advanced feature. They are passed as structured process arguments, but users should still treat imported workspace files as configuration with the same trust level as a shell shortcut.

Project status

This is an early working build, not a finished MTPuTTY replacement. The containerized cross-build plus the local Windows Release build, Core and adapter executables, formatting, source-safety, portable publish, complete Windows package, and recursive SHA-256 manifest gates are clean. Live Windows inspection has covered custom chrome, light/dark controls, borderless PuTTY hosting, direct three-session navigation, persisted navigator visibility, three-session tab/tile/dock layouts, attach/detach ownership, manual reconnect, fault-injected automatic reconnect without process overlap, and exact-package mixed-ownership tab-close/quit cancellation, confirmation, and restart. Exact-package fault injection also covers immediate exit, discovery timeout, wrong native window class, fresh retry, dark failure surfaces, and healthy-session isolation. KiTTY 0.76.1.13 also passes an exact-package Raw launch, native embed, detach, backend-aware orphan discovery, same-HWND reattach, and external-process preservation on quit. The explicit PuTTY/KiTTY import-or-reload workflow is now composed through a bounded Core connection-source catalog. It is covered through an isolated temporary-HKCU fixture plus exact-package stable-ID palette discovery. Protected credential storage is likewise composed through a bounded Core provider catalog; the Windows adapter is the default rather than a shell dependency, and dialogs use the selected provider's validated display metadata. A sanitized MTPuTTY XML tree also passes native file selection, merge preview, apply, persistence, and restart restoration; its versioned JSON tree passes native export, re-import, stable-ID preservation, and another full restart. Deterministic server-tree acceptance also covers friendly mixed-item sorting, sidebar side/width, hide/show, folder expansion, and two restart transitions. A minimal-shell run proves all four optional surfaces can be hidden, recovered through the always-visible status gear, and restored after restart; exact normal, maximized, and restore bounds also persist. A two-generation packaged run preserved session identity, renamed title order, active selection, and Columns layout across a full restart. A selected three-level folder also opened its three enabled descendants into independent live PuTTY panes while excluding and reporting one deep batch off profile. The exact 0.1.0-dock-targeting-final-v3 package invoked left, right, top, and bottom dock transactions, exposed the same actions through a keyboard-accessible Session menu, and restored a mixed row/column tree as three live native panes. The exact 0.1.0-splitter-transform-final package additionally resized every root and nested dock splitter, plus Columns and Rows splitters, through WPF's accessible Transform pattern and restored the saved proportions in fresh application/PuTTY processes. The exact 0.1.0-hotkey-focus-final package edited a focus chord and restored it after restart, then moved an explicitly cleared isolated-desktop focus state to the exact selected PuTTY HWND in both fresh generations. The exact 0.1.0-terminal-settings-final package then used the new accessible session-header action to change PuTTY from Courier New 10-point with a black background to Consolas 12-point and RGB 18,24,32, applied it, reopened it in the same terminal, saved it to a disposable PuTTY session, and reloaded the exact values in fresh NMT/PuTTY processes. The temporary registry session and every test process were removed. The exact 0.1.0-quick-connect-final package then opened two accessible Raw Quick Connect tabs without creating a saved profile. Shutdown persisted no profile, open-session, active-tab, or dock-layout residue, and a fresh isolated-desktop restart exposed No open sessions without reconnecting. The exact 0.1.0-profile-crud-final package now also creates a complete saved profile through 15 named editor controls, edits the same stable profile identity, reopens every value after restart, deletes it through the real confirmation path, and restarts with an empty workspace. The exact 0.1.0-toolbar-actions-final package additionally configures an ordered three-command toolbar over the shared 33-command catalog. A syntactically valid missing command remained visible and disabled until explicitly removed; the saved sequence routed the existing Appearance operation and survived a fresh process restart. The current catalog contains 35 commands after adding the two built-in connection-source actions. The exact 0.1.0-branding-final-v2 package now produces the per-user Setup and release-feed assets from a pinned tool version with one replaceable icon embedded consistently in the portable, framework-dependent, installed-input, and Setup executables. Its structure, recursive manifest, icon-resource checks, new startup entry point, and separate-desktop startup/restart pass, while signed clean-user install/upgrade/uninstall remains a release gate. The next UI milestone is literal physical-pointer gestures, a physical hotkey chord, and mixed-DPI movement. Same-DPI multi-monitor placement is now exact-package verified, including secondary-monitor maximize/restore and removed-monitor repair.

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages