Skip to content

Repository files navigation

GitHub Menu Bar

A macOS menu bar app for signing in to GitHub and creating new empty repositories from the menu bar — so you can hand a fresh repo URL to an AI agent (or a colleague) without opening github.com.

  • Menu-bar-only app (LSUIElement = true — no Dock icon).
  • Two sign-in paths: Personal Access Token (PAT) and OAuth (your own GitHub OAuth App, PKCE, ASWebAuthenticationSession).
  • Tokens are stored in the Keychain (never UserDefaults).
  • Create a repo (user or org owner, private by default, optional README), copy the URL to the clipboard, get a macOS notification, and open it in your browser.

Requirements

  • macOS 15.0 or later
  • Xcode 27 / Swift 6.4 toolchain
  • xcodegen (only needed to regenerate the project from project.yml; the generated .xcodeproj is committed so a plain xcodebuild works without xcodegen)

Build & run

# From the repo root:
xcodegen generate          # regenerate GitHubMenuBar.xcodeproj (optional)
xcodebuild -scheme GitHubMenuBar -configuration Debug build
open "$(xcodebuild -scheme GitHubMenuBar -showBuildSettings 2>/dev/null \
  | awk '/BUILT_PRODUCTS_DIR/{print $3}')/GitHubMenuBar.app"

Or open GitHubMenuBar.xcodeproj in Xcode and press ⌘R.

The app runs as a menu-bar item (a GitHub-mark SF Symbol). Click it to open the menu.

Tests

xcodebuild test -scheme GitHubMenuBar

Tests use a stubbing URLProtocol and a mock Keychain — no real network or Keychain access is required. (Two Keychain tests do hit the real Keychain in a per-run-unique service; they clean up after themselves.)

Sign in with a Personal Access Token (PAT)

  1. Create a PAT at https://github.com/settings/tokens (classic) or https://github.com/settings/personal-access-tokens (fine-grained).
  2. Required scopes:
    • repo — to list orgs and create repositories.
    • For fine-grained tokens: grant Repository administration: Read and write and Administration: Read on the account/org, plus Organization administration: Read if you want to create repos under orgs.
  3. Open the menu → Settings… → paste the token into the secure field → Save Token. The token is validated via GET /user and stored in the Keychain under your GitHub username.

Sign in with OAuth (your own OAuth App)

  1. Create an OAuth App at https://github.com/settings/developersNew OAuth App.

  2. Set the Authorization callback URL to:

    githubmenubar://oauth/callback
    

    (This exact value is shown in the Settings window with a Copy button.)

  3. Open the menu → Settings…OAuth App section.

  4. Enter your Client ID (and Client Secret, if your app has one).

  5. Click Save Config, then Sign in with GitHub. The app opens the GitHub authorize page via ASWebAuthenticationSession; after you approve, the callback is intercepted and the code is exchanged for an access token using PKCE (S256). The token is validated via GET /user and stored in the Keychain exactly like a PAT.

The OAuth App config (Client ID/Secret) is persisted in a separate Keychain entry (service com.github-menubar.oauth) — never in UserDefaults.

Create a repository

  1. Sign in (PAT or OAuth).
  2. Menu → New Repository… (⌘N).
  3. Pick an owner (your account or one of your orgs), enter a name (validated against GitHub's rules: alphanumeric plus -, _, .; no consecutive special characters; ≤100 chars), an optional description, and choose Private (default on) and Add README (default off — an empty repo is the point).
  4. Press Create (⏎).
  5. On success the new repo URL is copied to the clipboard, a macOS notification is posted, and the banner offers Open in Browser and Copy URL Again. On failure the GitHub error message is shown inline.

Sign out

Menu → Sign Out clears the stored token from the Keychain.

Architecture

GitHubMenuBar/
  App/            App entry, AppDelegate (NSStatusItem), menu construction
  Auth/           AuthManager (@MainActor @Observable), KeychainStore,
                  PKCE, OAuthConfig/OAuthConfigStore, OAuthCoordinator
  GitHub/         GitHubClient (actor), Codable models, endpoints
  UI/             NewRepoWindow, SettingsWindow, WindowHost, WindowEnvironment
  Utilities/      Clipboard, Notifier, RepoNameValidator
GitHubMenuBarTests/  unit tests (GitHubClient, KeychainStore, AuthManager,
                     RepoNameValidator, OAuth/PKCE, scaffold)
  • MV with @Observable: AuthManager is @MainActor @Observable; SwiftUI views and the menu observe it directly.
  • Networking lives in the GitHubClient actor (URLSession + async/await, no third-party deps). The OAuth token exchange uses a form-encoded POST to /login/oauth/access_token.
  • Secrets are Keychain-only (kSecClassGenericPassword, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly).
  • Swift 6 strict concurrency: blocking SecItem* calls run off the MainActor via Task.detached; the OAuth browser step is abstracted behind an OAuthCoordinating protocol so tests can stub it.

Project generation

The Xcode project is generated from project.yml with xcodegen. After structural changes (new files/targets), regenerate:

xcodegen generate

The generated GitHubMenuBar.xcodeproj is committed, so contributors without xcodegen can still build and test.

About

create new repos easily for your agents.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages