{"id":31237021,"url":"https://github.com/macvmio/curie","last_synced_at":"2026-03-08T00:12:50.211Z","repository":{"id":257823444,"uuid":"681766856","full_name":"macvmio/curie","owner":"macvmio","description":"CLI-oriented macOS virtual machine","archived":false,"fork":false,"pushed_at":"2026-02-02T22:08:34.000Z","size":1658,"stargazers_count":20,"open_issues_count":4,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-03T11:33:14.940Z","etag":null,"topics":["ci","cicd","macos","virtual-machine","virtualization","vm"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/macvmio.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":"2023-08-22T18:01:39.000Z","updated_at":"2026-02-02T22:08:38.000Z","dependencies_parsed_at":"2024-10-12T16:57:16.177Z","dependency_job_id":"d577cc55-6240-4778-97d4-e35a25125cc0","html_url":"https://github.com/macvmio/curie","commit_stats":null,"previous_names":["macvmio/curie"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/macvmio/curie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macvmio%2Fcurie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macvmio%2Fcurie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macvmio%2Fcurie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macvmio%2Fcurie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macvmio","download_url":"https://codeload.github.com/macvmio/curie/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macvmio%2Fcurie/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30238347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T23:52:25.683Z","status":"ssl_error","status_checked_at":"2026-03-07T23:52:25.373Z","response_time":53,"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":["ci","cicd","macos","virtual-machine","virtualization","vm"],"created_at":"2025-09-22T16:59:22.165Z","updated_at":"2026-03-08T00:12:50.201Z","avatar_url":"https://github.com/macvmio.png","language":"Swift","funding_links":[],"categories":["Virtualization"],"sub_categories":["macOS Environments"],"readme":"![Curie](Resources/curie-logo.png)\n\n[![Build Status](https://github.com/macvmio/curie/actions/workflows/main.yml/badge.svg)](https://github.com/macvmio/curie/actions/workflows/main.yml)\n[![Swift](https://img.shields.io/badge/Swift-5.8+-orange.svg)](https://swift.org)\n[![Platform](https://img.shields.io/badge/platform-macOS%2013+-blue.svg)](https://developer.apple.com/macos/)\n[![CLI](https://img.shields.io/badge/interface-CLI-green.svg)](#usage)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n[![GitHub Release](https://img.shields.io/github/v/release/macvmio/curie)](https://github.com/macvmio/curie/releases/latest)\n\n## Overview\n\n*Curie* is a lightweight, open-source virtualization solution that leverages the Apple [Virtualization.framework](https://developer.apple.com/documentation/virtualization). \n\nIt empowers users to run and manage isolated instances, simplifying the process of running, developing, and testing software in a controlled and reproducable environment.\n\n![Demo](Resources/curie-demo.png)\n\n### Key Features\n\n* **Containerization**: Like Docker, the tool allows users to create and manage containers, each providing a separate environment for running applications (under the hood, each container is represented by a standard macOS VM).\n\n* **Resource Management**: The tool offers basic resource management options, allowing users to allocate CPU and memory resources to containers. This ensures that containers run efficiently without overloading the host system.\n\n* **Image Management**: Users can create, modify, abd clone images. Images can be stored locally and reused across multiple containers.\n\n## Installation\n\n### Install via script\n\nThe following script will download [the latest version](https://github.com/macvmio/curie/releases/latest) of Curie from [GitHub Releases](https://github.com/macvmio/curie/releases) and install it in `/usr/local/bin/curie` (requires sudo for system-wide installation):\n\n```bash\n/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/macvmio/curie/refs/heads/main/.mise/tasks/install)\"\n```\n\nMake sure you have the necessary permissions, as sudo may be required during the installation process.\n\n## Usage\n\n### Commands\n\n#### Download an image restore file\n\n```sh\ncurie download -p ~/Downloads/RestoreImage.ipsw\n```\n\n#### Build an image\n\n```sh\ncurie build myteam/myimage/test-image:1.0 -i ~/Downloads/RestoreImage.ipsw -d \"60 GB\" \n```\n\n#### Remove an image\n\n```sh\ncurie rmi myteam/myimage/test-image:1.0\n```\n\n#### List images\n\n```sh\ncurie images\n\n# Example output\n\nREPOSITORY                 TAG     IMAGE ID         CREATED         SIZE\nmyteam/myimage/ci/test     2.3     9bf95fe0f7f0     2 hours ago     60.03 GB\nmyteam/myimage/ci/test     2.1     7d5347edc7ca     7 hours ago     60.03 GB\n```\n\nThe command has also `--format` (`-f`) parameter which allows to output JSON.\n\n```sh\ncurie images -f json\n```\n\nExample output:\n```json\n[\n  {\n    \"created\" : \"36 minutes ago\",\n    \"image_id\" : \"a5abe5c92583\",\n    \"repository\" : \"myteam\\/myimage\\/ci\\/test\",\n    \"size\" : \"60.03 GB\",\n    \"tag\" : \"2.4\"\n  },\n  {\n    \"created\" : \"4 days ago\",\n    \"image_id\" : \"4b72a86471ef\",\n    \"repository\" : \"myteam\\/myimage\\/ci\\/test\",\n    \"size\" : \"60.03 GB\",\n    \"tag\" : \"2.3\"\n  },\n  {\n    \"created\" : \"1 week ago\",\n    \"image_id\" : \"7d5347edc7ca\",\n    \"repository\" : \"myteam\\/myimage\\/ci\\/test\",\n    \"size\" : \"60.03 GB\",\n    \"tag\" : \"2.1\"\n  }\n]\n```\n\n#### Clone an image\n\n```sh\ncurie clone myteam/myimage/test-image:1.0 myteam/myimage/test-image:1.1\n```\n\n#### Export an image\n\n```sh\ncurie export a8302cc3e913 -p test-image-2.4.zip -c\n\n# or without compression\ncurie export a8302cc3e913 -p test-image-2.4\n```\n\n#### Import an image\n\n```sh\ncurie import myteam/myimage/test-image:2.4 -p test-image-2.4.zip\n```\n\n#### Start an ephemeral container\n\nThe container will be deleted after it is closed.\n\n```sh\ncurie run myteam/myimage/test-image:1.0\n```\n\n#### Create a container\n\n```sh\ncurie create myteam/myimage/test-image:1.0\n```\n\n#### List containers\n\n```sh\ncurie ps\n\n# Example output\n\nCONTAINER ID     REPOSITORY                               TAG     CREATED           SIZE\n7984867efb71     @7984867efb71/myteam/myimage/ci/test     2.1     3 minutes ago     60.03 GB\n```\n\nThe command has also `--format` (`-f`) parameter which allows to output JSON.\n\n#### Start a container\n\nAll changes that are made in the container will be applied to the image once the container is closed.\n\n```sh\ncurie start @7984867efb71/myteam/myimage/ci/test\n```\n\n#### Inspect an image or a container\n\n```sh\ncurie inspect myteam/myimage/ci/test:2.3\n\n# Example output\n\nMetadata:\n  id: 9bf95fe0f7f0\n  name: \u003cnone\u003e\n  createdAt: 2023-09-17T18:22:58Z\n  network:\n    devices:\n      index: 0\n      macAddress: 11:37:c4:2f:2a:a7\n\nConfig:\n  name: test:2.3\n  cpuCount: 8\n  memorySize: 8.00 GB\n  display:\n    width: 1920px\n    height: 1080px\n    pixelsPerInch: 144\n  network:\n    devices:\n      index: 0\n      macAddress: synthesized\n      mode: NAT\n```\n\nInspect command supports `--format` (`-f`) parameter.\n\n#### Edit config of an image or a container\n\nThe command will open the config file in the default text editor.\n\n```sh\ncurie config myteam/myimage/ci/test:2.3\n```\n\n### Config file\n\n`create` command allows to pass path to config file (`-c, --config-path \u003cconfig-path\u003e`). Config file describes basic properties of the virtual machine such as number of CPUs, RAM etc.\n\nExample:\n\n```json\n{\n  \"cpuCount\" : 8,\n  \"network\" : {\n    \"devices\" : [\n      {\n        \"mode\" : \"NAT\",\n        \"macAddress\" : \"synthesized\"\n      }\n    ]\n  },\n  \"display\" : {\n    \"width\" : 1920,\n    \"height\" : 1080,\n    \"pixelsPerInch\" : 144\n  },\n  \"sharedDirectory\": {\n    \"directories\": [\n      {\n        \"currentWorkingDirectory\": {\n          \"options\": {\n            \"name\": \"cwd\",\n            \"readOnly\": false\n          }\n        }\n      }\n    ]\n  },\n  \"name\" : \"Test VM\",\n  \"memorySize\" : \"8 GB\"\n}\n```\n\n### CPU count\n\nPossible values:\n* `\u003ccount\u003e`, e.g. `8` - hardcoded number of CPUs\n* `\"minimumAllowedCPUCount\"` - minimum number of CPUs\n* `\"maximumAllowedCPUCount\"` - maximum number of CPUs\n\n### Memory size\n\nPossible values:\n* `\"\u003cnumber\u003e GB\"`, e.g. `\"80 GB\"` - hardcoded size (user-friendly format)\n* `\"minimumAllowedMemorySize\"` - minimum size\n* `\"maximumAllowedMemorySize\"` - maximum size\n\n### Display\n\nProperties:\n* `width` - width of the screen\n* `height` - height of the screen\n* `pixelsPerInch` - density\n\n### Network\n\nCurrently we only support `NAT` interfaces. Each interface can have MAC address assigned in the following way:\n* `\"automatic\"` - Virtualization Framework will transparently assign new MAC address\n* `\"synthesized\"` - Curie will automatically generate unique MAC address per `run` or `start` operation (both MAC and IP address can be found using `curie inspect` command)\n* e.g. `\"6e:7e:67:0c:93:65\"` - manual MAC address\n\n### Shared directories\n\n#### Share current working directory\n\nUse `-s, --share-cwd` to share current working directory with the guest OS.\n\n#### Share an arbitrary directory\n\nAdd the directory descriptor to `config.json`, e.g.\n\n```json\n{\n \"sharedDirectory\" : {\n    \"directories\" : [\n      {\n        \"directory\": {\n          \"options\": {\n            \"path\": \"/Users/marcin/shared-directory\",\n            \"name\": \"shared-directory\",\n            \"readOnly\": false\n          }\n        }\n      }\n    ],\n    \"automount\" : true\n  }\n}\n```\n\n#### Mount shared directories\n\nA shared directory is automatically mounted via `/Volumes/My Shared Files` unless \"automount\" is disable via `config.json`, e.g.\n\n```json\n{\n  \"sharedDirectory\" : {\n    \"directories\" : [],\n    \"automount\" : false\n  }\n}\n```\n\nIf `automount` is set to `false`, the volume `curie` will need to be mounted manually, e.g.\n\n```sh\n# mounting shared directory\nmkdir -p shared # you can pick up different name\nmount -t virtiofs curie shared\n\n# or\nmkdir -p shared\nmount_virtiofs curie shared\n```\n\n### Data location\n\nBy default, curie stores images and containers in `~/.curie` directory. You can change the location by setting `CURIE_DATA_ROOT` environment variable.\n\n### Pull and Push Images\n\nCurie does not natively support interacting with image registries (such as OCI), but it provides a flexible plugin system that allows you to extend its functionality. By creating lightweight plugins, you can easily add `pull` and `push` commands to interact with external image registries or storage backends.\n\nThis plugin system abstracts the integration entirely. Whether you are working with an OCI registry, an S3 bucket, or any other storage solution, the choice is yours. The image handling logic is completely within your control.\n\n#### How to Add `pull` and `push` Plugins\n\nTo extend Curie with `pull` and/or `push` commands, follow these steps:\n\n1. Navigate to the `~/.curie` directory (or your custom data directory if `CURIE_DATA_ROOT` is set).\n2. Create a `plugins` directory inside.\n3. Add executable files named `pull` and/or `push` to this directory.\n\nOnce these executable files are in place, Curie will automatically recognize them and include the new commands in its `--help` output. When a user runs a `pull` or `push` command, Curie will call the corresponding plugin scripts:\n\n- `push --reference \u003creference\u003e` will be executed when the user runs `curie push \u003creference\u003e`.\n- `pull --reference \u003creference\u003e` will be executed when the user runs `curie pull \u003creference\u003e`.\n\n#### Pull Plugin Example\n\nThe following example shows a basic integration with [geranos](https://github.com/mobileinf/geranos).\n\n```bash\n#!/bin/bash -e\n\n# Check if the number of arguments\nif [[ $# -lt 2 ]]; then\n    echo \"Error: reference argument is required\"\n    echo \"Usage: $0 --reference \u003creference\u003e\"\n    exit 1\nfi\n\n# Check if the first argument is \"--reference\"\nif [ \"$1\" != \"--reference\" ]; then\n    echo \"Error: reference argument is required\"\n    echo \"Usage: $0 --reference \u003creference\u003e\"\n    exit 1\nfi\n\n# Check if geranos is installed\nif ! command -v geranos \u0026\u003e /dev/null; then\n    echo \"Error: geranos is not installed.\"\n    exit 1\nfi\n\n# Call geranos\ngeranos pull \"$2\"\n```\n\n## Development\n\n### Requirements\n\n- Xcode 16.0 or newer\n- mise\n\n### Set up dev environment\n\nAlmost all `make \u003ccommand\u003e` commands require [mise](https://github.com/jdx/mise).\n\nIf you don't have mise installed, run the following command to install it.\n\n```sh\nmake setup\n```\n\n### Build\n\nExecute the commands below to build the project in debug mode.\n\n```sh\nmake build \nmake sign\n```\n\n### Run\n\nExecute the commands below to run the project locally.\n\n```sh\n.build/debug/curie --help\n```\n\n### Build and Run in Xcode\n\nThe [Virtualization.framework](https://developer.apple.com/documentation/virtualization) requires the `com.apple.security.virtualization` entitlement to run correctly. Without this entitlement, certain commands, such as `start` or `run`, may fail and produce the following error:\n\n```\nError: Invalid virtual machine configuration. The process doesn’t have the “com.apple.security.virtualization” entitlement.\nProgram ended with exit code: 1\n```\n\nTo resolve this issue, you need to add the necessary entitlement to your app. Follow these steps to configure your Xcode project:\n\n1. Open the Scheme Editor:\n    - In Xcode, go to the **Product** menu and select **Scheme** \u003e **Edit Scheme**.\n\n2. Add a Post-Build Action:\n    - In the Scheme editor, select the Build tab.\n    - Under the **Post-actions** section, click the **+** button and choose New Run Script Action.\n\n3. Enter the Codesign Command:\n    - In the newly created **Run Script** action, enter the following command to apply the entitlement:\n\n```sh\ncodesign --sign - --entitlements \"$WORKSPACE_PATH/../../../Resources/curie.entitlements\" --force \"$TARGET_BUILD_DIR/curie\"\n```\n\n4. Save and Build:\n    - Save the scheme changes and rebuild the project. The app should now have the necessary entitlement to run the virtual machine without errors.\n\n## Attributions\n\nWe would like to thank the authors and contributors of the following projects:\n\n- [Virtualization.framework](https://developer.apple.com/documentation/virtualization)\n- [swift-argument-parser](https://github.com/apple/swift-argument-parser)\n- [swift-tools-support-core](https://github.com/apple/swift-tools-support-core)\n- [SwiftLint](https://github.com/realm/SwiftLint)\n- [SwiftFormat](https://github.com/nicklockwood/SwiftFormat)\n- [mise](https://github.com/jdx/mise)\n\n## License\n\nCurie is released under version 2.0 of the [Apache License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacvmio%2Fcurie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacvmio%2Fcurie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacvmio%2Fcurie/lists"}