Skip to content

feat: Add Windows support via ConPTY#6

Open
deblasis wants to merge 5 commits intoghostty-org:mainfrom
deblasis:feat/windows-port
Open

feat: Add Windows support via ConPTY#6
deblasis wants to merge 5 commits intoghostty-org:mainfrom
deblasis:feat/windows-port

Conversation

@deblasis
Copy link
Copy Markdown

Adds Windows support using the ConPTY API for terminal emulation.

  • Shell spawn via ConPTY with threaded pipe reader, resize, and cleanup
  • Auto-detect shell (pwsh, powershell, cmd) with --shell override
  • GUI subsystem app so the child shell writes through the pipe
  • CMake workarounds for upstream ghostty DLL path and import library on Windows
  • CI job for Windows

All behind #ifdef _WIN32 in main.c, Unix codepath unchanged.

Tested on Win, Mac and Linux

functional terminal built on the libghostty C API in a
[single C file](https://github.com/ghostty-org/ghostling/blob/main/main.c).

The example uses Raylib for windowing and rendering. It is single-threaded
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the threading detail because with windows technically this is an incorrect statement since we have two threads. Happy to revert as needed

@mitchellh
Copy link
Copy Markdown
Contributor

Lets wait for ghostty-org/ghostty#11756 and then I'll ask if you can rebase this and clean it up, since I think that'll maybe improve some of this.

mitchellh added a commit to ghostty-org/ghostty that referenced this pull request Mar 24, 2026
# What 

PR #11756 added IMPORTED_IMPLIB pointing to the .lib import library, but
the
import library is not listed in the OUTPUT directive of the
`add_custom_command`
that runs zig build. The file is produced as a side-effect of the build.

This works with the Visual Studio generator (which is lenient about
undeclared outputs) but fails with Ninja:

ninja: error: 'zig-out/lib/ghostty-vt.lib', needed by 'ghostling',
missing and no known rule to make it

The fix adds "${ZIG_OUT_DIR}/lib/${GHOSTTY_VT_IMPLIB}" to the OUTPUT
list. No
behavioral change. The file was already being built, Ninja just needs to
know
about it.

## but_why.gif

I am cleaning up ghostty-org/ghostling#6 and I
realise that in order to get rid of the CMake workarounds we had before
#11756, this change is necessary.

# POC

I set up a branch pointing at my fork with a POC and it builds, this is
the cleaned up CMakeList
https://github.com/deblasis/winghostling/blob/test/cmake-implib-no-workaround/CMakeLists.txt
@deblasis deblasis force-pushed the feat/windows-port branch from 2705c59 to 39ccb3a Compare March 24, 2026 04:05
Add Windows platform support to ghostling using the ConPTY API for
pseudo-terminal emulation.  The implementation lives entirely in
main.c alongside the existing Unix code, gated by #ifdef _WIN32.

Key changes:
- ConPTY-based pty spawning with shell auto-detection (pwsh > powershell > cmd)
- Threaded pipe reader for ConPTY output (PeekNamedPipe is unreliable)
- --shell <path> flag for explicit shell selection on all platforms
- GUI subsystem build to prevent console window on Windows
- Windows CI job on windows-latest
- Bump ghostty to include import-lib OUTPUT fix (ghostty-org/ghostty#11794)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@deblasis deblasis force-pushed the feat/windows-port branch from 39ccb3a to 224bcc4 Compare March 24, 2026 04:06
@deblasis
Copy link
Copy Markdown
Author

The #ifdef _WIN32 blocks in main() could be consolidated behind a unified Pty struct with platform-specific implementations (eg: pty_drain(), pty_reap(), pty_resize()), eliminating all conditionals from main().

I kept inline #ifdef blocks to match the existing style in the codebase, but happy to refactor if you'd prefer that approach.

Anything else, fire away.

Copy link
Copy Markdown
Contributor

@mitchellh mitchellh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not bad. I agree the ifdefs are pretty ugly. I'll have to think about it. I put a couple simple requests otherwise.

main.c Outdated
@@ -1,6 +1,55 @@
// ---------------------------------------------------------------------------
// Platform-independent headers
// ---------------------------------------------------------------------------
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this at the top.

main.c Outdated
int main(void)
int main(int argc, char *argv[])
{
// Parse --shell <path> flag for explicit shell selection.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's just change this to argv[1] (no parsing).

Remove section banner comment at top of main.c.
Replace --shell flag parsing with plain argv[1].
Update README to match new usage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@deblasis
Copy link
Copy Markdown
Author

Not bad. I agree the ifdefs are pretty ugly. I'll have to think about it. I put a couple simple requests otherwise.

Awesome! Done and done and tested.

@deblasis deblasis requested a review from mitchellh March 24, 2026 04:40
Resolve conflicts by integrating:
- New ghostty GIT_TAG with updated API
- ghostty_terminal_resize now takes cell_width/cell_height
- pty_spawn now takes cell dimensions for pixel-size winsize
- Keep Windows-specific ConPTY code paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Change EffectsContext.pty_fd to PtyHandle for Windows compatibility
- Fix effects_ctx initialization for both platforms
- Use platform-specific pty handle in effects context

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants