Skip to content

Instantly share code, notes, and snippets.

View jubishop's full-sized avatar
🎼
Making a podcast app.

Justin Bishop jubishop

🎼
Making a podcast app.
View GitHub Profile

Plan: Claude Code Remote Control via launchctl

Context

You want a persistent Claude Code remote-control session running in the background on your Mac, accessible from your phone at any time. This avoids needing to manually open a terminal and run claude remote-control every time.

What we'll create

File: ~/Library/LaunchAgents/com.jubi.claude-remote.plist

A LaunchAgent that:

@jubishop
jubishop / CLAUDE.md
Created February 26, 2026 22:06
CLAUDE.md

MCP Usage

  • If discussing Swift, SwiftUI, and iOS: Consult the apple-docs and apple-deep-docs mcps for up to date information.

Repo Guardrails

  • Never create commits or push unless the humans explicitly ask.
  • Assume the working tree may hold user edits; respect them and avoid resets or reverts.
  • Stay sandbox-friendly: ask for elevated access only when instructions require files outside the workspace.

Build & Test

  • Don't actually try to build or test unless the user explicitly asks.

⏺ Summary of All Three Bug Reports

All three reports are from the same user listening over Bluetooth AirPods with episodes played from local cache while the app is backgrounded. Two are related to the same root cause, and one is a distinct bug.


Bug 1 & 3: Audio Repeating (Feb 18 & Feb 21) — !con Error

Both "repeating" reports are manifestations of the known !con error (OSStatus 560164718). The new finding: the audio loops/repeats for ~10-15 seconds before

❯ can you walk me through these xcode tasks

⏺ Sure. Here's the step-by-step walkthrough:

  1. Create the Widget Extension Target

  2. In Xcode, go to File > New > Target

  3. Search for Widget Extension

  4. Name it PodHavenWidget

  5. Uncheck "Include Live Activity" and "Include Configuration App Intent"

⏺ Based on my analysis, none of the changes since commit 1183550f4fbc would have caused this issue. Here's why:

Changes to playback code:

  1. All the PlayManager/PodAVPlayer changes are our debugging additions - These are purely additive (logging, error handling, isCurrentItem check). They don't
    modify any core playback behavior.
  2. The only pre-debugging change was d08b406f which makes pause() async to save position immediately - this doesn't affect playback mechanics.

Other changes:

  • HTMLText parsing improvements
  • Chapter navigation (new feature)
---
Analysis Summary
Based on the logs and code review, I found a reproducible edge case related to the AirPods sleep detection feature.
What Happened (Timeline)
┌─────────────────────┬─────────────────────
## MCP Usage
- If discussing Swift, SwiftUI, and iOS: Consult the apple-docs and apple-deep-docs mcps for up to date information.
## Repo Guardrails
- Never create commits or push unless the humans explicitly ask.
- Assume the working tree may hold user edits; respect them and avoid resets or reverts.
- Stay sandbox-friendly: ask for elevated access only when instructions require files outside the workspace.
## Build & Test
- Do not run builds or tests unless the request is explicit.

• - Event 70a4b966 happened on October 18, 2025 at 15:23:19 UTC on one iPhone18,1 running iOS 26.0.1. The crash is an EXC_BREAKPOINT raised inside CF_IS_OBJC on an AVFoundation worker thread while handling an AVTimebaseObserver callback, and it fired immediately after the system posted mediaServicesWereResetNotification (app was still in foreground).

  • During a media-services reset our playback stack runs handleMediaServicesReset() to tear down and rebuild audio state (PodHaven/Play/PlayManager.swift:470). That calls clearOnDeck() → PodAVPlayer.clear() which re-adds the periodic time observer after relaunching the episode (PodHaven/Play/Utility/ PodAVPlayer.swift:226).
  • In that observer we pass DispatchQueue.global(qos: .utility) to AVPlayer.addPeriodicTimeObserver. Apple explicitly documents that supplying a concurrent queue “isn’t supported and results in undefined behavior”; you must provide a serial queue or nil. citeturn6apple-docs-mcp__get_apple_doc_content0 Combined with
@jubishop
jubishop / llm.md
Created October 14, 2025 21:46
what a world.md

• Here’s the key sequence that can leave podcastList stale if we gate executeTrendingSectionFetch on trendingSection == currentTrendingSection:

  1. User taps a new chip. selectTrendingSection(:) updates currentTrendingSection, clears the list, triggers observeCurrentDisplay(), and kicks off performTrendingSectionFetch(: ).
  2. Before the fetch finishes, the user either jumps to a different trending chip or moves into search. At that instant the list already holds the “new” (possibly empty) dataset for what’s on screen.
  3. The original fetch eventually completes for the old section. If executeTrendingSectionFetch returns false (because the section no longer matches currentTrendingSection), the outer task skips observeCurrentDisplay(), so there’s no new syncPodcastListEntries() call.
  4. When the user returns to the chip whose data just landed, podcastList is still showing whatever collection was left from step 2—because we never updated it after the fetch completed—and it stays that
@jubishop
jubishop / gist:9b001eba30525084f1a35d3e7fbb3c8e
Created September 5, 2025 22:00
Staged changes in PodHaven FakeFileManager
diff --git a/PodHavenTests/Fakes/FakeFileManager.swift b/PodHavenTests/Fakes/FakeFileManager.swift
index 5d001e2..96972bb 100644
--- a/PodHavenTests/Fakes/FakeFileManager.swift
+++ b/PodHavenTests/Fakes/FakeFileManager.swift
@@ -3,115 +3,61 @@
import Foundation
@testable import PodHaven
final class FakeFileManager: FileManageable, @unchecked Sendable {