RepoPilotOpen in app →

venmo/synx

A command-line tool that reorganizes your Xcode project folder to match your Xcode groups

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

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-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 17 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Tests present
  • Stale — last commit 7y ago
  • Concentrated ownership — top contributor handles 74% of recent commits

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 "Healthy" badge

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

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/venmo/synx)](https://repopilot.app/r/venmo/synx)

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/venmo/synx on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: venmo/synx

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/venmo/synx 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

GO — Healthy across all four use cases

  • 17 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 7y ago
  • ⚠ Concentrated ownership — top contributor handles 74% of recent commits

<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 venmo/synx repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/venmo/synx.

What it runs against: a local clone of venmo/synx — 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 venmo/synx | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | 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 ≤ 2517 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>venmo/synx</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of venmo/synx. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/venmo/synx.git
#   cd synx
#
# 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 venmo/synx and re-run."
  exit 2
fi

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

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT 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 "bin/synx" \\
  && ok "bin/synx" \\
  || miss "missing critical file: bin/synx"
test -f "lib/synx.rb" \\
  && ok "lib/synx.rb" \\
  || miss "missing critical file: lib/synx.rb"
test -f "lib/synx/project.rb" \\
  && ok "lib/synx/project.rb" \\
  || miss "missing critical file: lib/synx/project.rb"
test -f "lib/synx/xcodeproj_ext/project/object/pbx_group.rb" \\
  && ok "lib/synx/xcodeproj_ext/project/object/pbx_group.rb" \\
  || miss "missing critical file: lib/synx/xcodeproj_ext/project/object/pbx_group.rb"
test -f "lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb" \\
  && ok "lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb" \\
  || miss "missing critical file: lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2517 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2487d)"
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/venmo/synx"
  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

Synx is a Ruby CLI tool that automatically reorganizes your macOS file system directory structure to match the logical group hierarchy you've defined in Xcode's project navigator. It reads the .pbxproj file, analyzes group nesting, and moves/creates folders on disk to eliminate the common disconnect between Xcode's virtual groups and actual file layout—solving the problem of 'my Xcode groups say /UI/Buttons but files are scattered at the root'. Single-package CLI tool: lib/synx.rb is the entry point; lib/synx/project.rb orchestrates the sync logic; lib/synx/xcodeproj_ext/ monkeypatches the xcodeproj gem's PBXGroup, PBXFileReference, and related classes to add syncing methods; bin/synx is the executable wrapper; spec/dummy/ contains a full test Xcode project with nested groups and files.

👥Who it's for

iOS and macOS developers who maintain Xcode projects and want to keep their file system organization synchronized with their Xcode group structure. Typically used by teams working on codebases where this mismatch has accumulated over time.

🌱Maturity & risk

Moderately mature and stable. The project has a Travis CI setup, tagged releases on Rubygems (indicated by the Gem Version badge), and a test suite under spec/dummy/ with a full dummy Xcode project. However, there are no visible recent commit dates in the provided data, and the codebase is relatively small (~31KB Ruby), suggesting it may not be under active development but is likely production-ready for its narrow use case.

Low-to-moderate risk. The main risk is that this tool performs destructive file system operations (moving/deleting files via the --prune option), so incorrect logic could corrupt a project—though the README explicitly warns users to back up via source control first. Single-file extensions to the xcodeproj gem (lib/synx/xcodeproj_ext/) mean changes in the xcodeproj dependency could break parsing. No visible dependency count constraints or recent issue tracking in the provided data.

Active areas of work

No recent activity is visible in the provided repository snapshot. The last documented changes appear to be in the CHANGELOG.md and initial gem release. This suggests the tool is in maintenance mode rather than active feature development.

🚀Get running

git clone https://github.com/venmo/synx.git
cd synx
bundle install
bundle exec synx spec/dummy/dummy.xcodeproj

Daily commands:

bundle exec synx path/to/project.xcodeproj [OPTIONS]
# Examples:
bundle exec synx -p -e "/OCMock/Core Mocks" source/OCMock.xcodeproj
bundle exec synx --prune --no-sort-by-name path/to/project.xcodeproj

🗺️Map of the codebase

  • bin/synx — Entry point CLI script that users invoke; must understand argument parsing and high-level orchestration flow.
  • lib/synx.rb — Main module root that loads and initializes all synx components; foundational for understanding how pieces fit together.
  • lib/synx/project.rb — Core orchestrator that reads Xcode project structure, compares it to filesystem, and synchronizes them; handles the main business logic.
  • lib/synx/xcodeproj_ext/project/object/pbx_group.rb — Extension that models Xcode group hierarchy and provides traversal/mapping utilities; critical for understanding group-to-folder translation.
  • lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb — Models individual file references in Xcode and maps them to filesystem paths; essential for file matching logic.
  • synx.gemspec — Gem manifest declaring dependencies and metadata; needed to understand external tool versions and build requirements.
  • spec/synx/project_spec.rb — Integration test suite showing real end-to-end workflows and expected outcomes; invaluable for understanding happy paths.

🧩Components & responsibilities

  • bin/synx (CLI) (Ruby, OptionParser or similar) — Parse command-line arguments and invoke project orchestrator with the target Xcode project path
    • Failure mode: Invalid or missing project path; CLI exits with error message
  • lib/synx/project.rb (Orchestrator) (xcodeproj gem, File I/O) — Reads .pbxproj file via xcodeproj, scans filesystem, compares hierarchies, and issues filesystem move/create commands
    • Failure mode: Corrupted .pbxproj, missing files, or permission errors; logs errors and may leave filesystem in partial state
  • PBXGroup & PBXFileReference extensions (xcodeproj gem extensions, Ruby introspection) — Model Xcode group hierarchy and file references; provide utility methods for traversal and path resolution
    • Failure mode: Incorrect path mapping or missing groups; leads to incorrect file placement
  • Tabber (output formatter) (String formatting) — Format console output with proper indentation for group hierarchy visualization
    • Failure mode: Misaligned output; purely cosmetic, no functional impact

🔀Data flow

  • User (CLI argument)bin/synx → project.rb — Path to .xcodeproj directory
  • project.rbxcodeproj gem — Load and parse .pbxproj file
  • xcodeproj gemPBXGroup/PBXFileReference extensions — Instantiated Xcode objects; extended with custom methods
  • PBXGroup traversalproject.rb — Expected folder hierarchy and file paths based on Xcode groups
  • Filesystem scanproject.rb — Actual current folder structure and files
  • project.rb comparisonFilesystem (via — undefined

🛠️How to make changes

Add a new file reference extension method

  1. Open the PBXFileReference extension class (lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb)
  2. Add a new instance method that queries or transforms file reference properties (e.g., real_path, source_tree, relative path) (lib/synx/xcodeproj_ext/project/object/pbx_file_reference.rb)
  3. Write a test in the PBXGroup or Project spec to verify the method works correctly (spec/synx/xcodeproj_ext/project/object/pbx_group_spec.rb)

Add a new group hierarchy traversal or transformation

  1. Open the PBXGroup extension class to add recursive group processing logic (lib/synx/xcodeproj_ext/project/object/pbx_group.rb)
  2. Implement a method that traverses child groups and/or file references (e.g., collect all files, map hierarchy to paths) (lib/synx/xcodeproj_ext/project/object/pbx_group.rb)
  3. Add test cases using the dummy project fixture in spec/dummy to validate traversal (spec/synx/xcodeproj_ext/project/object/pbx_group_spec.rb)

Modify the synchronization logic for custom folder/group matching

  1. Review the main synchronization orchestrator to understand current matching rules (lib/synx/project.rb)
  2. Add custom matching or filtering logic in the appropriate method (likely in project.rb or a new helper method) (lib/synx/project.rb)
  3. Update or add test cases in the project spec with new fixtures in spec/dummy/dummy to validate the custom behavior (spec/synx/project_spec.rb)

🔧Why these technologies

  • Ruby — CLI tools for developer workflows are convention in the Ruby ecosystem; gem distribution via RubyGems is straightforward
  • xcodeproj gem — Mature, well-maintained library for programmatically reading/writing Xcode project files (.pbxproj); avoids reimplementing PBX format parsing
  • RSpec — Standard Ruby testing framework; allows integration tests on real dummy Xcode projects to validate end-to-end behavior

⚖️Trade-offs already made

  • Ruby CLI tool rather than Swift/Xcode plugin

    • Why: Ruby CLI is faster to develop and easier to distribute via gem; doesn't require Xcode plugin architecture
    • Consequence: Requires Ruby runtime on user's machine; no native IDE integration (users invoke from terminal)
  • Extends xcodeproj models rather than reimplementing PBX parsing

    • Why: Avoids duplicating complex PBX format logic; leverages tested third-party library
    • Consequence: Dependency on xcodeproj gem version stability; any breaking changes in that gem require updates here
  • One-way synchronization (Xcode groups → filesystem) rather than bidirectional

    • Why: Simpler mental model and implementation; Xcode is the source of truth
    • Consequence: File moves in Finder don't automatically update Xcode groups; user must run synx again

🚫Non-goals (don't propose these)

  • Does not modify Xcode project references or build phases; only reorganizes folder structure
  • Does not support bidirectional synchronization from filesystem to Xcode groups
  • Does not handle merge conflicts or version control integration
  • Does not provide real-time file watching or automatic re-sync on group changes

🪤Traps & gotchas

  1. The tool modifies the .pbxproj file directly via xcodeproj gem; if you interrupt mid-sync, the project may be left in an inconsistent state. 2. The --prune option deletes files not referenced by the project—this is irreversible without version control. 3. Core Data .xcdatamodeld bundles are treated as atomic units (see spec/dummy structure), not as individual files; moving them incorrectly can break versioning. 4. Symlinks and build products (Products/) are typically excluded; check --no-default-exclusions behavior if your project has unusual structure.

🏗️Architecture

💡Concepts to learn

  • Xcode Project Structure (.pbxproj format) — Synx's entire purpose is to parse and manipulate the .pbxproj file structure; understanding the PBX reference graph (how groups, file references, and targets link together) is critical to understanding how synx reconciles virtual groups with real files
  • File System Mirror Synchronization — Synx implements a bidirectional reconciliation algorithm: it reads Xcode's in-memory group tree and then modifies the file system to match it, which is a classic tree-sync problem
  • Monkeypatching / Gem Extension — Synx extends the xcodeproj gem by reopening PBXGroup and PBXFileReference classes and adding sync methods; understanding Ruby's open classes and method aliasing is needed to follow or modify this approach
  • Recursive Tree Traversal with State Management — Synx traverses nested Xcode groups (tree structure) and decides which files to move, create, or delete at each level; understanding depth-first vs breadth-first and memoization is important for debugging nesting issues
  • Path Resolution and Normalization — Synx must map Xcode group paths (like 'UI/Buttons') to file system paths, handling symlinks, relative paths, and bundle structures (.xcdatamodeld); any path bugs silently corrupt projects
  • cocoapods/xcodeproj — The gem that synx extends; understanding its PBXGroup/PBXFileReference classes is essential to modifying synx
  • fastlane/fastlane — Popular iOS automation tool that also manipulates Xcode projects; similar problem domain and some overlapping dependencies
  • krausefx/gym — Fastlane sub-tool for building iOS apps; works closely with Xcode project structure like synx does
  • Carthage/Carthage — Dependency manager for iOS that also parses and understands Xcode project hierarchies

🪄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 comprehensive unit tests for lib/synx/xcodeproj_ext/ extension modules

The repo has a spec/ directory with a dummy Xcode project, but there are no visible test files for the core extension classes (pbx_group.rb, pbx_file_reference.rb, abstract_object.rb, abstract_target.rb). These extensions directly manipulate Xcode project structures and are critical to synx's functionality. Testing these would catch regressions in group/file handling and improve code confidence.

  • [ ] Create spec/lib/synx/xcodeproj_ext/project/object/pbx_group_spec.rb with tests for group creation, path resolution, and hierarchy manipulation
  • [ ] Create spec/lib/synx/xcodeproj_ext/project/object/pbx_file_reference_spec.rb with tests for file reference path updates and sourceTree handling
  • [ ] Create spec/lib/synx/xcodeproj_ext/project/object/abstract_object_spec.rb with tests for object metadata and path calculations
  • [ ] Add integration tests in spec/ that verify the dummy project transformations work correctly

Add end-to-end integration test suite with multiple Xcode project scenarios

The spec/dummy directory contains one test project, but synx likely encounters diverse project structures (nested groups, build targets, workspace dependencies, custom file types like .xcdatamodeld). Add scenario-based integration tests covering edge cases like: multiple targets, symlinked files, special bundle types (.framework, .bundle), and complex group hierarchies. This prevents regressions when synx handles real-world projects.

  • [ ] Create spec/integration/ directory with separate test fixtures for each scenario (multi_target_project, symlink_handling, framework_bundles, deep_nesting)
  • [ ] Add spec/integration/synx_integration_spec.rb that runs synx on each fixture and validates the resulting file structure matches the Xcode group structure
  • [ ] Document in README.md the test scenarios covered and how to add new integration tests

Refactor lib/synx/project.rb into focused modules to improve testability and maintainability

lib/synx/project.rb likely contains multiple responsibilities (parsing, traversal, file operations, output). Breaking it into smaller modules (ProjectParser, GroupTraversal, FileOrganizer, SyncReporter) would make individual components easier to test in isolation, reduce coupling to Xcode internals, and make the codebase clearer for new contributors.

  • [ ] Analyze lib/synx/project.rb to identify distinct responsibilities and extract group/file traversal logic into lib/synx/group_traversal.rb
  • [ ] Extract file system operations (moving, creating directories) into lib/synx/file_organizer.rb
  • [ ] Extract reporting/output logic into lib/synx/sync_reporter.rb
  • [ ] Update lib/synx/project.rb to compose these modules and add unit tests for each new module in spec/lib/synx/

🌿Good first issues

  • Add integration tests under spec/ that verify actual file system changes (moving files, creating folders) for each group nesting depth; currently only the dummy project structure exists
  • Document the exclusion syntax and provide a --list-exclusions option to show what groups/paths will be skipped; helps users debug why certain files don't sync
  • Add a --dry-run flag to preview all changes without modifying files or .pbxproj; would greatly reduce user anxiety given the destructive nature of the tool

Top contributors

Click to expand

📝Recent commits

Click to expand
  • e22f20a — v0.2.1 (marklarr)
  • 974b545 — Merge pull request #109 from jschmid/patch-1 (marklarr)
  • b3fe480 — Using xcodeproj 1.0.0 (jschmid)
  • ad94e49 — 0.2.0 (marklarr)
  • dec8902 — Merge pull request #98 from rafalwojcik/flag_for_name_sorting (marklarr)
  • 7a978ff — Add flag to disable sort groups by name (rafalwojcik)
  • 27840e2 — Merge pull request #97 from PycKamil/master (eliperkins)
  • d50d87a — Prune support for Swift files (PycKamil)
  • f2eab5b — v0.1.1 (marklarr)
  • 625fcf7 — Merge pull request #86 from venmo/kylef/xcodeproj-0.28 (marklarr)

🔒Security observations

The synx project has a generally solid security posture for a command-line Ruby tool. No critical vulnerabilities were identified in the visible file structure. Primary concerns are related to best practices: preventing accidental commits of user-specific Xcode data and establishing a vulnerability disclosure process. The project would benefit from a formal security policy and regular dependency auditing. The codebase appears to focus on file system operations and Xcode project manipulation without obvious injection or data exposure risks in the visible structure.

  • Medium · Exposed User Data in Version Control — spec/dummy/dummy.xcodeproj/xcuserdata/. The repository contains xcuserdata files (spec/dummy/dummy.xcodeproj/xcuserdata/marklarsen.xcuserdatad/) which may contain user-specific settings, build preferences, or other sensitive configuration. While this is a test/dummy project, it establishes a pattern that could leak personal information in production repos. Fix: Add xcuserdata/ to .gitignore to prevent accidental commits of user-specific Xcode data. Ensure the project's .gitignore follows Xcode best practices.
  • Low · Test Fixtures with Overly Permissive Structure — spec/dummy/dummy/. The spec/dummy directory contains test fixtures with files explicitly marked as 'NotInXcodeProj' and other edge cases. While useful for testing, this pattern could be misunderstood as valid file organization practices if documentation isn't clear. Fix: Ensure comprehensive documentation exists explaining that spec/dummy is a test fixture. Add clear comments in the test files explaining edge cases being tested.
  • Low · No Security Policy or Vulnerability Disclosure Process — Repository root. The repository does not appear to have a SECURITY.md file or defined vulnerability disclosure process, based on the provided file listing. Fix: Create a SECURITY.md file that outlines how users can securely report vulnerabilities without exposing them publicly.
  • Low · Ruby Project Without Explicit Dependency Pinning Information — Gemfile, Gemfile.lock (not provided). While a Gemfile is present, no Gemfile.lock content was provided for analysis. Ruby projects should use lock files to ensure consistent dependency versions across environments. Fix: Ensure Gemfile.lock is committed to version control and regularly updated. Use 'bundle audit' to scan for known vulnerabilities in dependencies.

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.