Rename app to cmuxterm
This commit is contained in:
parent
6d3bbb1577
commit
3877dc2d98
20 changed files with 97 additions and 94 deletions
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
|
|
@ -101,9 +101,9 @@ jobs:
|
|||
echo "Missing notarization secrets (APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID)" >&2
|
||||
exit 1
|
||||
fi
|
||||
APP_PATH="build/Build/Products/Release/cmux.app"
|
||||
ZIP_SUBMIT="cmux-notary.zip"
|
||||
DMG_RELEASE="cmux-macos.dmg"
|
||||
APP_PATH="build/Build/Products/Release/cmuxterm.app"
|
||||
ZIP_SUBMIT="cmuxterm-notary.zip"
|
||||
DMG_RELEASE="cmuxterm-macos.dmg"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ZIP_SUBMIT"
|
||||
xcrun notarytool submit "$ZIP_SUBMIT" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --wait
|
||||
xcrun stapler staple "$APP_PATH"
|
||||
|
|
@ -111,9 +111,9 @@ jobs:
|
|||
spctl -a -vv --type execute "$APP_PATH"
|
||||
rm -f "$ZIP_SUBMIT"
|
||||
STAGING_DIR="$(mktemp -d)"
|
||||
cp -R "$APP_PATH" "$STAGING_DIR/cmux.app"
|
||||
cp -R "$APP_PATH" "$STAGING_DIR/cmuxterm.app"
|
||||
ln -s /Applications "$STAGING_DIR/Applications"
|
||||
hdiutil create -volname "cmux" -srcfolder "$STAGING_DIR" -ov -format UDZO "$DMG_RELEASE"
|
||||
hdiutil create -volname "cmuxterm" -srcfolder "$STAGING_DIR" -ov -format UDZO "$DMG_RELEASE"
|
||||
rm -rf "$STAGING_DIR"
|
||||
xcrun notarytool submit "$DMG_RELEASE" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --wait
|
||||
xcrun stapler staple "$DMG_RELEASE"
|
||||
|
|
@ -127,13 +127,13 @@ jobs:
|
|||
echo "Missing SPARKLE_PRIVATE_KEY secret" >&2
|
||||
exit 1
|
||||
fi
|
||||
./scripts/sparkle_generate_appcast.sh cmux-macos.dmg "$GITHUB_REF_NAME" appcast.xml
|
||||
./scripts/sparkle_generate_appcast.sh cmuxterm-macos.dmg "$GITHUB_REF_NAME" appcast.xml
|
||||
|
||||
- name: Upload release asset
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
cmux-macos.dmg
|
||||
cmuxterm-macos.dmg
|
||||
appcast.xml
|
||||
generate_release_notes: true
|
||||
|
||||
|
|
|
|||
24
CLAUDE.md
24
CLAUDE.md
|
|
@ -1,4 +1,4 @@
|
|||
# GhosttyTabs agent notes
|
||||
# cmuxterm agent notes
|
||||
|
||||
## Local dev
|
||||
|
||||
|
|
@ -11,17 +11,19 @@ xcodebuild -project GhosttyTabs.xcodeproj -scheme cmux -configuration Debug -des
|
|||
`reload` = kill and launch the Debug app only:
|
||||
|
||||
```bash
|
||||
pkill -x "cmux DEV" || true
|
||||
sleep 0.2
|
||||
open /Users/lawrencechen/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Debug/cmux\ DEV.app
|
||||
./scripts/reload.sh
|
||||
```
|
||||
|
||||
`reload-prod` = kill and launch the Release app:
|
||||
`reloadp` = kill and launch the Release app:
|
||||
|
||||
```bash
|
||||
pkill -x cmux || true
|
||||
sleep 0.2
|
||||
open /Users/lawrencechen/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Release/cmux.app
|
||||
./scripts/reloadp.sh
|
||||
```
|
||||
|
||||
`reload2` = reload both Debug and Release:
|
||||
|
||||
```bash
|
||||
./scripts/reload2.sh
|
||||
```
|
||||
|
||||
## Release
|
||||
|
|
@ -31,12 +33,12 @@ Tagging a version triggers the GitHub Actions release workflow and uploads the n
|
|||
```bash
|
||||
git tag vX.Y.Z
|
||||
git push origin vX.Y.Z
|
||||
gh run watch --repo manaflow-ai/GhosttyTabs
|
||||
gh run watch --repo manaflow-ai/cmuxterm
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Requires GitHub secrets: `APPLE_CERTIFICATE_BASE64`, `APPLE_CERTIFICATE_PASSWORD`,
|
||||
`APPLE_SIGNING_IDENTITY`, `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, `APPLE_TEAM_ID`.
|
||||
- The release asset is `cmux-macos.dmg` attached to the tag.
|
||||
- README download button points to `releases/latest/download/cmux-macos.dmg`.
|
||||
- The release asset is `cmuxterm-macos.dmg` attached to the tag.
|
||||
- README download button points to `releases/latest/download/cmuxterm-macos.dmg`.
|
||||
- Versioning: bump the minor version for updates unless explicitly asked otherwise.
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
A5001000 /* cmux.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cmux.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A5001000 /* cmuxterm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cmuxterm.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7E7E6EF344A568AC7FEE3715 /* GhosttyTabsUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GhosttyTabsUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A5001011 /* cmuxApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = cmuxApp.swift; sourceTree = "<group>"; };
|
||||
A5001012 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -196,7 +196,7 @@
|
|||
A5001042 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A5001000 /* cmux.app */,
|
||||
A5001000 /* cmuxterm.app */,
|
||||
7E7E6EF344A568AC7FEE3715 /* GhosttyTabsUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
|
|
@ -232,7 +232,7 @@
|
|||
);
|
||||
name = GhosttyTabs;
|
||||
productName = GhosttyTabs;
|
||||
productReference = A5001000 /* cmux.app */;
|
||||
productReference = A5001000 /* cmuxterm.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
CB450DF0F0B3839599082C4D /* GhosttyTabsUITests */ = {
|
||||
|
|
@ -406,23 +406,23 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 6;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "cmux DEV";
|
||||
INFOPLIST_KEY_CFBundleName = "cmux DEV";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "cmuxterm DEV";
|
||||
INFOPLIST_KEY_CFBundleName = "cmuxterm DEV";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainStoryboardFile = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
INFOPLIST_KEY_SUFeedURL = "https://github.com/manaflow-ai/GhosttyTabs/releases/latest/download/appcast.xml";
|
||||
INFOPLIST_KEY_SUFeedURL = "https://github.com/manaflow-ai/cmuxterm/releases/latest/download/appcast.xml";
|
||||
INFOPLIST_KEY_SUPublicEDKey = "$(SPARKLE_PUBLIC_KEY)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-lc++",
|
||||
"-framework",
|
||||
|
|
@ -436,8 +436,8 @@
|
|||
"-framework",
|
||||
Carbon,
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmux.app.debug;
|
||||
PRODUCT_NAME = "cmux DEV";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.app.debug;
|
||||
PRODUCT_NAME = "cmuxterm DEV";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cmux-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
@ -451,23 +451,23 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 6;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = cmux;
|
||||
INFOPLIST_KEY_CFBundleName = cmux;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = cmuxterm;
|
||||
INFOPLIST_KEY_CFBundleName = cmuxterm;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INFOPLIST_KEY_NSMainStoryboardFile = "";
|
||||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
INFOPLIST_KEY_SUFeedURL = "https://github.com/manaflow-ai/GhosttyTabs/releases/latest/download/appcast.xml";
|
||||
INFOPLIST_KEY_SUFeedURL = "https://github.com/manaflow-ai/cmuxterm/releases/latest/download/appcast.xml";
|
||||
INFOPLIST_KEY_SUPublicEDKey = "$(SPARKLE_PUBLIC_KEY)";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"-lc++",
|
||||
"-framework",
|
||||
|
|
@ -482,8 +482,8 @@
|
|||
Carbon,
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmux.app;
|
||||
PRODUCT_NAME = cmux;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.app;
|
||||
PRODUCT_NAME = cmuxterm;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cmux-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
@ -494,12 +494,12 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 6;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmux.appuitests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.appuitests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
@ -511,12 +511,12 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 6;
|
||||
CURRENT_PROJECT_VERSION = 7;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 1.1.0;
|
||||
MARKETING_VERSION = 1.2.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmux.appuitests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cmuxterm.appuitests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = GhosttyTabs;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry buildForTesting="YES" buildForRunning="YES" buildForProfiling="YES" buildForArchiving="YES" buildForAnalyzing="YES">
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmux.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmuxterm.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
|
|
@ -14,17 +14,17 @@
|
|||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmux.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmuxterm.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction buildConfiguration="Release" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" useCustomWorkingDirectory="NO" ignoresPersistentStateOnLaunch="NO" debugDocumentVersioning="YES" allowLocationSimulation="YES">
|
||||
<BuildableProductRunnable runnableDebuggingMode="0">
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmux.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmuxterm.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction buildConfiguration="Release" shouldUseLaunchSchemeArgsEnv="YES" savedToolIdentifier="" useCustomWorkingDirectory="NO" debugDocumentVersioning="YES">
|
||||
<BuildableProductRunnable runnableDebuggingMode="0">
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmux.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
<BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A5001050" BuildableName="cmuxterm.app" BlueprintName="GhosttyTabs" ReferencedContainer="container:GhosttyTabs.xcodeproj"/>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction buildConfiguration="Release"/>
|
||||
|
|
|
|||
12
README.md
12
README.md
|
|
@ -1,22 +1,22 @@
|
|||
# cmux
|
||||
# cmuxterm
|
||||
|
||||
Vertical tabs for Ghostty on macOS, built on libghostty.
|
||||
|
||||
[](releases/latest/download/cmux-macos.dmg)
|
||||
[](releases/latest/download/cmuxterm-macos.dmg)
|
||||
|
||||
## Releases
|
||||
|
||||
Tag a version like `v0.1.0` and push it to trigger the GitHub Actions release workflow.
|
||||
The workflow builds `GhosttyKit.xcframework`, builds the Release app, signs, notarizes,
|
||||
staples, and uploads `cmux-macos.dmg` to the release.
|
||||
staples, and uploads `cmuxterm-macos.dmg` to the release.
|
||||
|
||||
## Auto updates
|
||||
|
||||
cmux uses Sparkle with the same update UI flow as upstream Ghostty. The app looks for
|
||||
cmuxterm uses Sparkle with the same update UI flow as upstream Ghostty. The app looks for
|
||||
an appcast at:
|
||||
|
||||
```
|
||||
https://github.com/manaflow-ai/GhosttyTabs/releases/latest/download/appcast.xml
|
||||
https://github.com/manaflow-ai/cmuxterm/releases/latest/download/appcast.xml
|
||||
```
|
||||
|
||||
To sign updates, set these secrets for release builds:
|
||||
|
|
@ -36,7 +36,7 @@ to `.env`), run:
|
|||
For manual appcast generation (uses `SPARKLE_PRIVATE_KEY`):
|
||||
|
||||
```bash
|
||||
SPARKLE_PRIVATE_KEY=... ./scripts/sparkle_generate_appcast.sh cmux-macos.dmg vX.Y.Z appcast.xml
|
||||
SPARKLE_PRIVATE_KEY=... ./scripts/sparkle_generate_appcast.sh cmuxterm-macos.dmg vX.Y.Z appcast.xml
|
||||
```
|
||||
|
||||
### Required GitHub secrets
|
||||
|
|
|
|||
|
|
@ -422,13 +422,13 @@ class TabManager: ObservableObject {
|
|||
}
|
||||
|
||||
private func windowTitle(for tab: Tab?) -> String {
|
||||
guard let tab else { return "cmux" }
|
||||
guard let tab else { return "cmuxterm" }
|
||||
let trimmedTitle = tab.title.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if !trimmedTitle.isEmpty {
|
||||
return trimmedTitle
|
||||
}
|
||||
let trimmedDirectory = tab.currentDirectory.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return trimmedDirectory.isEmpty ? "cmux" : trimmedDirectory
|
||||
return trimmedDirectory.isEmpty ? "cmuxterm" : trimmedDirectory
|
||||
}
|
||||
|
||||
func focusTab(_ tabId: UUID, surfaceId: UUID? = nil) {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ struct TerminalNotification: Identifiable, Hashable {
|
|||
final class TerminalNotificationStore: ObservableObject {
|
||||
static let shared = TerminalNotificationStore()
|
||||
|
||||
static let categoryIdentifier = "com.cmux.app.userNotification"
|
||||
static let actionShowIdentifier = "com.cmux.app.userNotification.show"
|
||||
static let categoryIdentifier = "com.cmuxterm.app.userNotification"
|
||||
static let actionShowIdentifier = "com.cmuxterm.app.userNotification.show"
|
||||
|
||||
@Published private(set) var notifications: [TerminalNotification] = []
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ final class TerminalNotificationStore: ObservableObject {
|
|||
let content = UNMutableNotificationContent()
|
||||
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
|
||||
?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
|
||||
?? "cmux"
|
||||
?? "cmuxterm"
|
||||
content.title = appName
|
||||
content.subtitle = notification.title
|
||||
content.body = notification.body
|
||||
|
|
@ -173,8 +173,8 @@ final class TerminalNotificationStore: ObservableObject {
|
|||
self.hasPromptedForSettings = true
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.messageText = "Enable Notifications for cmux"
|
||||
alert.informativeText = "Notifications are disabled for cmux. Enable them in System Settings to see alerts."
|
||||
alert.messageText = "Enable Notifications for cmuxterm"
|
||||
alert.informativeText = "Notifications are disabled for cmuxterm. Enable them in System Settings to see alerts."
|
||||
alert.addButton(withTitle: "Open Settings")
|
||||
alert.addButton(withTitle: "Not Now")
|
||||
let response = alert.runModal()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Sparkle
|
|||
import Cocoa
|
||||
import Combine
|
||||
|
||||
/// Controller for managing Sparkle updates in cmux.
|
||||
/// Controller for managing Sparkle updates in cmuxterm.
|
||||
class UpdateController {
|
||||
private(set) var updater: SPUUpdater
|
||||
private let userDriver: UpdateDriver
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Cocoa
|
|||
extension UpdateDriver: SPUUpdaterDelegate {
|
||||
func feedURLString(for updater: SPUUpdater) -> String? {
|
||||
let infoURL = Bundle.main.object(forInfoDictionaryKey: "SUFeedURL") as? String
|
||||
let fallback = "https://github.com/manaflow-ai/GhosttyTabs/releases/latest/download/appcast.xml"
|
||||
let fallback = "https://github.com/manaflow-ai/cmuxterm/releases/latest/download/appcast.xml"
|
||||
let feedURLString = (infoURL?.isEmpty == false) ? infoURL! : fallback
|
||||
recordFeedURLString(feedURLString, usedFallback: feedURLString == fallback)
|
||||
return feedURLString
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class UpdateDriver: NSObject, SPUUserDriver {
|
|||
}
|
||||
|
||||
func showUpdateReleaseNotes(with downloadData: SPUDownloadData) {
|
||||
// cmux uses Sparkle's UI for release notes links instead.
|
||||
// cmuxterm uses Sparkle's UI for release notes links instead.
|
||||
}
|
||||
|
||||
func showUpdateReleaseNotesFailedToDownloadWithError(_ error: any Error) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import AppKit
|
|||
final class UpdateLogStore {
|
||||
static let shared = UpdateLogStore()
|
||||
|
||||
private let queue = DispatchQueue(label: "cmux.update.log")
|
||||
private let queue = DispatchQueue(label: "cmuxterm.update.log")
|
||||
private var entries: [String] = []
|
||||
private let maxEntries = 200
|
||||
private let logURL: URL
|
||||
|
|
@ -15,7 +15,7 @@ final class UpdateLogStore {
|
|||
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
||||
let logsDir = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first
|
||||
?? FileManager.default.temporaryDirectory
|
||||
logURL = logsDir.appendingPathComponent("Logs/cmux-update.log")
|
||||
logURL = logsDir.appendingPathComponent("Logs/cmuxterm-update.log")
|
||||
ensureLogFile()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ fileprivate struct PermissionRequestView: View {
|
|||
Text("Enable automatic updates?")
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
|
||||
Text("cmux can automatically check for updates in the background.")
|
||||
Text("cmuxterm can automatically check for updates in the background.")
|
||||
.font(.system(size: 11))
|
||||
.foregroundColor(.secondary)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ enum UpdateTestSupport {
|
|||
|
||||
private static func makeAppcastItem(displayVersion: String) -> SUAppcastItem? {
|
||||
let enclosure: [String: Any] = [
|
||||
"url": "https://example.com/cmux.zip",
|
||||
"url": "https://example.com/cmuxterm.zip",
|
||||
"length": "1024",
|
||||
"sparkle:version": displayVersion,
|
||||
"sparkle:shortVersionString": displayVersion,
|
||||
]
|
||||
let dict: [String: Any] = [
|
||||
"title": "cmux \(displayVersion)",
|
||||
"title": "cmuxterm \(displayVersion)",
|
||||
"enclosure": enclosure,
|
||||
]
|
||||
return SUAppcastItem(dictionary: dict)
|
||||
|
|
|
|||
|
|
@ -216,13 +216,13 @@ class UpdateViewModel: ObservableObject {
|
|||
if let networkError = networkError(from: nsError) {
|
||||
switch networkError.code {
|
||||
case NSURLErrorNotConnectedToInternet:
|
||||
return "cmux can’t reach the update server. Check your internet connection and try again."
|
||||
return "cmuxterm can’t reach the update server. Check your internet connection and try again."
|
||||
case NSURLErrorTimedOut:
|
||||
return "The update server took too long to respond. Try again in a moment."
|
||||
case NSURLErrorCannotFindHost:
|
||||
return "The update server can’t be found. Check your connection or try again later."
|
||||
case NSURLErrorCannotConnectToHost:
|
||||
return "cmux couldn’t connect to the update server. Check your connection or try again later."
|
||||
return "cmuxterm couldn’t connect to the update server. Check your connection or try again later."
|
||||
case NSURLErrorNetworkConnectionLost:
|
||||
return "The network connection was lost while checking for updates. Try again."
|
||||
case NSURLErrorSecureConnectionFailed,
|
||||
|
|
@ -238,7 +238,7 @@ class UpdateViewModel: ObservableObject {
|
|||
if nsError.domain == SUSparkleErrorDomain {
|
||||
switch nsError.code {
|
||||
case 2001:
|
||||
return "cmux couldn’t download the update feed. Check your connection and try again."
|
||||
return "cmuxterm couldn’t download the update feed. Check your connection and try again."
|
||||
case 1000, 1002:
|
||||
return "The update feed could not be read. Please try again later."
|
||||
case 4:
|
||||
|
|
@ -248,7 +248,7 @@ class UpdateViewModel: ObservableObject {
|
|||
case 1, 2, 3001, 3002:
|
||||
return "The update’s signature could not be verified. Please try again later."
|
||||
case 1003, 1005:
|
||||
return "Move cmux into Applications and relaunch to enable updates."
|
||||
return "Move cmuxterm into Applications and relaunch to enable updates."
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
@ -437,7 +437,7 @@ enum UpdateState: Equatable {
|
|||
|
||||
if let semver = Self.extractSemanticVersion(from: version) {
|
||||
let tag = semver.hasPrefix("v") ? semver : "v\(semver)"
|
||||
if let url = URL(string: "https://github.com/manaflow-ai/GhosttyTabs/releases/tag/\(tag)") {
|
||||
if let url = URL(string: "https://github.com/manaflow-ai/cmuxterm/releases/tag/\(tag)") {
|
||||
self = .tagged(url)
|
||||
return
|
||||
}
|
||||
|
|
@ -447,7 +447,7 @@ enum UpdateState: Equatable {
|
|||
return nil
|
||||
}
|
||||
|
||||
if let url = URL(string: "https://github.com/manaflow-ai/GhosttyTabs/commit/\(newHash)") {
|
||||
if let url = URL(string: "https://github.com/manaflow-ai/cmuxterm/commit/\(newHash)") {
|
||||
self = .commit(url)
|
||||
} else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ struct cmuxApp: App {
|
|||
.windowToolbarStyle(.automatic)
|
||||
.commands {
|
||||
CommandGroup(replacing: .appInfo) {
|
||||
Button("About cmux") {
|
||||
Button("About cmuxterm") {
|
||||
showAboutPanel()
|
||||
}
|
||||
Divider()
|
||||
|
|
@ -130,7 +130,7 @@ struct cmuxApp: App {
|
|||
let bundle = Bundle.main
|
||||
let appName = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
|
||||
?? bundle.object(forInfoDictionaryKey: "CFBundleName") as? String
|
||||
?? "cmux"
|
||||
?? "cmuxterm"
|
||||
let version = bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "1.0"
|
||||
let build = bundle.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "1"
|
||||
NSApp.orderFrontStandardAboutPanel(options: [
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
pkill -x "cmux DEV" || true
|
||||
xcodebuild -project GhosttyTabs.xcodeproj -scheme cmux -configuration Debug -destination 'platform=macOS' build
|
||||
pkill -x "cmuxterm DEV" || true
|
||||
sleep 0.2
|
||||
open /Users/lawrencechen/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Debug/cmux\ DEV.app
|
||||
open /Users/lawrencechen/Library/Developer/Xcode/DerivedData/GhosttyTabs-cbjivvtpirygxbbgqlpdpiiyjnwh/Build/Products/Debug/cmuxterm\ DEV.app
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ if [[ -z "${SPARKLE_PRIVATE_KEY:-}" ]]; then
|
|||
fi
|
||||
|
||||
SPARKLE_VERSION="${SPARKLE_VERSION:-2.8.1}"
|
||||
DOWNLOAD_URL_PREFIX="${DOWNLOAD_URL_PREFIX:-https://github.com/manaflow-ai/GhosttyTabs/releases/download/$TAG/}"
|
||||
RELEASE_NOTES_URL="${RELEASE_NOTES_URL:-https://github.com/manaflow-ai/GhosttyTabs/releases/tag/$TAG}"
|
||||
DOWNLOAD_URL_PREFIX="${DOWNLOAD_URL_PREFIX:-https://github.com/manaflow-ai/cmuxterm/releases/download/$TAG/}"
|
||||
RELEASE_NOTES_URL="${RELEASE_NOTES_URL:-https://github.com/manaflow-ai/cmuxterm/releases/tag/$TAG}"
|
||||
|
||||
work_dir="$(mktemp -d)"
|
||||
cleanup() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
SPARKLE_VERSION="${SPARKLE_VERSION:-2.8.1}"
|
||||
SPARKLE_KEYCHAIN_ACCOUNT="${SPARKLE_KEYCHAIN_ACCOUNT:-cmux}"
|
||||
SPARKLE_KEYCHAIN_ACCOUNT="${SPARKLE_KEYCHAIN_ACCOUNT:-cmuxterm}"
|
||||
SPARKLE_ENV_FILE="${SPARKLE_ENV_FILE:-.env}"
|
||||
|
||||
work_dir="$(mktemp -d)"
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
#!/bin/bash
|
||||
# Test script that sends keystrokes to cmux via AppleScript
|
||||
# Test script that sends keystrokes to cmuxterm via AppleScript
|
||||
# This tests the actual keyboard input path through the app
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== cmux Keystroke Test ==="
|
||||
echo "=== cmuxterm Keystroke Test ==="
|
||||
echo ""
|
||||
|
||||
# Check if cmux is running
|
||||
if ! pgrep -x "cmux" > /dev/null; then
|
||||
echo "Error: cmux is not running"
|
||||
echo "Please start cmux first"
|
||||
# Check if cmuxterm is running
|
||||
if ! pgrep -x "cmuxterm" > /dev/null; then
|
||||
echo "Error: cmuxterm is not running"
|
||||
echo "Please start cmuxterm first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "cmux is running"
|
||||
echo "cmuxterm is running"
|
||||
echo ""
|
||||
|
||||
# Activate cmux
|
||||
osascript -e 'tell application "cmux" to activate'
|
||||
# Activate cmuxterm
|
||||
osascript -e 'tell application "cmuxterm" to activate'
|
||||
sleep 0.5
|
||||
|
||||
echo "Test 1: Testing Ctrl+C (SIGINT)"
|
||||
|
|
@ -56,7 +56,7 @@ echo " If cat exited, Ctrl+D is working!"
|
|||
echo ""
|
||||
|
||||
echo "=== Manual Verification Required ==="
|
||||
echo "Please check the cmux window to verify:"
|
||||
echo "Please check the cmuxterm window to verify:"
|
||||
echo " 1. The 'sleep 30' command was interrupted by Ctrl+C"
|
||||
echo " 2. The 'cat' command exited after Ctrl+D"
|
||||
echo ""
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Automated test for ctrl+enter keybind using real keystrokes.
|
||||
|
||||
Requires:
|
||||
- cmux running
|
||||
- cmuxterm running
|
||||
- Accessibility permissions for System Events (osascript)
|
||||
- keybind = ctrl+enter=text:\\r (or \\n/\\x0d) configured in Ghostty config
|
||||
"""
|
||||
|
|
@ -64,7 +64,7 @@ def test_ctrl_enter_keybind(client: cmux) -> tuple[bool, str]:
|
|||
time.sleep(0.3)
|
||||
|
||||
# Make sure the app is focused for keystrokes
|
||||
run_osascript('tell application "cmux" to activate')
|
||||
run_osascript('tell application "cmuxterm" to activate')
|
||||
time.sleep(0.2)
|
||||
|
||||
# Clear any running command
|
||||
|
|
@ -94,14 +94,14 @@ def test_ctrl_enter_keybind(client: cmux) -> tuple[bool, str]:
|
|||
|
||||
def run_tests() -> int:
|
||||
print("=" * 60)
|
||||
print("cmux Ctrl+Enter Keybind Test")
|
||||
print("cmuxterm Ctrl+Enter Keybind Test")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
socket_path = cmux.DEFAULT_SOCKET_PATH
|
||||
if not os.path.exists(socket_path):
|
||||
print(f"Error: Socket not found at {socket_path}")
|
||||
print("Please make sure cmux is running.")
|
||||
print("Please make sure cmuxterm is running.")
|
||||
return 1
|
||||
|
||||
config_path = find_config_with_keybind()
|
||||
|
|
@ -109,7 +109,7 @@ def run_tests() -> int:
|
|||
print("Error: Required keybind not found in Ghostty config.")
|
||||
print("Add a line like:")
|
||||
print(" keybind = ctrl+enter=text:\\r")
|
||||
print("Then restart cmux and re-run this test.")
|
||||
print("Then restart cmuxterm and re-run this test.")
|
||||
return 1
|
||||
|
||||
print(f"Using keybind from: {config_path}")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue