Skip to content

Repository files navigation

Jack

Jack is a local MLX skill-adapter runtime for Apple Silicon. It binds one exact Qwen/Qwen3-8B-MLX-4bit revision to code-free, independently versioned MLX-LM LoRA bundles, then routes each request to either the base or exactly one installed adapter.

Jack owns the local Unix-socket protocol, base verification, bundle inspection, registry, routing, bounded adapter cache, cancellation, and evidence. OptiQ 0.4.2 is the currently selected live mounted-LoRA backend; the exact unpatched MOLA revision is retained as an independently qualified alternative.

The repository contains no trained skill adapter, training pipeline, downloaded dataset, or autoresearch execution path.

Setup

Requirements are macOS on Apple Silicon, Python 3.12 or 3.13, uv, and bd.

uv sync --all-groups
uv lock --check
uv build

--all-groups includes the pinned qualification candidates. Normal Jack imports remain lazy and do not import either candidate server.

Quality gates

uv run pytest -q
git diff --check
uv run python -m compileall -q src tests

Hardware-gated checks use already verified local material:

JACK_LIVE_HOME="$PWD/.jack" uv run pytest \
  tests/integration/test_optiq_conformance.py \
  tests/integration/test_mola_conformance.py \
  -q -m integration

Gateway contract and live-route checks are:

uv run pytest tests/gateway tests/integration/test_openai_client.py \
  tests/integration/test_gateway_clients.py -q
JACK_GATEWAY_LIVE_HOME="$PWD/.jack" uv run pytest \
  tests/integration/test_gateway_live.py -q -m integration

The live gateway check requires a running daemon, the verified exact base, a selected accepted backend, and at least one installed exact adapter.

Base model

Inspect first. Acquisition is the only command allowed to fetch the pinned revision and always requires explicit confirmation.

uv run jack base inspect --json
uv run jack base acquire --yes --json
uv run jack base verify --json

Runtime startup and generation operate offline and never download missing material.

Backend qualification

uv run jack backend qualify --candidate optiq \
  --base-lock config/base.lock.json --json
uv run jack backend qualify --candidate mola \
  --base-lock config/base.lock.json --json
uv run jack backend list --json
uv run jack backend select --candidate optiq --json

Selection accepts only complete evidence for the current clean repository revision, base lock, dependency set, and candidate profile.

Exclusive model workloads

Jack permits one cooperating model workload per macOS user, even when processes use different JACK_HOME or campaign roots. Live daemon generation, base probing, and backend qualification join this authority automatically. The daemon retains its lease while a live model is resident, including idle time, and releases it only after model cleanup.

Start an authorised campaign, training job, or model evaluation as one foreground process:

uv run jack workload run --kind campaign \
  --owner applescript-pilot -- <foreground-command>

Use training or model-evaluation for the other supported workload kinds. The command must remain in the foreground; daemonising is unsupported because the inherited descriptor defines the lease lifetime.

A contender exits safely with resource.model_workload_busy before model, route, adapter, report, or command mutation. Stop the cooperating owner normally, or let it exit, then retry. Do not delete the persistent lock file, probe PIDs, or signal a process based on diagnostic metadata.

The lease does not block fake generation, daemon status, registry inspection, documentation or dataset/source research, or AppleScript source compilation that performs no model work. Pre-existing direct MLX and legacy autoresearch processes are outside Jack's authority: Jack neither detects nor signals them. Do not disturb such a process; migrate its next run to jack workload run.

Daemon and adapters

Set JACK_HOME when managed state should live somewhere other than $PWD/.jack.

uv run jack daemon start --detach
uv run jack status --json
uv run jack adapter validate /path/to/bundle --json
uv run jack adapter install /path/to/bundle --json
uv run jack adapter list --json
uv run jack runtime inspect --json
uv run jack daemon stop

Installed adapter identities are name@version:

uv run jack generate --prompt "Hello" --json
uv run jack generate --prompt "Hello" \
  --adapter example@1.0.0 --json

Local OpenAI-compatible gateway

The optional gateway is a separate loopback-only process. Start the Jack daemon first, then start the gateway and display its one local bearer token:

uv run jack daemon start --detach
uv run jack gateway start --detach --port 8080
uv run jack gateway token show
uv run jack gateway status --json

Use http://127.0.0.1:8080/v1 as the OpenAI base URL and the displayed token as the API key. Public model names are exact: jack/base selects no adapter, while jack/<name>@<version> selects exactly one installed adapter. GET /v1/models lists only the verified base and installed adapters reported by the daemon. There are no aliases, paths, latest resolution, multi-adapter routes, or silent base fallback.

Revision 1 supports POST /v1/chat/completions with model, plain-string system/user/assistant messages, stream, max_tokens, temperature, and response_format of text or non-streaming json_object. Other OpenAI fields fail explicitly instead of being ignored. Text responses and SSE streams work with OpenAI Python 2.51.0:

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:8080/v1",
    api_key="<output of jack gateway token show>",
)
reply = client.chat.completions.create(
    model="jack/base",
    messages=[{"role": "user", "content": "Hello"}],
)

Hermes Agent can use the same base URL, token, and exact model ID for an auxiliary OpenAI chat model. Honcho can use response_format={"type": "json_object"} as a transport option. That Honcho fixture proves only HTTP and JSON-object compatibility: it does not prove that Jack's memory-extraction output matches Honcho's memory schema, and it does not make the in-flight memory adapter operationally ready.

Ordinary text generation keeps Qwen thinking enabled by default. JSON-object mode adds one fixed instruction and disables thinking for that request at Jack's shared renderer, then accepts only one complete JSON object. It does not repair malformed output, extract fenced JSON, strip thinking tags, retry, use a fallback model, or implement json_schema or tools.

The token is stored at .jack/secrets/openai.token with mode 0600; the directory is mode 0700. The gateway listens only on 127.0.0.1, logs no prompts, completions, tokens, or authorisation headers, and is intended for same-user local clients—not hostile local-user isolation.

If the daemon stops, authenticated health becomes degraded and daemon-dependent requests return service_unavailable; restart the daemon and retry. Correct an exact model name when model_not_found is returned. Stop or rotate the local gateway with:

uv run jack gateway stop
uv run jack gateway token rotate

Core operability

From a clean checkout with the verified base and a current accepted backend:

uv run jack daemon start --detach
uv run jack verify core --json
uv run jack daemon stop

The command runs the protocol/bundle, registry, and routing recovery gates; validates the base and selected live-backend evidence; audits later-scope paths; and writes an immutable CORE-EVIDENCE-V1 report under .jack/reports/core/verification/. Any dirty, stale, missing, blocked, failed, or untested evidence returns non-zero and cannot be promoted to ready.

Project contracts, design, research, and the implementation graph are indexed in docs/README.md. Work is tracked with Beads; run bd prime before changing the project.

About

A local MLX LoRa skill-adapter runtime for Apple Silicon.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages