A portable Windows coordination layer for running multiple ChatGPT chats through Desktop Commander on the same PC at the same time.
ChatGPT MultiChat reduces collisions between parallel chats by giving each managed chat its own session, slot, color, optional isolated Git worktree, development port, and shared-resource locks.
Current version: v2.4.0
When several chats execute local commands independently, they can easily:
- edit the same repository at the same time;
- start development servers on the same port;
- compete for ADB, fastboot, scrcpy, an Android emulator, or another exclusive resource;
- leave behind terminal sessions that are hard to identify;
- overwrite or interfere with another chat's work.
MultiChat turns those independent shells into coordinated sessions.
ChatGPT A ─┐
ChatGPT B ─┼─> Start-McpChatSession.ps1
ChatGPT C ─┘ │
├─ assigns CHAT-1 ... CHAT-N (configurable in the dashboard)
├─ tracks status and activity
├─ creates an isolated Git worktree/branch when appropriate
├─ reserves a development port
├─ applies shared-resource locks
└─ appears in the MultiChat dashboard
Each chat should open one persistent managed session and reuse that same process/PID for the entire task. All later commands for that chat should be sent to the same session.
- Configurable capacity from 2 to 32 simultaneous managed chats, editable directly from the dashboard.
- Isolated Git worktrees and branches for repository work.
- Exact-base worktree creation with optional
BaseRef+ fullBaseShavalidation. - Optional declared
CanonicalReffor fail-closed integration/cleanup checks. - Automatic development-port reservation.
- Dynamic resource identities, including Android serials and AVD names.
- Explicit resource wrappers that hold a lock for an entire operation.
- Persistent external-executor leases with heartbeat/TTL and conservative stale handling.
- Activity classification such as
READY,BUILD,TEST,GIT,ADB,SERVER, andWAIT. - Redesigned WinForms tray dashboard with a cleaner dark UI, metric cards, and improved table readability.
- Short history of completed sessions.
- Automatic background cleanup of finished worktrees that are verified
SAFE, with manual cleanup retained as a fallback. - Recovery of abandoned sessions and dead owner processes.
- Desktop Commander connection status with green/yellow/red LED, plus an On/Off connection switch. Remote access starts Off on every MultiChat launch and must be enabled locally when needed.
- Automatic hidden restart of Desktop Commander while the connection switch is On.
- Stable/Beta update channels with manual Check now.
- In-app release notes and signed portable self-updates.
- SHA-256 + RSA-4096 verification before an update is installed.
- One-command signed release publishing for the maintainer.
- No automatic Windows startup.
- Portable package with no machine-specific paths or runtime state.
- Optional Restricted Remote mode that runs Remote Desktop Commander under a dedicated standard Windows identity instead of the signed-in user.
|
|
| Live chat-capacity presets | Signed update workflow |
The screenshots above were captured from the portable build in an isolated Windows Sandbox environment using demo-only sessions and no personal workspace data.
- Added a dashboard chat-capacity selector: CHATS [−] N [+].
- Capacity can be changed live from 2 to 32 managed chats without restarting MultiChat.
- Clicking the capacity number opens presets for 4, 6, 8, 10, 12, 16, 20, 24, and 32 chats.
- Reducing capacity is blocked when an active higher-numbered slot would fall outside the new range.
- The active-chat metric updates immediately to the new capacity.
- The core allocator now enforces the same 2–32 range even if
config.jsonis edited manually. - Added 32 distinct dashboard slot colors and expanded console slot coloring.
- Added
CapacityTest.ps1, including 12-slot, 32-slot, overflow, and manual-config clamp validation. - UI theme helpers now use an explicitly shared theme so visual components remain reliable when loaded by tests or auxiliary scripts.
- Added a real portable self-updater. Install update downloads, verifies, stages, installs, and restarts MultiChat.
- Updates require both a matching SHA-256 checksum and a valid RSA-4096 package signature before any application files are replaced.
- Added Stable and Beta update channels with correct SemVer prerelease ordering.
- Added Check now in the dashboard and tray menu.
- Added an in-app What's new dialog using GitHub release notes.
- User configuration is merged into new defaults during updates; runtime state and workspaces are never replaced.
- Failed updates roll application files back and record a result for the next launch.
- Git checkouts are never overwritten by the self-updater; they fall back to the GitHub release page.
- Added
Sign-ReleasePackage.ps1,Test-ReleaseSignature.ps1, andPublish-Release.ps1. - The release public key is shipped with MultiChat; the private signing key remains outside the repository.
- Added a background GitHub Releases update check with a persistent 24-hour cache.
- The installed version is always shown in the dashboard footer.
- When a newer release exists, MultiChat shows the latest version plus Download update and Later controls.
- Update checks never block the UI and fail silently when the network or GitHub is unavailable.
- The update notification can be disabled with
checkForUpdatesor rescheduled withupdateCheckHours. - Update comparison is recalculated against the currently installed version even when release metadata comes from cache.
- MultiChat only opens the release page; it does not self-update or replace files automatically.
- Added exact Git base contracts:
-BaseRefand full 40-character-BaseShamust resolve to the same commit or session creation fails closed. - Worktrees are created from the validated SHA instead of implicit local
HEAD. - Added optional
-CanonicalRefand cleanup rules that prove either zero own commits relative tobaseShaor integration into the declared canonical ref. - Added persistent leases for external executors.
ACTIVE,STALE,MISMATCH, andUNKNOWNleases protect sessions from expiry, reservation release, and cleanup. - Added
Invoke-ManagedExternal.ps1with automatic lease heartbeat and resource retention for long-running external processes. - Added dynamic Android resource identities such as
android:serial:<serial>andandroid:avd:<name>; different devices can run concurrently while the same identity collides. - Added explicit
Invoke-WithChatResource(s)wrappers for operations that must hold a resource independently of command-regex detection. - Added
Validate-ManagedSession.ps1for fail-closed post-execution validation of workspace, base, worktree identity, and lease state. - Cleanup now verifies exact worktree identity and refuses legacy/ambiguous states such as
BASE_UNKNOWN,FOREIGN_WORKTREE_STATE, or protective leases. - Replaced the Desktop Commander switch's native CheckBox rendering with a fully custom-drawn panel so hover no longer paints a gray Windows background.
- Added
HardeningTest.ps1covering resource concurrency, exact-base mismatch, lease expiry/cleanup veto, stale/unknown lease behavior, canonical integration, and SAFE cleanup.
- Fixed the minimize-button container so its hover square is always fully visible.
- Replaced the header's flow layout with fixed-position window controls.
- Added a status LED for Desktop Commander: green
ONLINE, yellowCONNECTING, redOFFLINE. - Added a connection switch in the header. It originally defaulted to On; current hardened builds start remote access Off on every app launch.
- Switching Off stops Desktop Commander and disables automatic reconnect attempts until the switch is turned On again.
- Switching On starts Desktop Commander when needed and transitions through
CONNECTINGtoONLINE.
- Fixed the minimize button hover state and centered its glyph.
- Replaced unreliable form-level resizing with eight dedicated resize grips for edges and corners.
- Clarified Git tooltips: for example,
23 newnow explains that those files are not tracked by Git. - Finished
SAFEworktrees are cleaned automatically in the background instead of continuously accumulating. - Auto-clean skips worktrees whose owner process is still alive and keeps manual cleanup as a fallback.
- Stale folders that no longer resolve to their own Git worktree are classified as
NOT_A_WORKTREEand retained instead of being deleted without verifiable Git state.
- Refreshed dashboard using Segoe UI, flatter controls, status cards, and clearer visual hierarchy.
- Borderless dark window chrome replaces the native white Windows title bar; the custom header remains draggable.
- Git state is now shown with readable labels such as
Clean,28 new,4 changed,ahead 2, andbehind 1. - Worktree scanning and cleanup run in hidden worker processes instead of blocking the UI thread.
- Cleanup uses cached candidates, clears stale counts immediately, revalidates candidates before deletion, and reports failed removals.
- Git summaries, session expiry, liveness validation, and Desktop Commander health checks run in a hidden maintenance worker instead of the UI thread.
- Grid cells are updated only when their displayed value changes.
- Expensive Git checks are avoided during ordinary one-second status refreshes.
- The dashboard reads active sessions through indexed slot files instead of scanning the full session history on every refresh.
- Session/project registry handling is more defensive against malformed stale entries.
- UI helpers are isolated in
MultiChat.UI.ps1, while performance-sensitive runtime logic is consolidated inChatMulti.Advanced.ps1.
- Windows 10 or Windows 11.
- Windows PowerShell 5.1 or later.
- Git.
- Node.js with
npx. - Desktop Commander available through
npx.
- Download the portable ZIP from the latest GitHub release.
- Extract it to a permanent folder.
- Run
Setup.cmd. - A versioned ChatGPT MultiChat shortcut is created on the desktop.
- Open MultiChat before starting parallel Desktop Commander work.
Setup.cmd does not configure automatic startup.
Normal Remote Desktop Commander runs with the signed-in Windows user's permissions. MultiChat can optionally replace that execution identity with a dedicated local standard account named MultiChatRemote.
Restricted Remote is intended for users who want a stronger boundary against a malicious or compromised remote AI session. It is opt-in because initial setup requires one UAC elevation and some development tools may need separate configuration for the restricted identity.
Prepare the isolated identity from the MultiChat folder:
.\Install-RestrictedRemote.ps1The installer uses dynamic Windows profile/SID paths, verifies the reviewed Desktop Commander 0.2.51 runtime, creates a random credential protected with the interactive user's DPAPI, and grants the restricted identity read-only access to approved Git metadata. Normal repository working trees are not made writable. Restricted jobs use their own Git clones and their own state/workspace tree.
Before enabling the mode, finish or close normal managed sessions. Then run:
.\Activate-RestrictedRemote.ps1Activation transfers the existing Remote Desktop Commander authorization to the restricted profile and removes it from the interactive user's profile. Reopen MultiChat and turn Desktop Commander On locally.
In Restricted Remote mode:
- the remote process runs as a dedicated non-administrator Windows identity;
- the interactive user's DPAPI store, browser profile, Startup folder, HKCU persistence locations, and unrelated personal files are outside that identity's normal access boundary;
- canonical Git metadata is read-only and each managed task works in an isolated shared clone;
- restricted session state/workspaces are separate from normal MultiChat state;
- no GitHub credentials are copied automatically;
- finished restricted commits must be imported explicitly for review with
Import-RestrictedRemoteChanges.ps1; nothing is merged automatically; - the emergency disconnect still revokes authorization and kills the contained process tree.
To remove the mode and its dedicated Windows account:
.\Uninstall-RestrictedRemote.ps1Remote access remains Off after removal until it is explicitly enabled again. Moving the portable MultiChat folder intentionally invalidates an existing Restricted Remote configuration; rerun the installer from the new location rather than silently reusing stale ACL/path assumptions.
The easiest approach is to give ChatGPT the contents of PROMPT-FOR-CHATGPT.txt.
The essential instruction is:
Use the ChatGPT MultiChat system installed on this PC for any Desktop Commander work.
Start one persistent session with Start-McpChatSession.ps1, reuse its PID for the entire task,
and do not modify the project through loose MCP shells. If you work in a Git repository,
use the isolated worktree assigned by MultiChat. Respect resource locks and the assigned port.
A chat should start a session similar to:
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass `
-File "C:\path\to\ChatGPT-MultiChat\Start-McpChatSession.ps1" `
-ProjectPath "C:\path\to\project" `
-Task "short-task-description"From that point onward, all commands for that task should be sent to the same PID.
When an orchestrator already knows the exact base it expects, pass both the ref and the full SHA:
Start-McpChatSession.ps1 `
-ProjectPath "C:\path\to\project" `
-Task "validated-task" `
-BaseRef "origin/main" `
-BaseSha "0123456789abcdef0123456789abcdef01234567" `
-CanonicalRef "origin/main"MultiChat does not silently move the requested base. BaseRef and BaseSha must resolve to the same commit or session creation fails. The caller is responsible for fetching/revalidating the desired ref before starting the session when freshness matters.
CanonicalRef is optional. When supplied, it is used later to prove whether commits created in the managed worktree have been integrated. MultiChat never auto-merges them.
For work that should not create a Git worktree:
Start-McpChatSession.ps1 `
-ProjectPath "C:\path\to\project" `
-Task "test" `
-NoWorktreeType exit or quit inside the managed session to release it cleanly.
The dashboard shows one row per active managed chat:
| Field | Meaning |
|---|---|
| Chat | Assigned slot (CHAT-1 ... CHAT-N, according to the configured capacity) |
| Project | Associated project |
| Activity | FREE, IDLE, or WORKING |
| Detail | Detected command/activity type |
| Time | Time since the last state update |
| Git | Compact Git summary |
| Port | Development port reserved for the session |
| Task | Task description supplied when the session started |
| Warning | Conflicts or conditions that need attention |
The header includes a live CHATS capacity control. Use − / + for one-step changes or click the number for common presets. New sessions immediately use the new limit. MultiChat refuses reductions that would exclude an active higher-numbered slot.
Closing the dashboard window does not stop the agent. It remains in the Windows system tray. Use Exit from the tray menu to stop it completely.
The visible chat state still refreshes quickly, but expensive work is decoupled from that timer:
- the one-second UI refresh reads only the active slot index and cached values;
- Git summaries, session expiry, PID validation, and Desktop Commander process detection run in a hidden maintenance worker;
- recent history is refreshed separately;
- worktree scanning runs in its own hidden worker;
- worktree cleanup also runs in a hidden worker;
- refresh pauses while the window is moved or resized.
This keeps the WinForms UI responsive even when Git operations take around a second on a larger set of worktrees.
When a managed session is in READY, the dashboard displays it as FREE. After 10 minutes without a managed-shell command it becomes IDLE. IDLE means only that the shell has been quiet; it does not mean the ChatGPT conversation has ended or been abandoned.
Default behavior:
FREE: the managed shell is ready and was used recently.IDLE: the managed shell has been quiet for 10 minutes but remains allocated and is not terminated automatically.WORKING: MultiChat currently sees managed activity such asBUILD,TEST,ADB,SERVER, or another command class.- Automatic READY-session expiry is off by default. Users who explicitly opt into
autoExpireIdleSessionscan still use the legacy clean/dirty expiry thresholds.
If the process that owns a session disappears, MultiChat can release its slot, port, and resource locks only when no protective external lease exists. An ACTIVE, STALE, MISMATCH, or UNKNOWN lease keeps the session fail-closed. The dashboard's right-click close action is always explicit and warns that an IDLE shell may still belong to an active chat.
Cleanup is deliberately fail-closed.
A finished managed worktree is SAFE only when MultiChat can prove all of the following:
- there is no protective lease;
- the workspace is still the exact worktree registered by the originating repository;
- the expected managed branch still matches that worktree;
- the tree has no tracked modifications or untracked files;
- a valid persisted
baseShaexists and is an ancestor of the worktree HEAD; - either the worktree has zero own commits relative to
baseSha, or its HEAD is demonstrably integrated into the declaredcanonicalRef.
If any proof is missing, the result is KEEP, not deletion. Examples include BASE_UNKNOWN, BASE_INCORRECT, CANONICAL_REF_MISSING, UNMERGED_COMMITS, WORKSPACE_MISMATCH, FOREIGN_WORKTREE_STATE, and protective lease states.
Legacy session records that predate persisted baseSha are therefore not auto-cleaned merely because they look clean.
You can still use:
- Clean safe worktrees in the dashboard as a manual fallback;
Cleanup-Worktrees.ps1to inspect candidates and reasons;Cleanup-Worktrees.ps1 -Applyto apply only candidates that remainSAFEafter immediate revalidation.
The dashboard rescans periodically in the background and reports only the candidates that remain after automatic cleanup.
Resources are identified by real identity whenever possible instead of one global Android lock.
Examples:
android:serial:THOR_SERIALandroid:serial:emulator-5554android:avd:pixel_testandroid-sdk
ADB/fastboot/scrcpy commands with an explicit -s <serial> are locked by serial. Emulator launches with -avd <name> are locked by AVD name. Two different serials or AVDs can therefore run concurrently, while two operations targeting the same identity collide.
When an ADB-style command omits the serial, MultiChat uses ANDROID_SERIAL when present, otherwise it resolves a single connected ADB device when that is unambiguous. If it cannot prove one device identity, it falls back to the conservative android:adb-default resource. Ambiguous ADB/fastboot resources conflict with every android:serial:* lock, so uncertainty reduces concurrency rather than risking two operations on the same device.
Regex rules in config.json remain available for additional static shared resources, but Android serial/AVD isolation is resolved dynamically.
For operations where the lock must remain held for the entire wrapper operation, use:
Invoke-WithChatResource -Resource "android:serial:emulator-5554" -ScriptBlock {
# complete operation here
}or Invoke-WithChatResources for multiple identities. These wrappers are independent of command-line regex detection.
Long-running external executors can outlive the interactive shell that launched them. A lease keeps the managed session, worktree, slot, development port, and lease-owned resource locks protected while that executor is active.
Core commands:
New-ChatLeaseUpdate-ChatLeasefor heartbeat/renewalClose-ChatLeaseInvoke-WithChatLease
For a complete external process wrapper with automatic heartbeat:
.\Invoke-ManagedExternal.ps1 `
-SessionId $env:CHATGPT_SESSION_ID `
-Owner "external-validator" `
-Resource "android:serial:emulator-5554" `
-FilePath "powershell.exe" `
-ArgumentList @("-NoProfile","-File","run-validation.ps1")Lease states are conservative:
ACTIVE: execution is protected;STALE: heartbeat expired, but MultiChat still protects the session;MISMATCH: lease snapshot does not match session/workspace/base;UNKNOWN: lease evidence exists but cannot be safely interpreted;NONE: no protective lease is present.
Only NONE permits ordinary expiry/release/cleanup. Stale, mismatched, or unreadable lease evidence is never treated as permission to delete work.
Validate-ManagedSession.ps1 can be used after an external execution to fail closed on workspace/base/lease mismatches:
.\Validate-ManagedSession.ps1 `
-SessionId $env:CHATGPT_SESSION_ID `
-ExpectedWorkspace $env:CHATGPT_WORKSPACE `
-ExpectedBaseSha $env:CHATGPT_BASE_SHA `
-RequireLeaseEach managed session can reserve a different development port.
The default range starts at port 3000 and contains 100 configurable positions. This prevents two managed chats from accidentally starting development servers on the same port.
The main settings live in config.json:
| Setting | Default | Purpose |
|---|---|---|
maxSlots |
8 | Maximum simultaneous managed chats; dashboard selector supports 2–32 |
checkForUpdates |
true | Check GitHub Releases for newer MultiChat versions |
updateCheckHours |
24 | Minimum interval between successful release checks |
updateChannel |
stable | Release channel: stable or beta |
refreshSeconds |
1 | Lightweight chat-status/UI refresh interval |
maintenanceRefreshSeconds |
15 | Background Git, expiry, liveness, and Desktop Commander maintenance interval |
historyRefreshSeconds |
5 | Recent-history refresh interval |
cleanupScanSeconds |
30 | Background worktree-scan interval |
autoCleanSafeWorktrees |
true | Automatically remove finished worktrees that pass all SAFE checks |
defaultLeaseTtlMinutes |
60 | Default external-executor lease TTL when a caller does not supply one |
idleAfterMinutes |
10 (code default) | Time before a quiet READY shell is displayed as IDLE; absence of this optional property uses 10 minutes |
autoExpireIdleSessions |
false (code default) | Opt-in automatic expiry of live READY shells; disabled by default because shell silence cannot prove the chat was abandoned |
cleanExpireMinutes |
10 | Clean-session expiry threshold when autoExpireIdleSessions is explicitly enabled |
dirtyExpireMinutes |
20 | Dirty-session expiry threshold when autoExpireIdleSessions is explicitly enabled |
portRangeStart |
3000 | First reservable development port |
portRangeCount |
100 | Number of ports in the reservation pool |
historyLimit |
50 | Maximum stored history entries |
remoteDisconnectOnLock |
true | Stop Remote Desktop Commander when Windows is locked |
remoteIdleDisconnectMinutes |
30 | Stop Remote Desktop Commander after this many minutes with no managed chats; 0 disables the idle cutoff |
remotePurgeHistoryOnDisconnect |
true | Remove local Desktop Commander tool-history files whenever remote access is stopped |
The three remote-security values above are secure code defaults even when the properties are absent from an older config.json. Remote Desktop Commander itself also starts Off on every MultiChat launch; this startup rule is not controlled by config.json.
MultiChat also synchronizes Desktop Commander's allowedDirectories with registered project roots plus the conventional source\repos development root. This blocks direct filesystem-tool access outside those locations. It is a guardrail, not an OS sandbox: terminal commands still run with the Windows user's permissions.
Additional static resource-lock rules are defined in config.json. Android serial and AVD identities are resolved dynamically by MultiChat.
The dashboard supports two release channels:
- Stable uses the latest non-prerelease GitHub Release.
- Beta considers both stable releases and prereleases and compares them using SemVer precedence.
Check now bypasses the local release cache. What's new shows the release notes inside MultiChat. Later dismisses the current notification until the app restarts or a different release is discovered.
For ordinary portable installations, Install update runs a signed in-place update. MultiChat downloads three matching assets:
ChatGPT-MultiChat-VERSION-portable.zipChatGPT-MultiChat-VERSION-portable.zip.sha256ChatGPT-MultiChat-VERSION-portable.zip.sig
The ZIP must match its SHA-256 file and verify against the bundled RSA-4096 public key before staging begins. Runtime directories such as state/, workspaces/, and dist/ are not replaced. Existing user configuration is merged over the new default configuration.
Git checkouts are intentionally excluded from in-place updates to avoid dirtying or overwriting a developer repository.
Release public-key SHA-256 fingerprint:
1b602bccff512c84efbc67fda6a4bdbcafb61d484102dc5ff973f59107f3e3dd
The private signing key is stored outside the repository on the maintainer machine. To publish a signed release after updating VERSION:
.\Publish-Release.ps1This runs the self-test, builds the portable ZIP, creates the SHA-256 file, signs the ZIP, verifies the signature locally, and creates the GitHub Release. Versions containing a prerelease suffix such as 2.4.0-beta.1 are published with GitHub's prerelease flag.
| File | Purpose |
|---|---|
ChatMulti.psm1 |
Session-management core and module loader |
ChatMulti.Advanced.ps1 |
Configuration cache, ports, history, project resolution, Git/status, cleanup, idle-state, conflicts, and reservations |
ChatMulti.Hardening.ps1 |
Exact-base validation, dynamic resource identities, leases, worktree identity, canonical integration checks, and fail-closed validation |
SecurityTest.ps1 |
Static and runtime checks for Remote Desktop Commander hardening, ACLs, authorization storage, and secure defaults |
SecretScan.ps1 |
High-confidence credential scan for tracked files, with optional Git-history scanning |
Harden-DesktopCommander.ps1 |
Restricts local Desktop Commander state ACLs and disables telemetry |
Emergency-Stop-DesktopCommander.ps1 |
Immediately stops remote access, revokes the current server-side device/session when possible, removes local authorization, and supports non-destructive -DryRun validation |
Install-RestrictedRemote.ps1 / Activate-RestrictedRemote.ps1 |
Prepare and enable the optional dedicated standard-user containment mode |
RestrictedRemote.psm1 / RestrictedRemote-Launcher.ps1 / RestrictedRemote-Child.ps1 |
Restricted Remote configuration, credential handling, process containment, and isolated child environment |
Import-RestrictedRemoteChanges.ps1 |
Imports a finished restricted-session commit into a new local review branch without merging it |
Uninstall-RestrictedRemote.ps1 |
Revokes/removes the restricted identity and its ACL grants while leaving remote access Off |
RestrictedRemoteTest.ps1 / PortabilityTest.ps1 |
Isolation and machine-independent path validation |
SECURITY-AUDIT.md |
Threat model, adversarial capability results, implemented mitigations, and residual-risk analysis |
MultiChat-Tray.ps1 |
Lightweight dashboard orchestration and system-tray agent |
MultiChat.UI.ps1 |
Reusable WinForms styling and UI helpers |
MultiChat-Maintenance.ps1 |
Background Git, expiry, liveness, and Desktop Commander maintenance worker |
Check-Updates.ps1 |
Background GitHub Releases checker with Stable/Beta SemVer comparison and cached release notes |
Update-MultiChat.ps1 |
Signed portable self-updater with staging, rollback, and config preservation |
Sign-ReleasePackage.ps1 |
Maintainer-side RSA package signer |
Test-ReleaseSignature.ps1 |
Public RSA signature verifier |
Publish-Release.ps1 |
One-command test/build/checksum/sign/verify/GitHub release publisher |
RELEASE-PUBLIC-KEY.xml |
Public RSA-4096 key used by the updater to verify release packages |
Start-McpChatSession.ps1 |
Starts and owns one persistent managed chat session |
Setup.cmd / Setup.ps1 |
Local setup and desktop shortcut |
config.json |
Portable configuration |
PROMPT-FOR-CHATGPT.txt |
Ready-to-paste ChatGPT instruction |
SelfTest.cmd / SelfTest.ps1 |
System validation |
Cleanup-Worktrees.ps1 |
Fail-closed worktree cleanup and diagnostic result output |
Validate-ManagedSession.ps1 |
Post-execution workspace/base/lease validator |
Invoke-ManagedExternal.ps1 |
Long-running external-process wrapper with lease heartbeat and resource retention |
HardeningTest.ps1 |
Concurrency, exact-base, lease, and cleanup safety test suite |
CapacityTest.ps1 |
Isolated dynamic-capacity validation for 12/32 slots and overflow clamps |
Show-History.ps1 |
Session-history viewer |
Make-Portable-Package.ps1 |
Builds the portable release ZIP |
Run:
SelfTest.cmdExpected result:
SELF-TEST: OK
Dependencies, scripts, configuration, registry robustness, slots, colors and ports: OK.
The self-test checks dependencies, PowerShell syntax, configuration, slot behavior, UI controls, port reservation, deterministic update-version detection, and then runs HardeningTest.ps1. The hardening suite verifies dynamic-resource concurrency, exact-base creation and mismatch rejection, lease protection, stale/unknown fail-closed behavior, canonical integration, and SAFE cleanup.
The project uses paths relative to its own folder.
Make-Portable-Package.ps1 creates a ZIP without copying machine-local runtime state, logs, sessions, leases, or worktrees. The package recreates empty runtime directories, including state\leases, on the target machine.
To build a package:
.\Make-Portable-Package.ps1 -Version "2.4.0"MultiChat coordinates processes that use the MultiChat session system. It cannot prevent an unrelated terminal, another application, or a chat that ignores the manager from directly editing the same repository or using the same external resource.
Normal Remote Desktop Commander mode still executes as the interactive Windows user. allowedDirectories and command rules are guardrails, not an OS sandbox. Restricted Remote materially reduces this same-user exposure, but it can still read the approved project history/files made available to it and can send readable data over its required outbound network connection.
The key rule is therefore:
one chat → one persistent managed session → one reused PID for the entire task.
- If Restricted Remote was installed, run
Uninstall-RestrictedRemote.ps1first so its local account, authorization, and ACL grants are removed cleanly. - Exit the agent from the system-tray icon.
- Delete the desktop shortcut.
- Delete the ChatGPT MultiChat folder.
No Windows service or automatic-start entry is installed.


