Skip to main content

Threadstone

CI PyPI License: MIT Platform: macOS Apple Silicon Python 3.13+ Local-first

Threadstone is offline terminal chat for local MLX language models on Apple Silicon. It starts a local mlx-vlm server for the model you choose, streams the answer into your terminal, keeps the conversation usable across crashes, and shuts the server down when you leave.

The useful part is ownership. The network is only for setup and model downloads. After that, chat runs against local snapshots with Hugging Face offline flags, no telemetry, no hosted API, and no account.

Quick Start

Requirements: macOS 14 or newer, Apple Silicon, Python 3.13+, Homebrew, and about 12 GB for the default model set.

git clone https://github.com/gabrimatic/threadstone.git
cd threadstone
./setup.sh

setup.sh creates ~/mlx-env, installs the MLX runtime, downloads the configured Qwen model snapshots, installs the threadstone CLI, and writes shell helpers for oracle, forge, and quench.

pip install threadstone installs only the CLI. It still needs the MLX runtime in ~/mlx-env (or the venv named by THREADSTONE_VENV) and the model snapshots that setup.sh provides; threadstone --doctor reports what is missing.

Start a chat:

oracle
oracle 4B
oracle "be terse" 2B

Use the installed CLI directly:

threadstone --list-models
threadstone --doctor
threadstone "answer like a systems engineer" 9B

Local Runtime

Threadstone uses the network during setup. Runtime chat stays on localhost and local model files.

Path Runtime scope
Model snapshots Hugging Face cache on disk
Inference server mlx_vlm.server on 127.0.0.1
Chat client Python stdlib HTTP and SSE client
Session history In memory for the current terminal session
Session restore ~/.cache/threadstone/ per model and terminal tab
Telemetry Disabled through environment flags

Offline guard:

HF_HUB_OFFLINE=1
TRANSFORMERS_OFFLINE=1
HF_DATASETS_OFFLINE=1
HF_HUB_DISABLE_TELEMETRY=1
HF_HUB_DISABLE_IMPLICIT_TOKEN=1
HF_TOKEN=
DO_NOT_TRACK=1
DISABLE_TELEMETRY=1
ANONYMIZED_TELEMETRY=0

Commands

Inside chat:

Command Effect
/read <path> Attach a file or directory listing to the next message
/drop Cancel the pending attachment
/history Show recent visible conversation turns
/restore Restore the saved session for this terminal tab
/clear Reset conversation state and pending attachment
/help Show in-session commands
exit / quit Stop the chat and terminate the owned server

Shell helpers from setup.sh:

Command Effect
oracle [prompt] [size] Start chat with an owned server
forge [size] Start a manual background server
`quench [size all]`
threadstone --doctor Check platform, venv, model snapshots, offline flags, and port state
threadstone --list-models Print configured models, ports, context limits, and paths

Models

Default models are 4-bit MLX snapshots from mlx-community.

Key Model Thinking Max tokens Context trim
9B Qwen3.5-9B-MLX-4bit Yes 4096 8000
4B Qwen3.5-4B-MLX-4bit Yes 4096 8000
2B Qwen3.5-2B-MLX-4bit No 2048 4000
0.8B Qwen3.5-0.8B-MLX-4bit No 1024 2000

Each model has its own default port, memory estimate, context threshold, and response budget in threadstone/config.py.

Behavior

Threadstone owns the server lifecycle for normal chat.

  • Port recovery: if the default port is busy, Threadstone scans forward and starts the model on the next available localhost port.
  • RAM guard: startup checks free and reclaimable memory before launching a model, including other reachable model servers.
  • Crash recovery: if the server disappears during a turn, Threadstone restarts it and resends the pending message.
  • Interrupt safety: Ctrl-C mid-answer keeps the partial output; Ctrl-C while a request is in flight cancels the turn. The chat survives both.
  • Thinking models: reasoning streams dimmed until </think>, then the final answer prints normally and only the final answer is sent back in later history.
  • Attachments: /read accepts text files and directory listings, rejects non-regular files, rejects binary-looking content, and caps file payloads at 50 KB.
  • Context trimming: old turns are trimmed when the approximate context crosses the configured threshold while preserving valid role alternation.

Architecture

oracle / threadstone
    |
    v
threadstone/__init__.py
    |-- argument parsing, doctor, REPL, streaming, history
    |-- ServerManager starts and monitors mlx_vlm.server
    |-- /read attaches bounded local text context
    |
    v
threadstone/config.py
    |-- model registry, ports, limits, memory estimates
    |-- snapshot resolution from the Hugging Face cache
    |-- offline environment guard

Files:

File Role
threadstone/__init__.py CLI, server lifecycle, chat loop, streaming parser, attachment handling
threadstone/config.py Model registry, offline env, runtime limits, validation
setup.sh One-time macOS installer and shell helper setup
tests/ Unit coverage for parsing, streaming, history, config, attachments, and snapshots

Development

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
ruff check .
mypy
python3 -m unittest discover -s tests -t . -v
python3 -m build --sdist --wheel
python3 -m twine check --strict dist/*

Run the CLI without starting a model:

threadstone --version
threadstone --list-models

Run the local setup check after ./setup.sh:

threadstone --doctor --all-models

Package Release

Threadstone is a Python package, so the package registry is PyPI, not pub.dev. pub.dev is for Dart and Flutter packages.

Release path:

  1. Bump the version in pyproject.toml and VERSION in threadstone/__init__.py, and add a CHANGELOG.md entry.
  2. Push to main and wait for CI to pass.
  3. Publish a GitHub release with a vX.Y.Z tag that matches the package version.
  4. The release workflow reruns CI on the tagged commit, checks the tag against the package version, builds the sdist and wheel, and publishes to PyPI through Trusted Publishing.

PyPI Trusted Publishing must be configured for:

Field Value
Owner gabrimatic
Repository threadstone
Workflow release.yml
Environment pypi

Security

Runtime chat is local by design, but model files and dependencies still come from external package and model hosts during setup.

Report vulnerabilities through GitHub private vulnerability reporting. Do not open a public issue for security reports.

Metadata

Release files for threadstone 1.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for threadstone 1.2.2
File Size Uploaded
threadstone-1.2.2.tar.gz 28.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for threadstone 1.2.2
File Interpreter ABI Platform
threadstone-1.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 47.5 kB

Release files / threadstone-1.2.2.tar.gz

Download URL threadstone-1.2.2.tar.gz
Size 28.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ff3e5cdf2e9fb04c589ef29dc88d65228643065ab7dda52751b83278ef56485b
BLAKE2b-256 checksum
How to use checksums
64d8fc7424d97337ce0310dea5b9acac373bb4bf0e15311fb16bbe027a9889c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.

Transparency log

Release files / threadstone-1.2.2-py3-none-any.whl

Download URL threadstone-1.2.2-py3-none-any.whl
Size 19.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bd32a1d5094b5e0d25f8c672c8878325e29566eba56579a5e0501266e0de6ad1
BLAKE2b-256 checksum
How to use checksums
f64c66ba0f9d564167c39b06445f1e93ea5e85dee0b0a70303ef17f90cd43dc2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.2.2 This release

2 release files

1.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page