{"id":35377553,"url":"https://github.com/noworrieseh/macdisp","last_synced_at":"2026-01-13T19:29:27.070Z","repository":{"id":331378827,"uuid":"1126071840","full_name":"noworrieseh/macdisp","owner":"noworrieseh","description":"macOS command-line tool for changing the display","archived":false,"fork":false,"pushed_at":"2026-01-06T03:32:14.000Z","size":40,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-07T06:13:44.372Z","etag":null,"topics":["command-line-tool","mac-tools","macos","macos-tools","utilities"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noworrieseh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-01T03:00:59.000Z","updated_at":"2026-01-06T03:32:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/noworrieseh/macdisp","commit_stats":null,"previous_names":["noworrieseh/macdisp"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/noworrieseh/macdisp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noworrieseh%2Fmacdisp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noworrieseh%2Fmacdisp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noworrieseh%2Fmacdisp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noworrieseh%2Fmacdisp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noworrieseh","download_url":"https://codeload.github.com/noworrieseh/macdisp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noworrieseh%2Fmacdisp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28397826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line-tool","mac-tools","macos","macos-tools","utilities"],"created_at":"2026-01-02T04:47:45.112Z","updated_at":"2026-01-13T19:29:27.065Z","avatar_url":"https://github.com/noworrieseh.png","language":"Rust","funding_links":[],"categories":["System Monitor"],"sub_categories":[],"readme":"# macdisp\n\nA Rust implementation of [displayplacer](https://github.com/jakehilborn/displayplacer) with full compatibility. This tool allows you to configure macOS display settings from the command line.\n\n## Installation\n\n### Homebrew\n\n```bash\n# Add the tap\nbrew tap noworrieseh/brews\n\n# Install macdisp\nbrew install macdisp\n```\n\nOr as a one-liner:\n\n```bash\nbrew install noworrieseh/brews/macdisp\n```\n\n### MacPorts\n\n```bash\nsudo port install macdisp\n```\n\n### crates.io\n\n```bash\ncargo install macdisp\n```\n\n### Pre-built Binary\n\nDownload the latest release from the [releases page](https://github.com/noworrieseh/macdisp/releases):\n\n```bash\n# Download and install (ARM64 / Apple Silicon)\ncurl -L https://github.com/noworrieseh/macdisp/releases/latest/download/macdisp-macos-vX.X.X.tar.gz -o macdisp.tar.gz\ntar -xzf macdisp.tar.gz\nsudo mv macdisp /usr/local/bin/\nsudo chmod +x /usr/local/bin/macdisp\n\n# Or use the universal binary (works on both Intel and Apple Silicon)\ncurl -L https://github.com/noworrieseh/macdisp/releases/latest/download/macdisp-universal-vX.X.X.tar.gz -o macdisp.tar.gz\ntar -xzf macdisp.tar.gz\nsudo mv macdisp-universal /usr/local/bin/macdisp\nsudo chmod +x /usr/local/bin/macdisp\n```\n\n### Build from Source\n\n### Prerequisites\n\n- Rust toolchain (1.70+)\n- macOS (tested on 10.13+)\n- Xcode Command Line Tools\n\n### Build Instructions\n\n```bash\n# Clone the repository\ngit clone https://github.com/noworrieseh/macdisp.git\ncd macdisp\n\n# Build release version\ncargo build --release\n\n# The binary will be at target/release/macdisp\n\n```\n\n### Installation\n\n```bash\n# Copy to a location in your PATH\nsudo cp target/release/macdisp /usr/local/bin/\n```\n\n## Usage\n\n### List All Displays\n\n```bash\nmacdisp\n# or\nmacdisp list\n\n# Output as JSON\nmacdisp list --json\n```\n\nThis shows all connected displays with their current configuration and generates a command to restore the current arrangement.\n\nThe `--json` flag outputs the display information in JSON format, which is useful for scripting and integration with other tools.\n\n### Show Available Modes\n\n```bash\nmacdisp modes \u003cdisplay_id\u003e\n\n# Output as JSON\nmacdisp modes \u003cdisplay_id\u003e --json\n```\n\nShows all available display modes for a specific display, including resolution, refresh rate, bit depth, and whether each mode is safe for hardware.\n\nThe `--json` flag outputs the mode information in JSON format, including the current mode and all available modes with detailed properties.\n\n### Hide/Show the Notch (MacBook Pro)\n\n```bash\n# Hide the notch (switch to smaller height mode)\nmacdisp notch hide\n\n# Show the notch (switch to larger height mode)\nmacdisp notch show\n\n# Toggle between hiding and showing the notch\nmacdisp notch toggle\n\n# Specify a display ID (defaults to main display)\nmacdisp notch hide --display-id 1\n```\n\nOn MacBook Pro models with a notch, this command switches between display modes with different heights while maintaining the same width, refresh rate, and scaling settings. The \"hide\" mode uses a slightly smaller vertical resolution that doesn't extend into the notch area, while \"show\" mode uses the full screen height including the notch area.\n\n**Note:** If you run this command on a display without a notch (external monitors, older MacBooks, etc.), the tool will detect this and provide an appropriate error message:\n\n- For non-built-in displays: \"Display X is not a MacBook built-in display with a notch\"\n- For built-in displays without alternate height modes: \"Display X does not appear to have a notch (no alternate height modes found)\"\n\nThis prevents accidentally switching to inappropriate display modes on non-notch displays.\n\n### Configure Displays\n\n```bash\nmacdisp \"id:1 res:1920x1080 hz:60 color_depth:32 origin:(0,0) degree:0 enabled:true\"\n```\n\n#### Configuration Parameters\n\n- `id:\u003cnumber\u003e` - Display ID (required)\n- `res:\u003cwidth\u003ex\u003cheight\u003e` - Resolution\n- `hz:\u003crefresh_rate\u003e` - Refresh rate in Hz\n- `color_depth:\u003cbits\u003e` - Color depth (8, 16, or 32)\n- `origin:(\u003cx\u003e,\u003cy\u003e)` - Display position\n- `degree:\u003crotation\u003e` - Rotation (0, 90, 180, 270)\n- `mirror:\u003cdisplay_id\u003e` - Mirror another display\n- `enabled:\u003ctrue|false\u003e` - Enable/disable display\n\n### Examples\n\n```bash\n# Set display 1 to 1920x1080 @ 60Hz\nmacdisp \"id:1 res:1920x1080 hz:60\"\n\n# Configure multiple displays\nmacdisp \\\n  \"id:1 res:2560x1440 hz:60 origin:(0,0) enabled:true\" \\\n  \"id:2 res:1920x1080 hz:60 origin:(2560,0) enabled:true\"\n\n# Set a display to a specific mode number\nmacdisp \"id:1 mode:123\"\n\n# Get display information as JSON for scripting\nmacdisp list --json\n\n# Get all available modes as JSON\nmacdisp modes 1 --json\n```\n\n### Notch Management\n\n```bash\n# Hide the notch on current display\nmacdisp notch hide\n\n# Show the notch on current display\nmacdisp notch show\n\n# Toggle notch visibility\nmacdisp notch toggle\n\n# Target a specific display\nmacdisp notch hide --display-id 1\n```\n\nThe notch command intelligently finds display modes with matching specifications (width, refresh rate, color depth, scaling) but different heights to hide or show the notch area on compatible MacBook Pro displays. The command includes safety checks to prevent use on non-notch displays, providing clear error messages when run on external monitors or MacBooks without a notch.\n\n## JSON Output\n\nBoth the `list` and `modes` commands support JSON output for easy integration with scripts and other tools.\n\n### List Command JSON Output\n\n```bash\nmacdisp list --json\n```\n\nReturns an array of display objects:\n\n```json\n[\n    {\n        \"id\": 1,\n        \"persistent_id\": \"37D8832A-2D66-02CA-B9F7-8F30A301B230\",\n        \"contextual_id\": 1,\n        \"serial\": 4251086178,\n        \"x\": 0,\n        \"y\": 0,\n        \"width\": 1512,\n        \"height\": 945,\n        \"rotation\": 0,\n        \"hz\": 120.0,\n        \"depth\": 8,\n        \"scaling\": true,\n        \"mode_number\": 48,\n        \"is_main\": true,\n        \"is_mirror\": false,\n        \"mirror_of\": null,\n        \"enabled\": true,\n        \"display_type\": \"MacBook built in screen\"\n    }\n]\n```\n\n### Modes Command JSON Output\n\n```bash\nmacdisp modes 1 --json\n```\n\nReturns detailed mode information:\n\n```json\n{\n    \"display_id\": 1,\n    \"current_mode\": {\n        \"width\": 1512,\n        \"height\": 945,\n        \"refresh_rate\": 120.0,\n        \"depth\": 8,\n        \"mode_number\": 48,\n        \"is_stretched\": false,\n        \"is_interlaced\": false,\n        \"is_tv_mode\": false,\n        \"is_safe_for_hardware\": true,\n        \"is_scaled\": true\n    },\n    \"available_modes\": [\n        {\n            \"width\": 960,\n            \"height\": 600,\n            \"refresh_rate\": 120.0,\n            \"depth\": 8,\n            \"mode_number\": 0,\n            \"is_stretched\": false,\n            \"is_interlaced\": false,\n            \"is_tv_mode\": false,\n            \"is_safe_for_hardware\": true,\n            \"is_scaled\": true\n        }\n    ],\n    \"display_services_available\": true\n}\n```\n\n### Scripting Examples\n\n```bash\n# Get the persistent ID of the main display\nMAIN_ID=$(macdisp list --json | python3 -c \"import sys, json; displays = json.load(sys.stdin); print([d['persistent_id'] for d in displays if d['is_main']][0])\")\n\n# Count available modes for display 1\nMODE_COUNT=$(macdisp modes 1 --json | python3 -c \"import sys, json; data = json.load(sys.stdin); print(len(data['available_modes']))\")\n\n# Get current resolution\nRESOLUTION=$(macdisp list --json | python3 -c \"import sys, json; d = json.load(sys.stdin)[0]; print(f\\\"{d['width']}x{d['height']}\\\")\")\n\n# Find all 120Hz modes\nmacdisp modes 1 --json | python3 -c \"import sys, json; data = json.load(sys.stdin); [print(f\\\"Mode {m['mode_number']}: {m['width']}x{m['height']} @ {m['refresh_rate']}Hz\\\") for m in data['available_modes'] if m['refresh_rate'] == 120.0]\"\n```\n\n## Architecture\n\n### Components\n\n1. **Objective-C Helper** (`src/objc/display_services.m`)\n    - Dynamically loads DisplayServices private framework\n    - Provides C API for Rust to call\n    - Gracefully handles missing framework\n    - Implements UUID generation and display type detection\n\n2. **Rust Library** (`src/lib.rs`)\n    - Safe Rust wrappers around C APIs\n    - Display information and mode management\n    - Configuration parsing and application\n\n3. **CLI Tool** (`src/main.rs`)\n    - Command-line interface using clap\n    - Compatible with displayplacer syntax\n\n### DisplayServices vs CoreGraphics\n\nThe tool attempts to use the DisplayServices private framework first, which provides:\n\n- Access to all display modes (including HiDPI/scaled modes)\n- More detailed mode information (scaled, interlaced flags)\n- Mode switching for scaled/Retina resolutions\n\nIf DisplayServices is unavailable, it falls back to CoreGraphics, which:\n\n- Only shows \"safe\" native resolution modes\n- Has less detailed mode information\n- Works on all macOS versions\n\n## Compatibility\n\n### macOS Versions\n\n- macOS 10.13+ (High Sierra and later)\n- DisplayServices API changed in Sequoia (15.x) - fully supported\n- CoreGraphics fallback ensures universal compatibility\n\n### Original displayplacer\n\nThis implementation provides full CLI compatibility with the original displayplacer. All configuration strings work identically.\n\n## Known Limitations\n\n1. **Display Rotation**: Reading rotation works, but setting rotation via public APIs is not available. Rotation requires system reboot to take effect.\n2. **Enable/Disable**: The main display cannot be disabled via public APIs.\n\n## Development\n\n### Project Structure\n\n```\nmacdisp/\n├── Cargo.toml           # Rust dependencies\n├── build.rs             # Build script (compiles Obj-C)\n├── src/\n│   ├── main.rs         # CLI entry point\n│   ├── lib.rs          # Core library\n│   └── objc/\n│       ├── display_services.h  # C header\n│       └── display_services.m  # Obj-C implementation\n└── README.md\n```\n\n### Adding Features\n\nThe DisplayServices wrapper can be extended to support additional features:\n\n- Enhanced rotation support (requires private APIs)\n- HDR and color space configuration\n- More detailed display properties\n\n## Contributing\n\nContributions welcome! Areas for improvement:\n\n- Enhanced private API support for rotation\n- Better error handling and user feedback\n- Support for additional display features (HDR, color profiles)\n- Automated testing\n\n## Important Note for macOS Sequoia Users\n\nOn macOS Sequoia (15.x), Apple has moved the DisplayServices framework into the dyld shared cache and changed/removed many of its APIs. The tool works perfectly using CoreGraphics, which is the official Apple API and provides all necessary functionality:\n\n- ✅ List all displays and their configurations\n- ✅ Access all \"safe\" display modes (60+ modes typically available)\n- ✅ Change resolutions and refresh rates\n- ✅ Full compatibility with original displayplacer\n\nThe only difference is you won't see potentially unstable/unsupported modes that DisplayServices exposed on older macOS versions. For 99.9% of use cases, CoreGraphics provides everything you need.\n\n- **DisplayServices Support**: Accesses private DisplayServices framework for complete display mode information\n- **Automatic Fallback**: Falls back to CoreGraphics APIs when DisplayServices is unavailable\n- **Full Mode Access**: Can access and set all display modes, including hidden/unsafe ones (via DisplayServices)\n- **Compatible CLI**: Drop-in replacement for the original displayplacer syntax\n\n## License\n\nMIT License - see LICENSE file for details\n\n## Credits\n\nInspired by [displayplacer](https://github.com/jakehilborn/displayplacer) by Jake Hilborn. Reimplemented in Rust with full feature parity.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoworrieseh%2Fmacdisp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoworrieseh%2Fmacdisp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoworrieseh%2Fmacdisp/lists"}