Skip to content

Latest commit

 

History

1,053 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Darkbloom

Public Alpha — Darkbloom is a decentralized private-inference network for Apple Silicon. Expect rough edges, breaking changes, and downtime. Alpha pricing, the platform fee and payout rules are stated once, in billing.

Darkbloom turns idle Macs into a private, OpenAI-compatible inference cloud.

Today, AI compute reaches you through a stack of markups — chipmaker to hyperscaler to API vendor. Meanwhile, over 100 million Apple Silicon Macs sit mostly idle, each with up to 512 GB of unified memory and up to 819 GB/s of bandwidth — enough to run frontier-scale models at interactive speeds. Darkbloom connects that idle capacity directly to demand, and pays the people who own the machines.

The person running a provider node has root and physical custody of the machine doing your inference. Darkbloom is designed to keep prompts and responses inside the hardened provider process, using these controls:

  • In-process inference. The network provider runs MLX inside its hardened process, without a separate inference server or subprocess.
  • Runtime hardening. PT_DENY_ATTACH, Hardened Runtime and coordinator-verified SIP restrict debugging, memory access and code injection.
  • Hop-by-hop encryption. The coordinator opens the request for routing and billing, then seals it with NaCl Box (X25519 + XSalsa20-Poly1305) to the provider's attested key. The provider process decrypts it to run the model.
  • Provider authorization. Complete legacy verification combines Secure Enclave signatures, MDM/MDA evidence and APNs code identity. When independently enabled and qualified, eligible macOS 27+ providers can instead use App Attest authorization without MDM. The two paths retain separate evidence; see provider authorization.

These controls depend on the security of the operating system, hardware and attested software. See privacy expectations for what each party can observe and what metadata is retained.

The API is OpenAI- and Anthropic-compatible, so most clients work by changing one base URL.


Contents


How it works

flowchart LR
    U["<b>Consumer</b><br/>OpenAI / Anthropic SDK · curl · Web UI"]
    subgraph coord["Coordinator · Go · GCP Confidential VM (AMD SEV)"]
        CO["Auth · Routing · Billing<br/>Attestation · Encrypted transport"]
    end
    subgraph prov["Provider · Swift CLI · hardened macOS process"]
        P["mlx-swift-lm (in-process)"] --> G["Apple Silicon GPU (Metal)"]
    end

    U -->|"HTTPS · OpenAI-compatible<br/>TLS + optional NaCl Box"| CO
    CO -->|"WebSocket · outbound from provider<br/>mandatory per-request NaCl Box"| P
    P -.->|"encrypted SSE chunks"| CO
    CO -.->|"streamed response"| U
Loading

A consumer calls the coordinator over a standard HTTPS, OpenAI-compatible API. The coordinator is a Go control plane running in a Confidential VM; it authenticates the request, picks a provider, handles billing, and relays the encrypted payload. Providers are Apple Silicon Macs running the darkbloom Swift CLI; they connect outbound over WebSocket — no port forwarding or inbound firewall changes are needed — decrypt the request inside a hardened process, and run inference in-process on the GPU via MLX.

Privacy & security

Plaintext exists in the coordinator's Confidential-VM memory while it handles the request and inside the provider process while it runs inference. The coordinator writes no prompt or completion content to logs or storage. Provider hardening and attestation constrain which process can decrypt and use that content.

Encryption, hop by hop

sequenceDiagram
    participant C as Consumer
    participant K as Coordinator (CVM)
    participant P as Provider (Secure Enclave-bound)

    C->>K: Request over TLS<br/>(optionally NaCl Box-sealed to coordinator key)
    Note over K: Decrypts in CVM memory for routing + billing.<br/>Never logs or retains prompt content.
    K->>P: Re-encrypts body with a fresh ephemeral key →<br/>provider's attested X25519 key (mandatory NaCl Box)
    Note over P: Only the hardened provider process decrypts.<br/>Runs inference in-process on the GPU.
    P-->>K: Response SSE chunks encrypted to<br/>coordinator's ephemeral key
    K-->>C: Relays response (re-sealed if sender encryption is on)
Loading
Hop Protection
Consumer → Coordinator TLS by default; optionally NaCl Box-sealed to the coordinator's X25519 key (GET /v1/encryption-key)
Inside Coordinator Decrypts in Confidential-VM memory for routing & billing only; never logs or retains prompt content
Coordinator → Provider Mandatory per-request NaCl Box to the provider's attested X25519 key, with a fresh ephemeral key per request
Provider → Coordinator Response chunks encrypted back to the coordinator's ephemeral key

The encryption reference defines the keys, endpoint visibility and retained metadata for each hop. Sender sealing terminates at the coordinator; it does not hide the request from the coordinator or the provider process.

Provider hardening

Layer What it does
In-process inference MLX runs inside the provider process — no subprocess, local server, or IPC to observe
Hardened Runtime + SIP Blocks debugger attachment, memory reads, and code injection; immutable for the process lifetime
PT_DENY_ATTACH Kernel-level denial of debugger attach

Attestation & trust

flowchart TB
    SE["Secure Enclave P-256 key<br/>hardware-bound, keychain-ACL"] --> SIG["Signs attestation blob"]
    SIG --> SS["<b>self_signed</b>"]
    SS --> MDM["MDM SecurityInfo cross-check<br/>SIP · Secure Boot · FileVault"]
    MDM --> MDA["Apple MDA certificate chain<br/>Enterprise Attestation Root CA"]
    MDA --> HW["<b>hardware</b>"]
    HW --> APNS["APNs code-identity attestation (v0.6.0+)<br/>proves the running binary is genuine"]
    CHAL["Challenge-response every 5 min<br/>re-verifies SIP / Secure Boot"] -.-> SS
    CHAL -.-> HW
Loading

Providers carry one of three trust levels, surfaced on provider-committed responses via the X-Provider-Trust-Level header (alongside X-Provider-Attested, X-Provider-Encrypted, X-Provider-Chip, and X-Provider-Secure-Enclave). Pre-commit validation and capacity errors have no selected provider and no provider headers. POST /v1/chat/completions can copy the committed header fields into a JSON metadata object when the caller sets metadata_details: true (or X-Darkbloom-Metadata-Details: true). The same object also includes region/country GeoIP of the serving provider (metadata.location; not a header; no city, coordinates, lookup source, or raw IPs). See dispatch.go:3371-3379 and response_metadata.go:209-276.

Level Verification
none No attestation — not admitted for private text traffic
self_signed Secure Enclave P-256 signature + periodic challenge-response
hardware MDM enrollment + Apple Managed Device Attestation (MDA) certificate chain

The strongest live-network gate is APNs code-identity attestation, which proves the running provider binary is genuine and team-provisioned. Privacy-redacted provider trust status is public at GET /v1/providers/attestation; hardware serials, UDIDs, and raw Apple certificates remain private to providers and the coordinator.

Quickstart (consumers)

The API is OpenAI-compatible — point any OpenAI SDK at the Darkbloom base URL.

Base URL: https://api.darkbloom.dev/v1 Auth: Authorization: Bearer <key>, where <key> is an API key (sk-db-…, created in the console) or a Privy session JWT.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.darkbloom.dev/v1",
    api_key="sk-db-...",
)

stream = client.chat.completions.create(
    model="gemma-4-26b",                       # use an id from GET /v1/models
    messages=[{"role": "user", "content": "Hello, Darkbloom!"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
curl https://api.darkbloom.dev/v1/chat/completions \
  -H "Authorization: Bearer sk-db-..." \
  -H "Content-Type: application/json" \
  -d '{"model":"gemma-4-26b","messages":[{"role":"user","content":"Hello!"}],"stream":true}'

The Anthropic Messages API works too — point the Anthropic SDK at the same base URL and use /v1/messages.

See docs/consumer/quickstart.md for authentication, streaming, and SDK details.

API surface

OpenAI-compatible, with Anthropic Messages support. Inference endpoints require a Bearer key; reads marked public need no auth.

Method & path Purpose
POST /v1/chat/completions OpenAI Chat Completions (streaming + non-streaming)
POST /v1/responses OpenAI Responses API (auto-detects input vs messages)
POST /v1/completions OpenAI legacy text completions
POST /v1/messages Anthropic Messages API
GET /v1/models List models (OpenAI shape)
GET /v1/models/{id} Retrieve a model
GET /v1/models/catalog Public — full model catalog with Darkbloom metadata
GET /v1/pricing Public — live per-token pricing
GET /v1/encryption-key Public — coordinator X25519 key for optional sender-side sealing
GET /v1/providers/attestation Public — privacy-redacted provider attestation status
GET /v1/payments/balance, GET /v1/payments/usage Account balance and usage

Supported across the inference endpoints: streaming (SSE), tool / function calling, vision / multimodal input, reasoning models, and server-side continuous batching for throughput. n > 1 is rejected with 400 (on chat completions and the Responses API). Unimplemented OpenAI endpoints (e.g. /v1/embeddings) return a structured 404.

Full request/response schemas: docs/reference/api-contracts.md.

Models

The model catalog is owned by the coordinator and DB-backed — there is no hardcoded model list. Consumer-facing names are stable aliases (e.g. gemma-4-26b, gpt-oss-20b) that resolve to concrete, versioned builds; aliases can be re-pointed to new builds without breaking clients. Providers download approved models from https://models.darkbloom.ai and verify per-file and aggregate SHA-256 hashes before serving.

The authoritative, live list is always GET /v1/models (or the public GET /v1/models/catalog). Representative current models:

Alias Family Notes
gemma-4-26b Gemma 4 (MoE, ~4B active) Google's latest MoE; multimodal (text + vision)
gpt-oss-20b GPT-OSS 20B (MoE, ~3.6B active) OpenAI open-weight reasoning model

Quantization and exact build details evolve — query /v1/models rather than hardcoding them. See docs/consumer/models.md.

Pricing

Pricing is per-token and resolved per request: a provider's custom price, else a platform price, else built-in fallbacks.

Item Fallback default
Input tokens $0.05 / 1M
Output tokens $0.20 / 1M
Minimum charge $0.0001 / request
Platform fee see billing invariants

Per-token rates target roughly half of comparable hosted APIs. Live per-model pricing is always at GET /v1/pricing. Funding uses Stripe deposits into the internal micro-USD ledger; provider payouts run through Stripe Connect. Requests routed to your own machine via self-route are free. See docs/reference/pricing-model.md.

Run a provider

Earn by serving inference on your idle Mac — and stop paying for your own usage via self-route.

Requirements

Minimum Recommended
Chip Apple Silicon (M1+) M1 Pro/Max/Ultra or newer
macOS 14 (Sonoma) Latest stable
Memory 8 GB (start is rejected below 8 GB) 32 GB+ for large or multi-model
Disk 50 GB free 100 GB+
Network Outbound HTTPS (443) Low-latency path to api.darkbloom.dev

A model loads when it fits in available memory plus a small headroom (weights + ~2 GB), after the OS reserve. See docs/provider/hardware-requirements.md.

Install

curl -fsSL https://api.darkbloom.dev/install.sh | bash

Zero prerequisites and no sudo. The installer fetches the latest signed release, verifies the bundle / binary / mlx.metallib SHA-256 against the coordinator's release record, checks the Apple Developer ID code signature, provisions the Secure Enclave helper, and offers to install the MDM enrollment profile for hardware trust. See docs/provider/installation.md.

First run

darkbloom start              # background launchd service (interactive model picker + memory policy)
darkbloom start --foreground # run attached to the terminal
darkbloom idle keep-loaded   # keep models loaded while idle (instant responses); default frees after 60 min
darkbloom login              # link your account (RFC 8628 device-code flow)
darkbloom status             # config, hardware, schedule, live trust verdict
darkbloom doctor             # local diagnostics + coordinator's trust view

docs/provider/quickstart.md walks through the full flow.

CLI reference

Command Purpose
start Start serving (launchd daemon, --foreground, or --local)
stop / restart Stop (--uninstall removes the agent) / restart in place
status Hardware, config, schedule, and live daemon/trust state
doctor / verify Diagnostics (verify = strict, non-zero on any warning)
models catalog, list, download, remove cached models
login / logout Link / unlink the provider to a Darkbloom account
enroll / unenroll MDM enrollment for hardware-trust attestation
benchmark Local tokens/sec benchmark
update Check for and apply provider updates
logs Tail provider logs

There is no serve or earnings command — use start, and view earnings in the console. Full flags: docs/provider/cli-reference.md.

Configuration

Config lives at ~/.config/darkbloom/provider.toml (created on first start):

[provider]
name = "darkbloom-mac-1"
memory_reserve_gb = 4
auto_update = true
auto_restart = true

[backend]
enabled_models = []        # empty = advertise all downloaded models
idle_timeout_mins = 60     # free when idle: unload after N idle minutes, reload on demand (0 = always ready)
max_model_slots = 3        # max models resident at once
continuous_batching = true

[gemma_optimizations]
prefill_layer18 = true     # default ON; 18-layer prefill submissions
weighted_r1 = true         # default ON; coupled weighted-unsort + safe R1

[coordinator]
url = "wss://api.darkbloom.dev/ws/provider"
heartbeat_interval_secs = 5
private_only = false       # true = serve only your own self-route traffic

# Optional availability windows — outside them the node disconnects and frees GPU memory
[schedule]
enabled = true             # windows only take effect when this is true

[[schedule.windows]]
days  = ["mon", "tue", "wed", "thu", "fri"]
start = "22:00"
end   = "08:00"

[gemma_optimizations] is authoritative for production provider processes. Both selected controls default to true even when an older config omits the section. To roll back either optimization, set its key to false and run darkbloom restart; restart is the activation boundary.

Self-route & direct mode

Running a node also makes your own inference free.

  • Self-route"use my own machine, for free." Add X-Darkbloom-Route: self to any request to route only to a provider your account owns, through the same encrypted coordinator hops, with no fallback to the paid fleet (you get an explicit error if your machine can't serve). X-Darkbloom-Route: prefer routes to your machine first but falls back to the paid fleet so you're never stuck. An API key can also be pinned to owned-only with self_route_only. See docs/provider/self-route.md.

  • Direct mode — when the client can reach your Mac (same machine / LAN / tailnet), darkbloom start --local serves an OpenAI-compatible endpoint locally and skips the coordinator entirely: lowest latency, offline-capable, bytes never leave your network. See docs/provider/direct-mode.md.

Repository layout

Path Language Role
coordinator/ Go Control plane: OpenAI/Anthropic API, routing, attestation, billing, model registry
provider-swift/ Swift darkbloom provider CLI for Apple Silicon (in-process MLX inference)
console-ui/ Next.js 16 / React 19 Web dashboard: chat, billing, models, provider verification
admin-ui/ Next.js Internal read-only operator dashboard over the Postgres read replica
landing/ Next.js 16 / React 19 Darkbloom marketing site, imported from eigen-homepages
e2e/ Go System-level end-to-end & load test harness
scripts/ Shell Installer, admin CLI, model publishing, deploy helpers, docs lint (docs-check.sh, docs-stamp.sh)
libs/ Git submodules Pinned forks of mlx, mlx-swift, mlx-swift-lm compiled into the provider
docs/ Markdown How-tos, runbooks, reference, architecture, design records, dated reports — map in docs/README.md, rules in docs/AGENTS.md

The coordinator and provider share WebSocket message types that must stay in sync (coordinator/protocol/provider-swift/Sources/ProviderCore/Protocol/).

Development

# Run these commands from the repository root.
# Coordinator (Go)
go test ./coordinator/...
make coordinator-build-linux                  # → coordinator/coordinator-linux

# Provider (Swift) — depends on libs/mlx-swift and libs/mlx-swift-lm submodules
(cd provider-swift && swift test)
(cd provider-swift && swift build -c release)    # → provider-swift/.build/release/darkbloom

# Console UI (Next.js 16)
(cd console-ui && npm ci && npm run dev)
(cd console-ui && npm run build && npm test)     # production build + vitest

Build, test, and release details: docs/developer/build.md, docs/developer/test.md, docs/operations/provider-release.md.

Documentation

Full technical docs live in docs/. Starting points:

You want to… Start here
Call the API docs/consumer/quickstart.md
Understand the system docs/architecture/overview.md
Understand the privacy model docs/architecture/security/encryption.md
Run a provider node docs/provider/installation.mddocs/provider/quickstart.md
Verify a provider's attestation docs/consumer/verification.md
Build or contribute docs/developer/build.md

License & disclaimer

Proprietary. All rights reserved.

🚧 Darkbloom is under active development and has not been audited. It is upgraded rapidly; features may be added, removed, or changed, and interfaces will have breaking changes. Use it for testing only, not in production. Darkbloom is provided "as is" and Eigen Labs, Inc. does not guarantee its functionality or provide production support. 🚧

Security bugs: report vulnerabilities to security@eigenlabs.orgnot via GitHub Issues.

About

Private Inference Network on Idle Macs

Resources

Contributing

Stars

532 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages