├── .gitignore ├── README.md ├── forge.config.js ├── images ├── OpenAI_Logo.svg ├── icon.icns ├── icon.png ├── icon@2x.icns ├── icon@2x.png ├── newiconTemplate.png ├── newiconTemplate@2x.png └── screenshot.jpeg ├── index.css ├── index.html ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | .DS_Store 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # TypeScript cache 43 | *.tsbuildinfo 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | .env.test 63 | 64 | # parcel-bundler cache (https://parceljs.org/) 65 | .cache 66 | 67 | # next.js build output 68 | .next 69 | 70 | # nuxt.js build output 71 | .nuxt 72 | 73 | # vuepress build output 74 | .vuepress/dist 75 | 76 | # Serverless directories 77 | .serverless/ 78 | 79 | # FuseBox cache 80 | .fusebox/ 81 | 82 | # DynamoDB Local files 83 | .dynamodb/ 84 | 85 | # Webpack 86 | .webpack/ 87 | 88 | # Electron-Forge 89 | out/ 90 | 91 | .env -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChatGPT menubar app 2 | 3 | This is a fork of https://github.com/vincelwt/chatgpt-mac without analytics and compiled from source for swyx personal use. it's literally a Tauri app with a browser window that you can pull up very quickly with a keyboard shortcut 4 | 5 | 6 | 7 | 8 | ## install 9 | 10 | https://github.com/sw-yx/chatgpt-mac/releases/tag/vswyx 11 | 12 | ## usage 13 | 14 | Cmd+Shift+G -> quick open 15 | 16 | Cmd+R -> refresh/clear 17 | -------------------------------------------------------------------------------- /forge.config.js: -------------------------------------------------------------------------------- 1 | const { parsed } = require("dotenv").config(); 2 | module.exports = { 3 | packagerConfig: { 4 | name: "ChatGPT", 5 | executableName: "ChatGPT", 6 | icon: "images/icon", 7 | appBundleId: "com.sw-yx.chatgptmac", 8 | extendInfo: { 9 | LSUIElement: "true", 10 | }, 11 | osxSign: { 12 | hardenedRuntime: false, 13 | gatekeeperAssess: false, 14 | identity: "Developer ID Application: Lyser.io Ltd (R4PF6TTR6Z)", 15 | } 16 | }, 17 | publishers: [ 18 | { 19 | name: "@electron-forge/publisher-github", 20 | config: { 21 | repository: { 22 | owner: "sw-yx", 23 | name: "chatgpt-mac", 24 | }, 25 | prerelease: true, 26 | }, 27 | }, 28 | ], 29 | 30 | rebuildConfig: {}, 31 | makers: [ 32 | { 33 | name: "@electron-forge/maker-squirrel", 34 | config: {}, 35 | }, 36 | { 37 | name: "@electron-forge/maker-dmg", 38 | platforms: ["darwin"], 39 | config: {}, 40 | }, 41 | { 42 | name: "@electron-forge/maker-deb", 43 | config: {}, 44 | }, 45 | { 46 | name: "@electron-forge/maker-rpm", 47 | config: {}, 48 | }, 49 | ], 50 | }; 51 | -------------------------------------------------------------------------------- /images/OpenAI_Logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /images/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/icon.icns -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/icon.png -------------------------------------------------------------------------------- /images/icon@2x.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/icon@2x.icns -------------------------------------------------------------------------------- /images/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/icon@2x.png -------------------------------------------------------------------------------- /images/newiconTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/newiconTemplate.png -------------------------------------------------------------------------------- /images/newiconTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/newiconTemplate@2x.png -------------------------------------------------------------------------------- /images/screenshot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swyxio/chatgpt-mac/9f2c321fafdf0abb663a3b773bd24440c51b2f9f/images/screenshot.jpeg -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, 3 | Arial, sans-serif; 4 | padding: 0; 5 | margin: 0; 6 | overflow: hidden; 7 | } 8 | 9 | :root { 10 | /* account for the arrow */ 11 | --actual-height: calc(100vh - 12px); 12 | } 13 | 14 | .myarrow { 15 | position: relative; 16 | /* padding-top: 12px; */ 17 | padding: 12px 0 0 0 ; 18 | } 19 | 20 | .myarrow:before { 21 | content: ''; 22 | height: 0; 23 | width: 0; 24 | border-width: 0 8px 12px 8px; 25 | border-style: solid; 26 | border-color: transparent transparent white transparent; 27 | position: absolute; 28 | 29 | top: 0; 30 | left: 50%; 31 | transform: translateX(-50%); 32 | } 33 | 34 | @media (prefers-color-scheme: dark) { 35 | .myarrow:before { 36 | border-color: transparent transparent #343541 transparent !important; 37 | } 38 | } 39 | 40 | .page { 41 | background: #eeeeee; 42 | width: 100%; 43 | height: 100vh; 44 | margin-top: 12px; 45 | margin: 0 auto; 46 | position: relative; 47 | } 48 | 49 | .darwin.page { 50 | border-radius: 8px; 51 | overflow: hidden; 52 | } 53 | 54 | webview { 55 | /* overflow: hidden; */ 56 | position: absolute; 57 | top: 0; 58 | left: 0; 59 | width: 100%; 60 | height: calc(100vh - 12px); 61 | display: inline-flex !important; 62 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ChatGPT 6 | 7 | 8 | 9 |
10 | 11 | 12 |
13 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require("update-electron-app")(); 2 | 3 | const { menubar } = require("menubar"); 4 | 5 | const path = require("path"); 6 | const { 7 | app, 8 | nativeImage, 9 | Tray, 10 | Menu, 11 | globalShortcut, 12 | shell, 13 | } = require("electron"); 14 | const contextMenu = require("electron-context-menu"); 15 | 16 | const image = nativeImage.createFromPath( 17 | path.join(__dirname, `images/newiconTemplate.png`) 18 | ); 19 | 20 | app.on("ready", () => { 21 | 22 | const tray = new Tray(image); 23 | 24 | const mb = menubar({ 25 | browserWindow: { 26 | icon: image, 27 | transparent: path.join(__dirname, `images/iconApp.png`), 28 | webPreferences: { 29 | webviewTag: true, 30 | // nativeWindowOpen: true, 31 | }, 32 | width: 450, 33 | height: 550, 34 | }, 35 | tray, 36 | showOnAllWorkspaces: true, 37 | preloadWindow: true, 38 | showDockIcon: false, 39 | icon: image, 40 | }); 41 | 42 | mb.on("ready", () => { 43 | const { window } = mb; 44 | 45 | 46 | if (process.platform !== "darwin") { 47 | window.setSkipTaskbar(true); 48 | } else { 49 | app.dock.hide(); 50 | } 51 | 52 | const contextMenuTemplate = [ 53 | // add links to github repo and vince's twitter 54 | { 55 | label: "Quit", 56 | accelerator: "Command+Q", 57 | click: () => { 58 | app.quit(); 59 | }, 60 | }, 61 | { 62 | label: "Reload", 63 | accelerator: "Command+R", 64 | click: () => { 65 | window.reload(); 66 | }, 67 | }, 68 | { 69 | label: "Quick Open", 70 | accelerator: "Command+Shift+G", 71 | click: () => { 72 | window.reload(); 73 | }, 74 | }, 75 | { 76 | label: "Open in browser", 77 | click: () => { 78 | shell.openExternal("https://chat.openai.com/chat"); 79 | }, 80 | }, 81 | { 82 | type: "separator", 83 | }, 84 | { 85 | label: "View on GitHub", 86 | click: () => { 87 | shell.openExternal("https://github.com/sw-yx/chatgpt-mac"); 88 | }, 89 | } 90 | ]; 91 | 92 | tray.on("right-click", () => { 93 | mb.tray.popUpContextMenu(Menu.buildFromTemplate(contextMenuTemplate)); 94 | }); 95 | 96 | tray.on("click", (e) => { 97 | //check if ctrl or meta key is pressed while clicking 98 | e.ctrlKey || e.metaKey 99 | ? mb.tray.popUpContextMenu(Menu.buildFromTemplate(contextMenuTemplate)) 100 | : null; 101 | }); 102 | const menu = new Menu(); 103 | 104 | globalShortcut.register("CommandOrControl+Shift+g", () => { 105 | if (window.isVisible()) { 106 | mb.hideWindow(); 107 | } else { 108 | mb.showWindow(); 109 | if (process.platform == "darwin") { 110 | mb.app.show(); 111 | } 112 | mb.app.focus(); 113 | } 114 | }); 115 | 116 | Menu.setApplicationMenu(menu); 117 | 118 | // open devtools 119 | // window.webContents.openDevTools(); 120 | 121 | console.log("Menubar app is ready."); 122 | }); 123 | 124 | app.on("web-contents-created", (e, contents) => { 125 | if (contents.getType() == "webview") { 126 | // open link with external browser in webview 127 | contents.on("new-window", (e, url) => { 128 | e.preventDefault(); 129 | shell.openExternal(url); 130 | }); 131 | // set context menu in webview 132 | contextMenu({ 133 | window: contents, 134 | }); 135 | 136 | // we can't set the native app menu with "menubar" so need to manually register these events 137 | // register cmd+c/cmd+v events 138 | contents.on("before-input-event", (event, input) => { 139 | const { control, meta, key } = input; 140 | if (!control && !meta) return; 141 | if (key === "c") contents.copy(); 142 | if (key === "v") contents.paste(); 143 | if (key === "a") contents.selectAll(); 144 | if (key === "z") contents.undo(); 145 | if (key === "y") contents.redo(); 146 | if (key === "q") app.quit(); 147 | if (key === "r") contents.reload(); 148 | }); 149 | } 150 | }); 151 | 152 | if (process.platform == "darwin") { 153 | // restore focus to previous app on hiding 154 | mb.on("after-hide", () => { 155 | mb.app.hide(); 156 | }); 157 | } 158 | 159 | // open links in new window 160 | // app.on("web-contents-created", (event, contents) => { 161 | // contents.on("will-navigate", (event, navigationUrl) => { 162 | // event.preventDefault(); 163 | // shell.openExternal(navigationUrl); 164 | // }); 165 | // }); 166 | 167 | // prevent background flickering 168 | app.commandLine.appendSwitch( 169 | "disable-backgrounding-occluded-windows", 170 | "true" 171 | ); 172 | }); 173 | 174 | // Quit when all windows are closed, except on macOS. There, it's common 175 | // for applications and their menu bar to stay active until the user quits 176 | // explicitly with Cmd + Q. 177 | app.on("window-all-closed", () => { 178 | if (process.platform !== "darwin") { 179 | app.quit(); 180 | } 181 | }); 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatgpt-mac", 3 | "productName": "chatgpt-mac", 4 | "version": "0.0.5", 5 | "description": "Menubar app for ChatGPT", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "electron-forge start", 9 | "package": "electron-forge package --arch arm64,x64", 10 | "make": " electron-forge make --arch arm64,x64", 11 | "publish": "electron-forge publish --arch arm64,x64", 12 | "lint": "echo \"No linting configured\"" 13 | }, 14 | "keywords": [ 15 | "chatgpt", 16 | "openai", 17 | "mac" 18 | ], 19 | "license": "MIT", 20 | "dependencies": { 21 | "electron-context-menu": "^3.6.0", 22 | "menubar": "^9.2.3", 23 | "update-electron-app": "^2.0.1" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/sw-yx/chatgpt-mac" 28 | }, 29 | "devDependencies": { 30 | "@electron-forge/cli": "^6.0.4", 31 | "@electron-forge/maker-deb": "^6.0.4", 32 | "@electron-forge/maker-dmg": "^6.0.4", 33 | "@electron-forge/maker-rpm": "^6.0.4", 34 | "@electron-forge/maker-squirrel": "^6.0.4", 35 | "@electron-forge/maker-zip": "^6.0.4", 36 | "@electron-forge/publisher-github": "^6.0.4", 37 | "dotenv": "^16.0.3", 38 | "electron": "^21.0.0", 39 | "electron-squirrel-startup": "^1.0.0" 40 | } 41 | } 42 | --------------------------------------------------------------------------------