langchain-nomac
A macOS sandbox for LangChain Deep Agents: a NoMac Mac, a cloud Mac with Xcode, as your agent's shell and files. The agent builds and tests apps for iPhone, iPad and the Mac, signs them and runs anything else macOS runs. On demand, billed per minute from prepaid credit, no subscription.
pip install langchain-nomac
Python 3.11 and later. It brings deepagents and nomac, NoMac's SDK, which starts and stops the Mac.
A Mac for your agent
from deepagents import create_deep_agent
from langchain_nomac import NoMacSandbox
from nomac import NoMac
mac = NoMac().macs.start() # NOMAC_API_KEY from the environment
mac.wait_until_ready() # usually under a minute
backend = NoMacSandbox(mac=mac)
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
system_prompt="You are an iOS developer with a Mac. Build with xcodebuild.",
backend=backend,
)
try:
agent.invoke({"messages": [{"role": "user", "content": "Clone https://github.com/acme/app and run its tests on an iPhone Simulator"}]})
finally:
mac.stop() # the Mac and everything outside ~/drive are deleted
NoMacSandbox(mac=..., timeout=1800) takes a started Mac: NoMac().macs.start(...) then mac.wait_until_ready(), or NoMac().mac(id) for a running one, also with a Mac's own token (NoMac(token=...)). backend.mac is the Mac itself, for its screen, a link to its desktop, extend() and stop(). backend.id is its session id. Get an API key at nomac.app; the Mac's options (a label for each of your users, limits, a drive) are in the nomac README.
Always stop the Mac when the agent is done. It also stops by itself at its time limit (2 hours by default), after 10 idle minutes, at its spend cap or when the credit runs out.
What the agent gets
The Mac runs macOS with Xcode, the iOS Simulator, Homebrew, Python, Node, Ruby, CocoaPods, Git and the GitHub CLI; nomac.app/llms.txt lists the versions. The agent's user is agent, with sudo and no password asked, and every macOS permission prompt is answered for it.
- Commands (
execute) run in a login shell (bash -lc) asagent. The output is stdout and stderr together, in the order they were written;exit_codeis the command's. A command runs for 30 minutes at most by default (timeouton the sandbox or on each call, an hour at most;0asks for the hour). One stopped at its timeout answers exit code 124 and says so at the end of its output. Past 8 MiB, NoMac keeps the start and the end of the output, andtruncatedis set. - Files (
upload_files,download_files, and the agent'swrite_file) go byte for byte, any size up to 2 GiB, folders made on the way. Paths must be absolute (elseinvalid_path); a missing file answersfile_not_found, a folderis_directory, a file the agent cannot readpermission_denied. - ls, read, edit, glob and grep come from Deep Agents'
BaseSandboxand run with the Mac's Python. grep runs macOS's own grep, with the flags that make it answer as GNU grep does, and stops after 35 seconds. - A Mac that has stopped (its time limit, idle timeout, spend cap or the credit's end) or a NoMac that cannot be reached:
executeraisesnomac.NoMacError, whosecodeandmessagesay which, and file calls answer it as each file's error.
~/drive is kept between Macs: what the agent leaves there is on its next Mac. Start with access={"drive": "none"} for a Mac with nothing kept, or with label="user-42" for a Mac with that user's own drive.
Async
Every call has its async form (aexecute, aupload_files, adownload_files, aread, agrep, ...), which runs the sync call in a thread.
Tests
uv sync --group test
uv run pytest tests/unit_tests # offline
NOMAC_API_KEY=nmk_... uv run pytest tests/integration_tests # a live Mac, about 6 minutes
Both run LangChain's standard sandbox tests (SandboxIntegrationTests from langchain-tests): offline against a fake NoMac whose Mac is the machine running them, live on a NoMac Mac that starts without a drive and is stopped however the run ends. Seven of the standard tests (six on glob, one on write) still assert the contract Deep Agents 0.7 replaced, and fail for every sandbox built on BaseSandbox; they are marked as expected failures until langchain-ai/langchain#40283 ships, and tests/standard.py checks the current contract in their place.
MIT licensed.
Metadata
Release files for langchain-nomac 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| langchain_nomac-0.1.0.tar.gz | 14.5 kB | Without provenance | Details for langchain_nomac-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| langchain_nomac-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for langchain_nomac-0.1.0-py3-none-any.whl |
Total release size: 23.1 kB
Release files / langchain_nomac-0.1.0.tar.gz
| Download URL | langchain_nomac-0.1.0.tar.gz |
|---|---|
| Size | 14.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
553d3df2ae0dc2cfb990b07575e8ed93e2260b819bcb31d29214eafe93903485
|
|
BLAKE2b-256 checksum How to use checksums |
23b19c8976db531c168619005e2cae1be7cc6039bce1071d913c663179a910c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / langchain_nomac-0.1.0-py3-none-any.whl
| Download URL | langchain_nomac-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
74d6c9ab5ebdda78a465551f1d9d020eefe7956e1fa00dcebdbb3a64fb369d86
|
|
BLAKE2b-256 checksum How to use checksums |
f377c9ebcab37a291bff7d83d9d79688d217e81487913f9e3c9b7d7b685bdc3e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for langchain-nomac 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.