diff --git a/README.md b/README.md index 4a661fb5..2c84c6e8 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ sudo dnf install ./jumpserver-client_*.rpm ### Supported Connection Types -- **SSH/Telnet** - Terminal connections (PuTTY, XShell, SecureCRT, iTerm2) +- **SSH/Telnet** - Terminal connections (PuTTY, XShell, SecureCRT, iTerm2, Ghostty) - **RDP** - Remote Desktop Protocol for Windows servers - **VNC** - Virtual Network Computing for remote desktop access - **Database Connections**: diff --git a/README_CN.md b/README_CN.md index 477f0a7d..865a727e 100755 --- a/README_CN.md +++ b/README_CN.md @@ -107,7 +107,7 @@ sudo dnf install ./jumpserver-client_*.rpm ### 支持的连接类型 -- **SSH/Telnet** - 终端连接(PuTTY、XShell、SecureCRT、iTerm2) +- **SSH/Telnet** - 终端连接(PuTTY、XShell、SecureCRT、iTerm2、Ghostty) - **RDP** - Windows 服务器的远程桌面协议 - **VNC** - 用于远程桌面访问的虚拟网络计算 - **数据库连接**: diff --git a/docs/plugins/DESIGN.md b/docs/plugins/DESIGN.md index 1cd6a966..46c08f89 100644 --- a/docs/plugins/DESIGN.md +++ b/docs/plugins/DESIGN.md @@ -316,7 +316,7 @@ sequenceDiagram | Windows | terminal | putty | | Windows | remotedesktop | mstsc | | Windows | filetransfer | winscp(可选) | -| macOS | terminal | terminal, iterm | +| macOS | terminal | terminal, iterm, ghostty | | macOS | remotedesktop | 系统 RDP(open) | | Linux | terminal | 系统 terminal | | Linux | remotedesktop | xfreerdp, tigervnc | diff --git a/go-client/pkg/awaken/awaken_darwin.go b/go-client/pkg/awaken/awaken_darwin.go index 7c38cf1c..00ea561c 100755 --- a/go-client/pkg/awaken/awaken_darwin.go +++ b/go-client/pkg/awaken/awaken_darwin.go @@ -117,6 +117,30 @@ func awakenSSHCommand(r *Rouse, cfg *config.AppConfig) (*exec.Cmd, error) { scriptPath := filepath.Join(currentPath, "Scripts", "iterm2_loader.scpt") //command = fmt.Sprintf(`%s "%s"`, scriptPath, command) cmd = exec.Command("osascript", "-s", "h", scriptPath, itermCmd, "0") + } else if appItem.Name == "ghostty" { + // Ghostty has no "do script" AppleEvent; `open -na --args -e` only works + // cleanly on a cold start. Once Ghostty is already running, that path + // triggers a security confirmation and, if allowed, a broken extra tab. + // Its AppleScript dictionary avoids both, cold or warm. "wait after + // command" keeps the surface open once the client exits. "activate" + // runs last since calling it earlier opens Ghostty's own default tab; + // the window-count check picks new tab vs. new window so repeat + // connections land in the existing window instead of a new one. + ghosttyCmd := strings.NewReplacer(`\`, `\\`, `"`, `\"`).Replace( + fmt.Sprintf("%s %s", clientPath, commands), + ) + script := fmt.Sprintf(`tell application "Ghostty" + set cfg to new surface configuration + set command of cfg to "%s" + set wait after command of cfg to true + if (count of windows) > 0 then + new tab in (front window) with configuration cfg + else + new window with configuration cfg + end if + activate +end tell`, ghosttyCmd) + cmd = exec.Command("osascript", "-e", script) } else { cmd = exec.Command( "osascript", "-s", "h", "-e", fmt.Sprintf(`tell application "%s" to do script "%s %s" activate`, diff --git a/plugins/macos/index.json b/plugins/macos/index.json index c2a8537b..b5bc6073 100644 --- a/plugins/macos/index.json +++ b/plugins/macos/index.json @@ -11,6 +11,11 @@ "name": "dbeaver", "category": "databases" }, + { + "id": "macos.ghostty", + "name": "ghostty", + "category": "terminal" + }, { "id": "macos.iterm", "name": "iterm", diff --git a/plugins/macos/macos.ghostty/connect.json b/plugins/macos/macos.ghostty/connect.json new file mode 100644 index 00000000..4fe79f9e --- /dev/null +++ b/plugins/macos/macos.ghostty/connect.json @@ -0,0 +1,16 @@ +{ + "platform": "macos", + "match_first": [], + "is_default": false, + "is_set": false, + "is_internal": true, + "executable": { + "type": "bundled", + "default": "Ghostty" + }, + "launch": { + "type": "args", + "template": "{protocol} {username}@{host} -p {port} -P {value}" + }, + "display_name": "Ghostty" +} diff --git a/plugins/macos/macos.ghostty/icon.png b/plugins/macos/macos.ghostty/icon.png new file mode 100644 index 00000000..d787d806 Binary files /dev/null and b/plugins/macos/macos.ghostty/icon.png differ diff --git a/plugins/macos/macos.ghostty/manifest.json b/plugins/macos/macos.ghostty/manifest.json new file mode 100644 index 00000000..1b960a05 --- /dev/null +++ b/plugins/macos/macos.ghostty/manifest.json @@ -0,0 +1,20 @@ +{ + "id": "macos.ghostty", + "name": "ghostty", + "display_name": "Ghostty", + "version": "1.0.0", + "min_client_version": "4.1.3", + "author": "JumpServer", + "homepage": "https://github.com/jumpserver/clients", + "download_url": "https://ghostty.org/download", + "category": "terminal", + "protocols": [ + "ssh", + "telnet" + ], + "builtin": true, + "comment": { + "zh": "Ghostty是一款快速、功能丰富、跨平台的终端模拟器。\n\n!!!手动下载安装,点击保存启用!!!", + "en": "Ghostty is a fast, feature-rich, cross-platform terminal emulator.\n\n!!!Manually download and install, click Save to activate!!!" + } +} diff --git a/ui/assets/images/ghostty.png b/ui/assets/images/ghostty.png new file mode 100644 index 00000000..d787d806 Binary files /dev/null and b/ui/assets/images/ghostty.png differ diff --git a/ui/components/SettingItems/settingItems.vue b/ui/components/SettingItems/settingItems.vue index 0096c471..f72b15d9 100644 --- a/ui/components/SettingItems/settingItems.vue +++ b/ui/components/SettingItems/settingItems.vue @@ -20,6 +20,7 @@ const { setAppConfig } = useSettingManager(); const imagesMap: Record = { iterm: getImageByName("item2"), + ghostty: getImageByName("ghostty"), dbeaver: getImageByName("dbeaver"), heidisql: getImageByName("heidisql"), mstsc: getImageByName("mstsc"),