RepoPilotOpen in app →

yagiz/Bagel

a little native network debugging tool for iOS

Mixed

Stale — last commit 2y ago

worst of 4 axes
Use as dependencyMixed

last commit was 2y ago; no tests detected…

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isMixed

last commit was 2y ago; no CI workflows detected

  • 21+ active contributors
  • Apache-2.0 licensed
  • Stale — last commit 2y ago
Show 3 more →
  • Concentrated ownership — top contributor handles 70% of recent commits
  • No CI workflows detected
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days; add a test suite
  • Deploy as-is MixedHealthy if: 1 commit in the last 180 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/yagiz/bagel?axis=fork)](https://repopilot.app/r/yagiz/bagel)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/yagiz/bagel on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: yagiz/Bagel

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/yagiz/Bagel shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 2y ago

  • 21+ active contributors
  • Apache-2.0 licensed
  • ⚠ Stale — last commit 2y ago
  • ⚠ Concentrated ownership — top contributor handles 70% of recent commits
  • ⚠ No CI workflows detected
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live yagiz/Bagel repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/yagiz/Bagel.

What it runs against: a local clone of yagiz/Bagel — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in yagiz/Bagel | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 658 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>yagiz/Bagel</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of yagiz/Bagel. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/yagiz/Bagel.git
#   cd Bagel
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of yagiz/Bagel and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "yagiz/Bagel(\\.git)?\\b" \\
  && ok "origin remote is yagiz/Bagel" \\
  || miss "origin remote is not yagiz/Bagel (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "iOS/Source/Bagel.m" \\
  && ok "iOS/Source/Bagel.m" \\
  || miss "missing critical file: iOS/Source/Bagel.m"
test -f "iOS/Source/BagelURLSessionInjector.m" \\
  && ok "iOS/Source/BagelURLSessionInjector.m" \\
  || miss "missing critical file: iOS/Source/BagelURLSessionInjector.m"
test -f "iOS/Source/BagelURLConnectionInjector.m" \\
  && ok "iOS/Source/BagelURLConnectionInjector.m" \\
  || miss "missing critical file: iOS/Source/BagelURLConnectionInjector.m"
test -f "iOS/Source/BagelRequestCarrier.m" \\
  && ok "iOS/Source/BagelRequestCarrier.m" \\
  || miss "missing critical file: iOS/Source/BagelRequestCarrier.m"
test -f "iOS/Source/BagelController.m" \\
  && ok "iOS/Source/BagelController.m" \\
  || miss "missing critical file: iOS/Source/BagelController.m"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 658 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~628d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/yagiz/Bagel"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Bagel is a native iOS network debugging tool that intercepts HTTP/HTTPS requests from iOS apps without requiring proxy configuration or certificate installation. It uses Bonjour (mDNS) protocol to communicate between an iOS client library and a native macOS desktop app, allowing developers to inspect network traffic in real-time across multiple devices and simulators connected to the same network. Dual-platform monorepo: iOS/Source/ contains the client library (Swift entry points in Bagel.m wrapping Objective-C interceptors and model classes; BagelRequestCarrier.m handles transmission), while mac/ holds the companion desktop app. Both use their own Xcode projects (iOS/Bagel.xcodeproj and mac/Bagel.xcodeproj). Data flows: network requests → BagelURLSessionInjector/BagelURLConnectionInjector → BagelRequestInfo models → BagelRequestCarrier → Bonjour service → macOS UI.

👥Who it's for

iOS developers building apps in Swift/Objective-C who need to debug network requests during development. They want to see detailed request/response information separated by device or simulator without configuring system proxies or installing SSL certificates.

🌱Maturity & risk

Production-ready and actively maintained. Version 1.4.0 is released and available via CocoaPods, Carthage, and SPM. The dual-platform architecture (iOS client + macOS companion) and clean Swift/Objective-C implementation suggest stability, though the single-maintainer structure and sparse commit history visible in the file listing suggest measured development pace rather than rapid iteration.

Low-to-moderate risk: Bagel intercepts URLSession and NSURLConnection traffic at the framework level (via BagelURLSessionInjector.m and BagelURLConnectionInjector.m), which could have subtle side effects on edge-case networking behavior. Single-maintainer repo increases risk if critical bugs emerge. No visible test suite in the file listing is a red flag for regression safety.

Active areas of work

No visible ongoing work apparent from file structure alone. The repo appears stable at version 1.4.0 with support for modern package managers (SPM via Package.swift). No recent breaking changes are evident from the README.

🚀Get running

Clone and build the iOS client:

git clone https://github.com/yagiz/Bagel.git
cd Bagel/iOS
pod install  # if using CocoaPods
xcodebuild -scheme Bagel build

Build the macOS desktop client:

cd ../mac
pod install
xcodebuild -scheme Bagel build

For app integration, add to Podfile: pod 'Bagel', '~> 1.4.0' and call Bagel.start() in code.

Daily commands: For iOS library:

cd iOS
pod install
open Bagel.xcworkspace
# Build scheme 'Bagel' with Cmd+B

For macOS desktop app:

cd mac
pod install
open Bagel.xcworkspace
# Build and run scheme 'Bagel' with Cmd+R

Minimal app integration: import Bagel, call Bagel.start() in DEBUG builds.

🗺️Map of the codebase

  • iOS/Source/Bagel.m — Main entry point for the iOS SDK; initializes network debugging instrumentation and must be integrated into every app using Bagel
  • iOS/Source/BagelURLSessionInjector.m — Core runtime injection mechanism for NSURLSession; intercepts all HTTP requests at the framework level
  • iOS/Source/BagelURLConnectionInjector.m — Legacy URLConnection interception layer; maintains backward compatibility with older iOS networking APIs
  • iOS/Source/BagelRequestCarrier.m — Network carrier that transmits captured request/response data from iOS device to macOS app over local network
  • iOS/Source/BagelController.m — Orchestrates all iOS-side debugging logic: injection, request capture, and transmission coordination
  • mac/Bagel/AppDelegate.swift — Entry point for macOS desktop app; initializes the debugging UI and network listener for incoming device connections
  • iOS/Source/BagelRequestInfo.m — Data model for serializing HTTP request/response details; bridge between captured network data and transmission format

🧩Components & responsibilities

  • BagelURLSessionInjector (Objective-C method swizzling, NSURLSessionDelegate, NSURLSessionTaskDelegate) — Swizzles NSURLSession delegate methods to intercept all modern iOS HTTP requests
    • Failure mode: If swizzling fails (e.g., app uses URLSession in unusual way), requests silently bypass instrumentation
  • BagelRequestCarrier (NSURLConnection (for) — Serializes captured request data and transmits to macOS app via HTTP POST on local network

🛠️How to make changes

Add a new network interception hook

  1. Create a new Injector class (e.g., BagelHTTPClientInjector.m) following the pattern of BagelURLSessionInjector.m (iOS/Source/BagelURLSessionInjector.m)
  2. Implement method swizzling to intercept delegate callbacks or completion handlers (iOS/Source/BagelURLSessionInjector.m)
  3. Call BagelRequestCarrier to transmit captured requests using the same pattern as existing injectors (iOS/Source/BagelRequestCarrier.m)
  4. Register the new injector in BagelController.m during initialization (iOS/Source/BagelController.m)

Add a new request detail field to capture

  1. Add property to BagelRequestInfo.h and implement getter in BagelRequestInfo.m (iOS/Source/BagelRequestInfo.m)
  2. Extract the field in BagelURLSessionInjector.m or BagelURLConnectionInjector.m during interception (iOS/Source/BagelURLSessionInjector.m)
  3. Ensure JSON serialization includes the field by updating BagelUtility.m if custom formatting needed (iOS/Source/BagelUtility.m)
  4. Update macOS UI view models in mac/Bagel/Base/ViewModels to display the new field (mac/Bagel/Base/ViewModels)

Support a new configuration option

  1. Add property to BagelConfiguration.h with getter/setter (iOS/Source/BagelConfiguration.m)
  2. Persist configuration in BagelConfiguration.m (defaults or file storage) (iOS/Source/BagelConfiguration.m)
  3. Use the configuration value in BagelController.m or relevant injector to control behavior (iOS/Source/BagelController.m)

🔧Why these technologies

  • Objective-C for iOS framework (iOS/Source/) — Runtime method swizzling for transparent interception of NSURLSession/NSURLConnection requires low-level Objective-C APIs; enables zero-code-change integration into existing apps
  • Swift for macOS app (mac/Bagel/) — Modern desktop UI development with SwiftUI/Cocoa; cleaner threading and network handling than Objective-C
  • Local HTTP POST for iOS→macOS communication — Avoids proxy/certificate complexity; devices and Mac must be on same LAN but no external infrastructure required
  • CocoaPods + Carthage + SPM distribution — Supports all major iOS dependency managers for flexible integration into various project setups

⚖️Trade-offs already made

  • No proxy—direct method swizzling instead

    • Why: Eliminates certificate pinning and proxy configuration friction for developers
    • Consequence: Only works on same LAN; cannot debug remote device traffic without VPN; requires both app and macOS app running simultaneously
  • Separate iOS framework + macOS app rather than single unified tool

    • Why: iOS cannot run desktop UI; separates concerns and allows independent versioning
    • Consequence: Developer must run two apps; slightly more friction than integrated proxy debugger (e.g., Charles, Proxyman)
  • Synchronous request capture (blocks request briefly)

    • Why: Ensures all data is captured before response completion; simpler implementation
    • Consequence: May add microseconds to request latency; not suitable for ultra-latency-sensitive apps

🚫Non-goals (don't propose these)

  • Does not handle remote/non-LAN debugging (requires VPN for remote devices)
  • Does not intercept system-level networking (e.g., DNS, socket-level calls outside NSURLSession/NSURLConnection)
  • Not a man-in-the-middle proxy (no certificate pinning bypass or request modification/replay)
  • Does not support authentication/access control (runs on local network only; assumes trusted Mac)

🪤Traps & gotchas

  1. Method swizzling in BagelURLSessionInjector and BagelURLConnectionInjector can conflict with other libraries doing similar hooks—test thoroughly with third-party networking libraries. 2) Bonjour requires devices and Mac on same local network; won't work across cellular or VPN boundaries. 3) Captured request/response bodies are stored in memory; large file uploads/downloads could cause memory pressure. 4) The library must be started before any network requests (Bagel.start() should be the first call in AppDelegate or main()); late initialization will miss early network activity. 5) No visible test suite in repo—changes to interceptor logic are high-risk.

🏗️Architecture

💡Concepts to learn

  • Method Swizzling — BagelURLSessionInjector and BagelURLConnectionInjector use Objective-C runtime method swizzling to intercept URLSession and NSURLConnection calls without modifying app code; understanding this is critical to grasping how Bagel non-invasively captures traffic
  • Bonjour (mDNS/Zero-Config Networking) — Bagel uses Bonjour (NSNetService) to advertise and connect the iOS client to the macOS desktop app without manual IP/port configuration; essential to understand why it requires same local network
  • URLSession Delegation & Interception — Modern iOS apps use URLSession with delegate patterns; Bagel's approach of intercepting at the URLSession level (not proxy) requires understanding how delegates and task completion handlers work
  • In-Process Packet Serialization — BagelRequestPacket and BagelRequestInfo serialize captured HTTP data in-memory before transmission; understanding serialization constraints prevents data loss for large payloads
  • NSURLConnection (Legacy API) — BagelURLConnectionInjector maintains backward compatibility with NSURLConnection (deprecated but still used in older codebases); necessary to support legacy iOS projects
  • Local Area Network (LAN) Communication — Bagel is constrained by iOS privacy policies requiring 'Local Network' permission (iOS 14+); understanding privacy implications and permission flow is crucial for deployment
  • Proxyman/Proxyman — Alternative macOS proxy debugger for iOS; uses system proxy rather than in-app interception, so requires cert installation but works across networks
  • CharlesProxy/charles-proxy — Industry-standard HTTP proxy debugger for macOS; intercepts at network level rather than app level, trade-off of more setup vs. no code integration
  • CocoaLumberjack/CocoaLumberjack — Companion logging framework popular in iOS projects; Bagel users often pair it with network request logging for richer debugging context
  • Alamofire/Alamofire — Modern Swift networking library; Bagel should be validated with Alamofire-based apps to ensure URLSession hook doesn't break its abstractions

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add URLSession modern API support (async/await and Combine) to BagelURLSessionInjector.m

The current BagelURLSessionInjector.m only intercepts traditional URLSession completion handler-based requests. It doesn't capture network traffic from modern async/await (iOS 13+) or Combine-based URLSession calls, which are increasingly common in new iOS codebases. This is a critical gap in network debugging coverage that prevents users from seeing traffic from modern networking patterns.

  • [ ] Extend BagelURLSessionInjector.m to hook into URLSessionDataTask lifecycle for async methods
  • [ ] Add support for capturing requests made via URLSession.data(from:delegate:) and URLSession.data(for:delegate:)
  • [ ] Update BagelRequestCarrier.m to handle async/await response patterns
  • [ ] Test with sample async/await URLSession calls in the macOS/iOS demo apps

Implement WebSocket traffic capture in BagelRequestCarrier.m

Bagel currently only captures HTTP/HTTPS traffic (URLSession and URLConnection). Modern iOS apps increasingly use WebSockets for real-time communication. Adding WebSocket interception would make Bagel a more complete network debugging tool by capturing WebSocket handshakes, frames, and closures through URLSessionWebSocketTask.

  • [ ] Create BagelWebSocketInjector.h/.m to intercept URLSessionWebSocketTask
  • [ ] Extend BagelRequestPacket.h to support WebSocket frame types and binary data
  • [ ] Add WebSocket-specific metadata to BagelRequestInfo.m (connection duration, message count, frame types)
  • [ ] Update the macOS viewer to parse and display WebSocket traffic separately

Add comprehensive unit test suite for iOS/Source files with XCTest

The repository currently has no visible unit tests for core network interception classes (BagelURLSessionInjector, BagelURLConnectionInjector, BagelRequestPacket, BagelUtility). This makes it difficult to verify that network traffic capture works correctly across iOS versions and prevents regression detection when refactoring interception logic.

  • [ ] Create iOS/Tests directory with BagelURLSessionInjectorTests.m covering NSURLSession hook injection
  • [ ] Create BagelRequestPacketTests.m to verify request/response serialization and edge cases
  • [ ] Create BagelUtilityTests.m to test header parsing, body truncation, and data transformation utilities
  • [ ] Add test target to iOS/Bagel.xcodeproj/project.pbxproj and configure CI workflow to run tests

🌿Good first issues

  • Add unit tests for BagelRequestInfo.m to verify correct parsing and serialization of HTTP headers, status codes, and request bodies—currently no test files visible in the repo.
  • Document the exact iOS version compatibility matrix (iOS 11.0+? 12.0+?) in README.md, and update Bagel.podspec platform version constraint if it's currently too permissive.
  • Add Swift Package Manager example / integration test in the repo (e.g. Example/ folder with a minimal iOS app using Bagel via SPM) to validate Package.swift works as advertised.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 763aadb — Merge pull request #69 from techinpark/feature/update-readme (yagiz)
  • e84621b — Update Installation versions (techinpark)
  • edbaca5 — Merge pull request #68 from yagiz/release/1.4.0 (yagiz)
  • 0033906 — version++ (yagiz)
  • a03dc3e — Merge pull request #50 from DavidObfuscator/master (yagiz)
  • 7286a28 — Merge pull request #58 from colinhumber/url-cleanup (yagiz)
  • 026efb6 — Merge pull request #67 from fredpi/patch-1 (yagiz)
  • 5cbd269 — Use official release version of CocoaAsyncSocket (fredpi)
  • 8e5704f — Replace escaped URL strings with unescaped slashes (colinhumber)
  • 1e7fd0c — Merge pull request #51 from dcordero/tvOS (yagiz)

🔒Security observations

Bagel is a native iOS network debugging tool with moderate security concerns. The primary risks stem from the nature of the tool itself—it captures and exposes network traffic without apparent authentication mechanisms or encryption. While useful for development, the tool lacks security controls to prevent unauthorized access to sensitive data on shared networks. Key recommendations include implementing network authentication, encrypting transmitted data, sanitizing sensitive information from logs, and securing local data storage. The codebase shows no obvious hardcoded credentials or SQL injection risks, but the lack of defensive measures against network-based attacks and data exposure is concerning for a debugging tool that operates on the same network as production devices.

  • High · Network Debugging Tool Without Authentication — iOS/Source/BagelRequestCarrier.m, iOS/Source/BagelController.m. Bagel is a network debugging tool that operates on the same network without apparent authentication mechanisms. The tool captures and displays network traffic, which could expose sensitive data (API keys, tokens, personal information) if accessed by unauthorized users on the same network. Fix: Implement network-level authentication (e.g., PIN, token-based authentication) for accessing the debugging interface. Ensure only authorized devices can connect to the debugger. Consider adding encryption for data transmission between iOS device and Mac.
  • High · Potential Exposure of Sensitive Network Data — iOS/Source/BagelRequestInfo.m, iOS/Source/BagelRequestPacket.m. The tool logs and transmits network request/response data including headers and potentially body content. Without proper sanitization, this could expose authentication tokens, API keys, session cookies, and other sensitive information through the debugging interface. Fix: Implement data sanitization to mask or redact sensitive headers (Authorization, Cookie, X-API-Key, etc.). Add configurable filters to prevent logging of sensitive request/response data. Ensure all transmitted data is encrypted.
  • Medium · Network Service Discovery Without Validation — iOS/Source/BagelBrowser.m. The tool uses network discovery (Bonjour/mDNS) to find debugging instances on the same network. Without proper validation, a malicious actor on the same network could potentially spoof services or perform man-in-the-middle attacks. Fix: Implement certificate pinning or mutual TLS authentication for connections. Validate the authenticity of discovered services before establishing connections. Use strong encryption for all network communications.
  • Medium · Missing Code Injection Protections in URL Session Injector — iOS/Source/BagelURLSessionInjector.m, iOS/Source/BagelURLConnectionInjector.m. The URL session and connection injectors (BagelURLSessionInjector.m, BagelURLConnectionInjector.m) perform runtime method swizzling to intercept network calls. This approach could be vulnerable to injection attacks if input validation is insufficient. Fix: Validate and sanitize all intercepted request data before logging or transmitting. Implement strict input validation on URLs, headers, and body content. Consider using safer alternatives to method swizzling if available.
  • Medium · User Data Storage Without Encryption — iOS/Source/ (storage-related components). Network logs and request/response data are stored locally without apparent encryption. An attacker with physical access to the device or backup could access sensitive information captured by the debugger. Fix: Implement encryption at rest for all stored network logs using iOS Keychain or Data Protection API. Consider limiting the duration for which logs are retained. Provide options to clear sensitive data.
  • Low · Potential Carrier Delegate Security Consideration — iOS/Source/BagelCarrierDelegate.h. The BagelCarrierDelegate.h component handles carrier-related callbacks. Without proper implementation, this could be exploited if sensitive operations are tied to carrier state changes. Fix: Review carrier delegate implementation to ensure no security-sensitive operations depend solely on carrier state. Implement additional validation layers for any carrier-dependent logic.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · yagiz/Bagel — RepoPilot