@wangyaoshen/remux 0.3.8-dev.a8ceb0c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +38 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +28 -0
  4. package/.github/dependabot.yml +33 -0
  5. package/.github/workflows/ci.yml +65 -0
  6. package/.github/workflows/deploy.yml +65 -0
  7. package/.github/workflows/publish.yml +312 -0
  8. package/.github/workflows/release-please.yml +21 -0
  9. package/.gitmodules +3 -0
  10. package/.nvmrc +1 -0
  11. package/.release-please-manifest.json +3 -0
  12. package/CLAUDE.md +104 -0
  13. package/Dockerfile +23 -0
  14. package/LICENSE +21 -0
  15. package/README.md +120 -0
  16. package/apps/ios/Config/signing.xcconfig +4 -0
  17. package/apps/ios/Package.swift +26 -0
  18. package/apps/ios/Remux.xcodeproj/project.pbxproj +477 -0
  19. package/apps/ios/Remux.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  20. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/Contents.json +23 -0
  21. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png +0 -0
  22. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_120x120.png +0 -0
  23. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_152x152.png +0 -0
  24. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_167x167.png +0 -0
  25. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_180x180.png +0 -0
  26. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_20x20.png +0 -0
  27. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_29x29.png +0 -0
  28. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_40x40.png +0 -0
  29. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_58x58.png +0 -0
  30. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_60x60.png +0 -0
  31. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_76x76.png +0 -0
  32. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_80x80.png +0 -0
  33. package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_87x87.png +0 -0
  34. package/apps/ios/Sources/Remux/Assets.xcassets/Contents.json +6 -0
  35. package/apps/ios/Sources/Remux/Extensions/FaceIDManager.swift +29 -0
  36. package/apps/ios/Sources/Remux/Extensions/InspectCache.swift +66 -0
  37. package/apps/ios/Sources/Remux/MainTabView.swift +32 -0
  38. package/apps/ios/Sources/Remux/Remux.entitlements +8 -0
  39. package/apps/ios/Sources/Remux/RemuxiOSApp.swift +14 -0
  40. package/apps/ios/Sources/Remux/RootView.swift +130 -0
  41. package/apps/ios/Sources/Remux/Views/Control/ControlView.swift +102 -0
  42. package/apps/ios/Sources/Remux/Views/Inspect/InspectView.swift +98 -0
  43. package/apps/ios/Sources/Remux/Views/Live/LiveTerminalView.swift +132 -0
  44. package/apps/ios/Sources/Remux/Views/Now/NowView.swift +173 -0
  45. package/apps/ios/Sources/Remux/Views/Onboarding/ManualConnectView.swift +55 -0
  46. package/apps/ios/Sources/Remux/Views/Onboarding/OnboardingView.swift +70 -0
  47. package/apps/ios/Sources/Remux/Views/Onboarding/QRScannerView.swift +92 -0
  48. package/apps/ios/Sources/Remux/Views/Settings/MeView.swift +136 -0
  49. package/apps/macos/Package.swift +37 -0
  50. package/apps/macos/Resources/shell-integration/bash/bash-preexec.sh +382 -0
  51. package/apps/macos/Resources/shell-integration/bash/ghostty.bash +315 -0
  52. package/apps/macos/Resources/shell-integration/elvish/lib/ghostty-integration.elv +191 -0
  53. package/apps/macos/Resources/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish +246 -0
  54. package/apps/macos/Resources/shell-integration/nushell/vendor/autoload/ghostty.nu +110 -0
  55. package/apps/macos/Resources/shell-integration/zsh/.zshenv +61 -0
  56. package/apps/macos/Resources/shell-integration/zsh/ghostty-integration +458 -0
  57. package/apps/macos/Resources/terminfo/67/ghostty +0 -0
  58. package/apps/macos/Resources/terminfo/78/xterm-ghostty +0 -0
  59. package/apps/macos/Sources/Remux/AppDelegate.swift +257 -0
  60. package/apps/macos/Sources/Remux/CrashReporter.swift +210 -0
  61. package/apps/macos/Sources/Remux/FinderIntegration.swift +117 -0
  62. package/apps/macos/Sources/Remux/GhosttyConfig.swift +311 -0
  63. package/apps/macos/Sources/Remux/KeyboardShortcuts/ShortcutAction.swift +115 -0
  64. package/apps/macos/Sources/Remux/KeyboardShortcuts/ShortcutSettingsView.swift +271 -0
  65. package/apps/macos/Sources/Remux/KeyboardShortcuts/StoredShortcut.swift +149 -0
  66. package/apps/macos/Sources/Remux/MainContentView.swift +308 -0
  67. package/apps/macos/Sources/Remux/MenuBarManager.swift +275 -0
  68. package/apps/macos/Sources/Remux/NotificationManager.swift +145 -0
  69. package/apps/macos/Sources/Remux/PortScanner.swift +152 -0
  70. package/apps/macos/Sources/Remux/RemuxApp.swift +13 -0
  71. package/apps/macos/Sources/Remux/SSHDetector.swift +151 -0
  72. package/apps/macos/Sources/Remux/SessionPersistence.swift +226 -0
  73. package/apps/macos/Sources/Remux/SocketController.swift +258 -0
  74. package/apps/macos/Sources/Remux/UpdateChecker.swift +152 -0
  75. package/apps/macos/Sources/Remux/Views/CommandPalette.swift +198 -0
  76. package/apps/macos/Sources/Remux/Views/ConnectionView.swift +84 -0
  77. package/apps/macos/Sources/Remux/Views/InspectView.swift +127 -0
  78. package/apps/macos/Sources/Remux/Views/SettingsView.swift +77 -0
  79. package/apps/macos/Sources/Remux/Views/Sidebar/SidebarView.swift +410 -0
  80. package/apps/macos/Sources/Remux/Views/SplitTree/BrowserPanel.swift +193 -0
  81. package/apps/macos/Sources/Remux/Views/SplitTree/MarkdownPanel.swift +277 -0
  82. package/apps/macos/Sources/Remux/Views/SplitTree/PanelProtocol.swift +14 -0
  83. package/apps/macos/Sources/Remux/Views/SplitTree/SplitNode.swift +149 -0
  84. package/apps/macos/Sources/Remux/Views/SplitTree/SplitView.swift +234 -0
  85. package/apps/macos/Sources/Remux/Views/SplitTree/TerminalPanel.swift +26 -0
  86. package/apps/macos/Sources/Remux/Views/TabBarView.swift +94 -0
  87. package/apps/macos/Sources/Remux/Views/Terminal/ClipboardHelper.swift +101 -0
  88. package/apps/macos/Sources/Remux/Views/Terminal/CopyModeOverlay.swift +325 -0
  89. package/apps/macos/Sources/Remux/Views/Terminal/GhosttyNativeTerminalView.swift +39 -0
  90. package/apps/macos/Sources/Remux/Views/Terminal/GhosttyNativeView.swift +559 -0
  91. package/apps/macos/Sources/Remux/Views/Terminal/SurfaceSearchOverlay.swift +109 -0
  92. package/apps/macos/Sources/Remux/Views/Terminal/TerminalContainerView.swift +95 -0
  93. package/apps/macos/Sources/Remux/Views/Terminal/TerminalRelay.swift +117 -0
  94. package/build.mjs +33 -0
  95. package/native/android/DecodeGoldenPayloads.kt +487 -0
  96. package/native/android/ProtocolModels.kt +188 -0
  97. package/native/ios/DecodeGoldenPayloads.swift +711 -0
  98. package/native/ios/ProtocolModels.swift +200 -0
  99. package/package.json +45 -0
  100. package/packages/RemuxKit/Package.swift +27 -0
  101. package/packages/RemuxKit/Sources/RemuxKit/Device/DeviceManager.swift +27 -0
  102. package/packages/RemuxKit/Sources/RemuxKit/Models/ProtocolModels.swift +206 -0
  103. package/packages/RemuxKit/Sources/RemuxKit/Networking/MessageRouter.swift +108 -0
  104. package/packages/RemuxKit/Sources/RemuxKit/Networking/RemuxConnection.swift +395 -0
  105. package/packages/RemuxKit/Sources/RemuxKit/State/RemuxState.swift +188 -0
  106. package/packages/RemuxKit/Sources/RemuxKit/Storage/KeychainStore.swift +142 -0
  107. package/packages/RemuxKit/Sources/RemuxKit/Terminal/GhosttyBridge.swift +145 -0
  108. package/packages/RemuxKit/Sources/RemuxKit/Terminal/GhosttyTerminalView.swift +35 -0
  109. package/packages/RemuxKit/Sources/RemuxKit/Terminal/Resources/ghostty-terminal.html +91 -0
  110. package/packages/RemuxKit/Tests/RemuxKitTests/ConnectionIntegrationTest.swift +74 -0
  111. package/packages/RemuxKit/Tests/RemuxKitTests/KeychainStoreTests.swift +81 -0
  112. package/packages/RemuxKit/Tests/RemuxKitTests/ProtocolModelsTests.swift +179 -0
  113. package/packages/RemuxKit/Tests/RemuxKitTests/RemuxStateTests.swift +62 -0
  114. package/playwright.config.ts +17 -0
  115. package/pnpm-lock.yaml +1588 -0
  116. package/pty-daemon.js +303 -0
  117. package/release-please-config.json +14 -0
  118. package/scripts/auto-deploy.sh +46 -0
  119. package/scripts/build-dmg.sh +121 -0
  120. package/scripts/build-ghostty-kit.sh +43 -0
  121. package/scripts/check-active-terminology.mjs +132 -0
  122. package/scripts/setup-ci-secrets.sh +80 -0
  123. package/scripts/sync-ghostty-web.sh +28 -0
  124. package/scripts/upload-testflight.sh +100 -0
  125. package/server.js +7074 -0
  126. package/src/adapters/agent-events.ts +246 -0
  127. package/src/adapters/claude-code.ts +158 -0
  128. package/src/adapters/codex.ts +210 -0
  129. package/src/adapters/generic-shell.ts +58 -0
  130. package/src/adapters/index.ts +15 -0
  131. package/src/adapters/registry.ts +99 -0
  132. package/src/adapters/types.ts +41 -0
  133. package/src/auth.ts +174 -0
  134. package/src/e2ee.ts +236 -0
  135. package/src/git-service.ts +168 -0
  136. package/src/message-buffer.ts +137 -0
  137. package/src/pty-daemon.ts +357 -0
  138. package/src/push.ts +127 -0
  139. package/src/renderers.ts +455 -0
  140. package/src/server.ts +2407 -0
  141. package/src/service.ts +226 -0
  142. package/src/session.ts +978 -0
  143. package/src/store.ts +1422 -0
  144. package/src/team.ts +123 -0
  145. package/src/tunnel.ts +126 -0
  146. package/src/types.d.ts +50 -0
  147. package/src/vt-tracker.ts +188 -0
  148. package/src/workspace-head.ts +144 -0
  149. package/src/workspace.ts +153 -0
  150. package/src/ws-handler.ts +1526 -0
  151. package/start.ps1 +83 -0
  152. package/tests/adapters.test.js +171 -0
  153. package/tests/auth.test.js +243 -0
  154. package/tests/codex-adapter.test.js +535 -0
  155. package/tests/durable-stream.test.js +153 -0
  156. package/tests/e2e/app.spec.js +530 -0
  157. package/tests/e2ee.test.js +325 -0
  158. package/tests/message-buffer.test.js +245 -0
  159. package/tests/message-routing.test.js +305 -0
  160. package/tests/pty-daemon.test.js +346 -0
  161. package/tests/push.test.js +281 -0
  162. package/tests/renderers.test.js +391 -0
  163. package/tests/search-shell.test.js +499 -0
  164. package/tests/server.test.js +882 -0
  165. package/tests/service.test.js +267 -0
  166. package/tests/store.test.js +369 -0
  167. package/tests/tunnel.test.js +67 -0
  168. package/tests/workspace-head.test.js +116 -0
  169. package/tests/workspace.test.js +417 -0
  170. package/tsconfig.backend.json +11 -0
  171. package/tsconfig.json +15 -0
  172. package/tui/client/client_test.go +125 -0
  173. package/tui/client/connection.go +342 -0
  174. package/tui/client/host_manager.go +141 -0
  175. package/tui/config/cache.go +81 -0
  176. package/tui/config/config.go +53 -0
  177. package/tui/config/config_test.go +89 -0
  178. package/tui/go.mod +32 -0
  179. package/tui/go.sum +50 -0
  180. package/tui/main.go +261 -0
  181. package/tui/tests/integration_test.go +283 -0
  182. package/tui/ui/model.go +310 -0
  183. package/vitest.config.js +10 -0
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a regression or defect in the current Zellij-era product path
4
+ title: "[bug] "
5
+ labels: ["bug"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ Describe the problem in one paragraph.
12
+
13
+ ## Affected Layer
14
+
15
+ - [ ] backend gateway
16
+ - [ ] zellij integration
17
+ - [ ] web frontend
18
+ - [ ] docs / devex
19
+ - [ ] tests / CI
20
+
21
+ ## Environment
22
+
23
+ - Remux version:
24
+ - Node.js version:
25
+ - Zellij version:
26
+ - Browser / device:
27
+
28
+ ## Reproduction
29
+
30
+ 1.
31
+ 2.
32
+ 3.
33
+
34
+ ## Expected Behavior
35
+
36
+ What should have happened?
37
+
38
+ ## Validation
39
+
40
+ - [ ] `npm run typecheck`
41
+ - [ ] `npm test`
42
+ - [ ] `npm run build`
43
+
44
+ ## Notes
45
+
46
+ Include logs, screenshots, or links when relevant.
47
+
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Feature request
3
+ about: Propose a feature aligned with the current Zellij-era roadmap
4
+ title: "[feature] "
5
+ labels: ["enhancement"]
6
+ assignees: []
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ What capability should Remux gain?
12
+
13
+ ## Scope Bucket
14
+
15
+ - [ ] v1 must ship
16
+ - [ ] v1.5 optional
17
+ - [ ] research / future
18
+
19
+ ## Surfaces
20
+
21
+ - [ ] Inspect
22
+ - [ ] Live
23
+ - [ ] Control
24
+ - [ ] gateway / runtime
25
+ - [ ] docs / devex
26
+
27
+ ## User Outcome
28
+
29
+ What becomes possible or easier after this lands?
30
+
31
+ ## Acceptance
32
+
33
+ How will we know the work is done?
34
+
35
+ ## Risks / Dependencies
36
+
37
+ What could block or complicate this?
38
+
@@ -0,0 +1,28 @@
1
+ ## Summary
2
+
3
+ - what changed
4
+ - why it changed
5
+
6
+ ## Area
7
+
8
+ - [ ] backend gateway
9
+ - [ ] zellij integration
10
+ - [ ] web frontend
11
+ - [ ] docs / devex
12
+ - [ ] tests / CI
13
+
14
+ ## Validation
15
+
16
+ - [ ] `npm run check:terminology`
17
+ - [ ] `npm run typecheck`
18
+ - [ ] `npm test`
19
+ - [ ] `npm run build`
20
+
21
+ ## Acceptance Notes
22
+
23
+ List the user-visible or maintainer-visible acceptance outcomes here.
24
+
25
+ ## Risk
26
+
27
+ Call out migration risk, compatibility risk, or follow-up work.
28
+
@@ -0,0 +1,33 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ day: "monday"
8
+ time: "06:00"
9
+ timezone: "UTC"
10
+ open-pull-requests-limit: 10
11
+ labels:
12
+ - "dependencies"
13
+ commit-message:
14
+ prefix: "deps"
15
+ groups:
16
+ npm-patch-minor:
17
+ update-types:
18
+ - "minor"
19
+ - "patch"
20
+
21
+ - package-ecosystem: "github-actions"
22
+ directory: "/"
23
+ schedule:
24
+ interval: "weekly"
25
+ day: "monday"
26
+ time: "06:30"
27
+ timezone: "UTC"
28
+ open-pull-requests-limit: 5
29
+ labels:
30
+ - "dependencies"
31
+ - "ci"
32
+ commit-message:
33
+ prefix: "deps(ci)"
@@ -0,0 +1,65 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [dev, main]
6
+ pull_request:
7
+ branches: [dev, main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [20, 22]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: pnpm/action-setup@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: ${{ matrix.node-version }}
21
+ cache: pnpm
22
+ - run: pnpm install --frozen-lockfile
23
+ - run: pnpm run build
24
+ - run: pnpm test
25
+
26
+ swift-test:
27
+ runs-on: macos-15
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ with:
31
+ submodules: recursive
32
+ - run: cd packages/RemuxKit && swift build && swift test
33
+
34
+ # ── Dev prerelease: publish @dev tag on push to dev ──
35
+ prerelease:
36
+ if: github.ref == 'refs/heads/dev' && github.event_name == 'push'
37
+ needs: test
38
+ runs-on: ubuntu-latest
39
+ permissions:
40
+ contents: read
41
+ id-token: write
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: pnpm/action-setup@v4
45
+ - uses: actions/setup-node@v4
46
+ with:
47
+ node-version: 22.x
48
+ registry-url: https://registry.npmjs.org
49
+ cache: pnpm
50
+ - run: pnpm install --frozen-lockfile
51
+ - run: pnpm run build
52
+
53
+ - name: Set prerelease version
54
+ run: |
55
+ BASE=$(node -p "require('./package.json').version")
56
+ SHA=$(git rev-parse --short HEAD)
57
+ PREID="${BASE}-dev.${SHA}"
58
+ npm version "$PREID" --no-git-tag-version
59
+ echo "Publishing @wangyaoshen/remux@${PREID} to @dev tag"
60
+
61
+ - name: Publish @dev
62
+ run: pnpm publish --access public --no-git-checks --tag dev
63
+ continue-on-error: true
64
+ env:
65
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,65 @@
1
+ name: Deploy
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ workflow_dispatch:
7
+ inputs:
8
+ branch:
9
+ description: "Branch to deploy (main or dev)"
10
+ required: true
11
+ default: "dev"
12
+ type: choice
13
+ options: [main, dev]
14
+
15
+ jobs:
16
+ deploy:
17
+ runs-on: [self-hosted, remux-deploy]
18
+ timeout-minutes: 10
19
+
20
+ steps:
21
+ - name: Resolve target
22
+ id: target
23
+ run: |
24
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
25
+ BRANCH="${{ inputs.branch }}"
26
+ else
27
+ BRANCH="${GITHUB_REF#refs/heads/}"
28
+ fi
29
+ echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
30
+ if [ "$BRANCH" = "main" ]; then
31
+ echo "app=remux-main" >> "$GITHUB_OUTPUT"
32
+ echo "worktree=$HOME/.remux/runtime-worktrees/runtime-main" >> "$GITHUB_OUTPUT"
33
+ else
34
+ echo "app=remux-dev" >> "$GITHUB_OUTPUT"
35
+ echo "worktree=$HOME/.remux/runtime-worktrees/runtime-dev" >> "$GITHUB_OUTPUT"
36
+ fi
37
+
38
+ - name: Pull latest code
39
+ working-directory: ${{ steps.target.outputs.worktree }}
40
+ run: |
41
+ git fetch origin ${{ steps.target.outputs.branch }}
42
+ git checkout --detach origin/${{ steps.target.outputs.branch }}
43
+
44
+ - name: Install dependencies
45
+ working-directory: ${{ steps.target.outputs.worktree }}
46
+ run: |
47
+ # Use the same Node.js that the launchd service runs (node@20)
48
+ # to ensure native modules (better-sqlite3, node-pty) are compiled
49
+ # for the correct NODE_MODULE_VERSION
50
+ export PATH="/opt/homebrew/opt/node@20/bin:$PATH"
51
+ node --version
52
+ pnpm install
53
+
54
+ - name: Build
55
+ working-directory: ${{ steps.target.outputs.worktree }}
56
+ run: |
57
+ export PATH="/opt/homebrew/opt/node@20/bin:$PATH"
58
+ pnpm run build
59
+
60
+ - name: Restart launchd service
61
+ run: |
62
+ SERVICE="com.remux.${{ steps.target.outputs.branch }}"
63
+ launchctl kickstart -k "gui/$(id -u)/${SERVICE}"
64
+ sleep 2
65
+ launchctl print "gui/$(id -u)/${SERVICE}" 2>&1 | head -5
@@ -0,0 +1,312 @@
1
+ name: Publish
2
+
3
+ # Triggered by release-please creating a tag, or manual tag push
4
+ on:
5
+ push:
6
+ tags: ['v[0-9]+.[0-9]+.[0-9]+']
7
+
8
+ jobs:
9
+ # ── npm publish (@latest) ────────────────────────────
10
+ npm:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ id-token: write
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: pnpm/action-setup@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 22.x
21
+ registry-url: https://registry.npmjs.org
22
+ cache: pnpm
23
+ - run: pnpm install --frozen-lockfile
24
+ - run: pnpm run build
25
+ - run: pnpm test
26
+ - run: pnpm publish --access public --no-git-checks --provenance
27
+ env:
28
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
29
+
30
+ # ── Docker image → ghcr.io ──────────────────────────
31
+ docker:
32
+ runs-on: ubuntu-latest
33
+ permissions:
34
+ contents: read
35
+ packages: write
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - uses: docker/login-action@v3
39
+ with:
40
+ registry: ghcr.io
41
+ username: ${{ github.actor }}
42
+ password: ${{ secrets.GITHUB_TOKEN }}
43
+ - uses: docker/metadata-action@v5
44
+ id: meta
45
+ with:
46
+ images: ghcr.io/${{ github.repository }}
47
+ tags: |
48
+ type=semver,pattern={{version}}
49
+ type=semver,pattern={{major}}.{{minor}}
50
+ type=raw,value=latest
51
+ - uses: docker/build-push-action@v6
52
+ with:
53
+ context: .
54
+ push: true
55
+ tags: ${{ steps.meta.outputs.tags }}
56
+ labels: ${{ steps.meta.outputs.labels }}
57
+
58
+ # ── iOS → TestFlight ─────────────────────────────────
59
+ ios:
60
+ runs-on: macos-15
61
+ permissions:
62
+ contents: read
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ with:
66
+ submodules: recursive
67
+
68
+ - name: Set up signing
69
+ env:
70
+ CERTIFICATES_P12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
71
+ CERTIFICATES_PASSWORD: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
72
+ API_KEY_P8: ${{ secrets.APP_STORE_CONNECT_API_KEY_P8 }}
73
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
74
+ run: |
75
+ # Create temporary keychain
76
+ KEYCHAIN_PATH="$RUNNER_TEMP/signing.keychain-db"
77
+ KEYCHAIN_PASSWORD="$(openssl rand -hex 16)"
78
+ security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
79
+ security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
80
+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
81
+
82
+ # Import certificates
83
+ echo "$CERTIFICATES_P12" | base64 --decode > "$RUNNER_TEMP/certs.p12"
84
+ security import "$RUNNER_TEMP/certs.p12" \
85
+ -P "$CERTIFICATES_PASSWORD" \
86
+ -A -t cert -f pkcs12 \
87
+ -k "$KEYCHAIN_PATH"
88
+ security set-key-partition-list -S apple-tool:,apple:,codesign: \
89
+ -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
90
+
91
+ # Add keychain to search list
92
+ security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
93
+
94
+ # Install Apple WWDR G3 intermediate cert
95
+ curl -sO https://www.apple.com/certificateauthority/AppleWWDRCAG3.cer
96
+ sudo security add-certificates -k /Library/Keychains/System.keychain AppleWWDRCAG3.cer
97
+
98
+ # Set up API key
99
+ mkdir -p ~/.private_keys
100
+ echo "$API_KEY_P8" | base64 --decode > ~/.private_keys/AuthKey_${API_KEY_ID}.p8
101
+
102
+ # Verify
103
+ security find-identity -v -p codesigning "$KEYCHAIN_PATH"
104
+
105
+ - name: Archive
106
+ env:
107
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
108
+ API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
109
+ run: |
110
+ TAG="${GITHUB_REF#refs/tags/}"
111
+ VERSION="${TAG#v}"
112
+
113
+ xcodebuild archive \
114
+ -project apps/ios/Remux.xcodeproj \
115
+ -scheme Remux \
116
+ -destination 'generic/platform=iOS' \
117
+ -archivePath "$RUNNER_TEMP/Remux.xcarchive" \
118
+ -allowProvisioningUpdates \
119
+ -authenticationKeyPath ~/.private_keys/AuthKey_${API_KEY_ID}.p8 \
120
+ -authenticationKeyID "$API_KEY_ID" \
121
+ -authenticationKeyIssuerID "$API_ISSUER_ID" \
122
+ CURRENT_PROJECT_VERSION="$(git rev-list --count HEAD)" \
123
+ MARKETING_VERSION="$VERSION" \
124
+ -quiet
125
+
126
+ - name: Export IPA
127
+ env:
128
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
129
+ API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
130
+ run: |
131
+ cat > "$RUNNER_TEMP/ExportOptions.plist" << 'PLIST'
132
+ <?xml version="1.0" encoding="UTF-8"?>
133
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
134
+ <plist version="1.0">
135
+ <dict>
136
+ <key>method</key>
137
+ <string>app-store-connect</string>
138
+ <key>signingStyle</key>
139
+ <string>automatic</string>
140
+ <key>uploadSymbols</key>
141
+ <true/>
142
+ <key>manageAppVersionAndBuildNumber</key>
143
+ <true/>
144
+ </dict>
145
+ </plist>
146
+ PLIST
147
+
148
+ xcodebuild -exportArchive \
149
+ -archivePath "$RUNNER_TEMP/Remux.xcarchive" \
150
+ -exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist" \
151
+ -exportPath "$RUNNER_TEMP/export" \
152
+ -allowProvisioningUpdates \
153
+ -authenticationKeyPath ~/.private_keys/AuthKey_${API_KEY_ID}.p8 \
154
+ -authenticationKeyID "$API_KEY_ID" \
155
+ -authenticationKeyIssuerID "$API_ISSUER_ID" \
156
+ -quiet
157
+
158
+ - name: Upload to TestFlight
159
+ env:
160
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
161
+ API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
162
+ run: |
163
+ IPA=$(find "$RUNNER_TEMP/export" -name "*.ipa" | head -1)
164
+ xcrun altool --upload-app --type ios \
165
+ --file "$IPA" \
166
+ --apiKey "$API_KEY_ID" \
167
+ --apiIssuer "$API_ISSUER_ID"
168
+
169
+ - name: Set export compliance
170
+ run: |
171
+ pip3 install PyJWT cryptography
172
+ python3 << 'PYEOF'
173
+ import jwt, time, json, urllib.request, os
174
+
175
+ with open(os.path.expanduser(f"~/.private_keys/AuthKey_{os.environ['API_KEY_ID']}.p8")) as f:
176
+ key = f.read()
177
+ token = jwt.encode(
178
+ {"iss": os.environ["API_ISSUER_ID"], "iat": int(time.time()),
179
+ "exp": int(time.time()) + 1200, "aud": "appstoreconnect-v1"},
180
+ key, algorithm="ES256",
181
+ headers={"kid": os.environ["API_KEY_ID"], "typ": "JWT"})
182
+
183
+ # Find latest build
184
+ req = urllib.request.Request(
185
+ f"https://api.appstoreconnect.apple.com/v1/builds?filter[app]=6761521429&sort=-uploadedDate&limit=1",
186
+ headers={"Authorization": f"Bearer {token}"})
187
+ data = json.loads(urllib.request.urlopen(req).read())
188
+ build_id = data["data"][0]["id"]
189
+
190
+ # Set usesNonExemptEncryption = false
191
+ body = json.dumps({"data": {"type": "builds", "id": build_id,
192
+ "attributes": {"usesNonExemptEncryption": False}}}).encode()
193
+ req = urllib.request.Request(
194
+ f"https://api.appstoreconnect.apple.com/v1/builds/{build_id}",
195
+ data=body, method="PATCH",
196
+ headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"})
197
+ urllib.request.urlopen(req)
198
+ print(f"✓ Export compliance set for build {build_id}")
199
+ PYEOF
200
+ env:
201
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
202
+ API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
203
+
204
+ - name: Clean up keychain
205
+ if: always()
206
+ run: security delete-keychain "$RUNNER_TEMP/signing.keychain-db" 2>/dev/null || true
207
+
208
+ # ── macOS app (.dmg) → signed + notarized + GitHub Release ──
209
+ # Runs on self-hosted runner (Mac Mini) which has Developer ID cert installed
210
+ macos:
211
+ runs-on: [self-hosted, remux-deploy]
212
+ permissions:
213
+ contents: write
214
+ steps:
215
+ - uses: actions/checkout@v4
216
+ with:
217
+ submodules: recursive
218
+
219
+ - name: Verify signing identity
220
+ run: |
221
+ security find-identity -v -p codesigning | grep "Developer ID Application"
222
+
223
+ - name: Build GhosttyKit xcframework (if needed)
224
+ run: |
225
+ XCFW="vendor/ghostty/macos/GhosttyKit.xcframework"
226
+ if [ ! -d "$XCFW" ] || [ ! -f "$XCFW/Info.plist" ]; then
227
+ cd vendor/ghostty
228
+ zig build -Demit-xcframework=true -Dxcframework-target=native -Doptimize=ReleaseFast
229
+ fi
230
+
231
+ - name: Build, sign, and notarize DMG
232
+ env:
233
+ API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
234
+ API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
235
+ TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
236
+ run: |
237
+ TAG="${GITHUB_REF#refs/tags/}"
238
+ VERSION="${TAG#v}"
239
+
240
+ # Build .app and DMG
241
+ bash scripts/build-dmg.sh "$VERSION"
242
+
243
+ # Sign with Developer ID + hardened runtime + timestamp
244
+ codesign --force --deep --options runtime --timestamp \
245
+ --sign "Developer ID Application: Yaoshen Wang ($TEAM_ID)" \
246
+ "build/Remux.app"
247
+
248
+ # Rebuild DMG with signed app
249
+ DMG="build/Remux-${VERSION}-arm64.dmg"
250
+ rm -f "$DMG"
251
+ hdiutil create -volname "Remux" \
252
+ -srcfolder build/Remux.app \
253
+ -ov -format UDZO "$DMG"
254
+ codesign --force --timestamp \
255
+ --sign "Developer ID Application: Yaoshen Wang ($TEAM_ID)" "$DMG"
256
+
257
+ # Notarize
258
+ xcrun notarytool submit "$DMG" \
259
+ --key ~/.private_keys/AuthKey_${API_KEY_ID}.p8 \
260
+ --key-id "$API_KEY_ID" \
261
+ --issuer "$API_ISSUER_ID" \
262
+ --wait
263
+
264
+ xcrun stapler staple "$DMG"
265
+
266
+ - name: Upload DMG to GitHub Release
267
+ env:
268
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
269
+ run: |
270
+ TAG="${GITHUB_REF#refs/tags/}"
271
+ VERSION="${TAG#v}"
272
+ DMG="build/Remux-${VERSION}-arm64.dmg"
273
+
274
+ if [ -f "$DMG" ]; then
275
+ gh release upload "$TAG" "$DMG" --clobber
276
+ echo "✓ Uploaded $DMG to release $TAG"
277
+ fi
278
+
279
+ # ── Update Homebrew tap ─────────────────────────────
280
+ homebrew:
281
+ needs: [npm, macos]
282
+ runs-on: ubuntu-latest
283
+ permissions:
284
+ contents: read
285
+ steps:
286
+ - uses: actions/checkout@v4
287
+
288
+ - name: Update Homebrew formula and cask
289
+ env:
290
+ GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
291
+ run: |
292
+ TAG="${GITHUB_REF#refs/tags/}"
293
+ VERSION="${TAG#v}"
294
+
295
+ git clone https://x-access-token:${GH_TOKEN}@github.com/yaoshenwang/homebrew-tap /tmp/tap
296
+ cd /tmp/tap
297
+
298
+ # Update cask version
299
+ sed -i "s/version \".*\"/version \"${VERSION}\"/" Casks/remux-app.rb
300
+
301
+ # Update formula URL
302
+ sed -i "s|remux-.*\.tgz|remux-${VERSION}.tgz|" Formula/remux.rb
303
+
304
+ # Compute sha256 for npm tarball
305
+ NPM_SHA=$(curl -sL "https://registry.npmjs.org/@wangyaoshen/remux/-/remux-${VERSION}.tgz" | sha256sum | cut -d' ' -f1)
306
+ sed -i "s/sha256 \".*\"/sha256 \"${NPM_SHA}\"/" Formula/remux.rb
307
+
308
+ git config user.name "github-actions[bot]"
309
+ git config user.email "github-actions[bot]@users.noreply.github.com"
310
+ git add -A
311
+ git diff --cached --quiet || git commit -m "Update to v${VERSION}"
312
+ git push origin main
@@ -0,0 +1,21 @@
1
+ name: Release Please
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: write
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ release-please:
13
+ runs-on: ubuntu-latest
14
+ outputs:
15
+ release_created: ${{ steps.release.outputs.release_created }}
16
+ tag_name: ${{ steps.release.outputs.tag_name }}
17
+ steps:
18
+ - uses: googleapis/release-please-action@v4
19
+ id: release
20
+ with:
21
+ release-type: node
package/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "vendor/ghostty"]
2
+ path = vendor/ghostty
3
+ url = https://github.com/ghostty-org/ghostty.git
package/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 25
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.3.6"
3
+ }