hf2q 0.1.15

Pure Rust CLI for converting HuggingFace models to hardware-optimized formats and serving them over an OpenAI-compatible API on Apple Silicon
# Getting started: hf2q + OpenCode + local web research

This guide takes a fresh Mac from nothing to a working local coding agent:
hf2q serving a verified Qwen3.8-27B model, OpenCode connected to it, Agentic
Kit installed, and a local search/fetch research stack the agent can use.

You need an Apple Silicon Mac, about 20 GiB of free disk space, Node.js,
`jq`, and `curl`. Google Chrome is required later for the research stack's
browser fallback. The flow was validated on an Apple M5 Max with 128 GiB
unified memory; that names the validation host, not a minimum.

## 1. Install hf2q

```bash
curl -fsSL https://hf2q.us/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
hf2q setup
hf2q doctor
```

`hf2q setup` asks five questions and writes `~/.hf2q/config.toml`; every
answer can be changed later by rerunning it:

- **Quantization** — keep the default `q4_k_m`.
- **Optimize for long agent and tool-use prompts** — answer `Y` for agentic
  coding; it selects the batched scheduler and persists the qualified
  agentic serving profile (repetition penalty and bounded thinking budgets)
  into the configuration, so `hf2q serve` inherits it with no environment
  variables to set.
- **Maximum simultaneous active requests**`4` is a good agentic-coding
  value on a 128 GiB host; `1` is the safe default elsewhere.
- **LAN access**`N` keeps the server on loopback.
- **Port** — keep the default `8081`.

Non-interactive shells can run `hf2q setup --accept-defaults` instead.
`hf2q doctor` confirms the installation is healthy before you download 17 GiB.

## 2. Prepare and serve the model (terminal 1)

```bash
hf2q serve jenerallee78/Qwen3.8-27B-Abliterated-SFT:Q4_K_M
```

That is the whole model preparation command. hf2q first looks for an exact
verified local Q4_K_M—including a manually downloaded file under the managed
model directory. If none exists, it resolves the repository to one immutable
commit, checks disk space, downloads and verifies the exact hosted GGUF, and
stores it below
`$HOME/.local/share/hf2q/models/<owner>__<repo>/<commit>/`.

For this multimodal model, hf2q also reuses or downloads the one matching
`mmproj`, verifies the pair, and loads it automatically. If a valid projector
cannot be established, the server warns and remains available text-only.
Host, port, scheduler, and slot count come from your `hf2q setup` answers.
Leave this foreground terminal open and wait for the listening message.

Use `hf2q serve list` at any time to inspect local receipt-backed, managed,
cached, and loose GGUF options without contacting the Hub.

## 3. Chat with the model (terminal 2)

```bash
hf2q chat
```

Chat discovers the running server on this machine and connects. Ask it
something real—this is the first inference proof. `/status` shows the endpoint
and token statistics; `/quit` exits.

For a one-command standalone check, this performs the same preparation and
starts an owned loopback server automatically. A targeted chat deliberately
owns its exact server even when another local server is already advertised:

```bash
hf2q chat jenerallee78/Qwen3.8-27B-Abliterated-SFT:Q4_K_M
```

## 4. Confirm the managed artifact

```bash
hf2q chat list
```

The Q4_K_M row must name the canonical repository and immutable revision. A
second `serve` or model-targeted `chat` invocation reuses those verified bytes
instead of transferring the payload again.

## 5. Prove vision with one request

Still in terminal 2:

```bash
RED_PNG="iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAb0lEQVR4nO3PAQkAAAyEwO9feoshgnABdLep8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3I8QUNyPEFDcjxBQ3IPanc8OLDQitxAAAAAElFTkSuQmCC"
MODEL_ID="$(curl -fsS http://127.0.0.1:8081/v1/models |
  jq -r '[.data[] | select(.loaded == true) | .id] | first // ""')"
if [ -z "$MODEL_ID" ]; then
  echo "no loaded model yet — wait for terminal 1 to report the model is ready" >&2
  exit 1
fi
RESPONSE="$(jq -n --arg model "$MODEL_ID" --arg image "data:image/png;base64,$RED_PNG" '{
  model: $model,
  messages: [{role: "user", content: [
    {type: "text", text: "What is the dominant color? One word."},
    {type: "image_url", image_url: {url: $image}}
  ]}],
  temperature: 0, max_tokens: 16, stream: false, hf2q_enable_thinking: false
}' | curl -sS http://127.0.0.1:8081/v1/chat/completions \
  -H 'Content-Type: application/json' -d @-)"
echo "$RESPONSE" | jq -er '.choices[0].message.content' | grep -i red || {
  echo "vision check failed; the server said:" >&2
  echo "$RESPONSE" | jq -r '.error.message // .' >&2
  exit 1
}
echo "vision check passed: $MODEL_ID saw red"
```

It must end with `vision check passed`. If it does, text, streaming, and
vision are all proven. Do not continue until both this and the previous
section pass; on failure the block prints the server's own error message —
read that and the server output in terminal 1 before retrying.

## 6. Install OpenCode

```bash
npm install -g opencode-ai
```

## 7. Point OpenCode at hf2q

This merge adds the local hf2q provider and selects its model.
It preserves every existing agent, tool, permission, plugin, instruction,
and MCP setting:

```bash
CONFIG="$HOME/.config/opencode/opencode.json"
MODEL_ID="$(curl -fsS http://127.0.0.1:8081/v1/models |
  jq -er '.data | map(select(.loaded == true)) | .[0].id')"
mkdir -p "$(dirname "$CONFIG")"
[ -f "$CONFIG" ] || printf '{}\n' > "$CONFIG"
cp "$CONFIG" "$CONFIG.$(date +%Y%m%d%H%M%S).bak"

jq --arg model_id "$MODEL_ID" '
  .provider = (.provider // {})
  | .provider.hf2q = ((.provider.hf2q // {}) + {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Local hf2q",
      "options": {"baseURL": "http://127.0.0.1:8081/v1", "apiKey": "local"},
      "models": {
        ($model_id): {
          "name": "Qwen3.8 27B Abliterated SFT via hf2q",
          "tool_call": true,
          "attachment": true,
          "modalities": {"input": ["text", "image"], "output": ["text"]},
          "reasoning": true,
          "interleaved": "reasoning_content",
          "temperature": true,
          "cost": {"input": 0, "output": 0},
          "limit": {"context": 262144, "output": 8192}
        }
      }
    })
  | .model = ("hf2q/" + $model_id)
' "$CONFIG" > "$CONFIG.tmp" && mv "$CONFIG.tmp" "$CONFIG"
```

Try it: `opencode --model "hf2q/$MODEL_ID"`, then ask the agent to list the
current directory. The first launch downloads the provider package
(`@ai-sdk/openai-compatible`), which can take a minute on a fresh machine;
later launches reuse it. The transcript must show a real Bash tool call and
its result — a prose claim that tools exist is not proof.

## 8. Install Agentic Kit

Run this from the Git repository where you want Agentic Kit's project files.
Project setup may replace existing agent configuration, so commit or back up
first.

```bash
npm install -g @pacphi/agentic-kit@next
ak setup
ak setup --opencode
ak sync
ak status
```

The first `ak setup` performs machine and project setup. The second wires the
OpenCode host integration, and `ak sync` upgrades, heals, and verifies the
whole kit. `ak status` should report the memory backend, MCP integrations,
and OpenCode convergence as healthy.

## 9. Install the local research stack

This gives the agent `web_search`, `web_fetch`, `web_crawl`, and `web_extract`
(plus capitalized aliases) backed by local SearXNG and fetch services. Both
services bind to `127.0.0.1` only, restart automatically at login, and need
no API keys. Google Chrome is required for the JavaScript and anti-bot fetch
fallbacks:

```bash
if [ ! -d '/Applications/Google Chrome.app' ]; then
  brew install --cask google-chrome
fi

curl -fsSL \
  https://raw.githubusercontent.com/robertelee78/hf2q/main/scripts/install_opencode_web_stack.sh \
  | bash
```

If `brew` is missing, install Chrome from <https://www.google.com/chrome/>
first. The installer pins every dependency, backs up changed files, and
verifies the services live before exiting — a successful run is the
installation proof. Restart OpenCode once afterward so it loads the plugin.

## 10. Use the full stack

```bash
opencode
```

Ask it to research something current, for example a library released this
month. The transcript must contain a real `web_search` tool call with fetched
page content, and ordinary Bash/file tools must work in the same session.
That transcript is the end-to-end acceptance proof.

To stop the model server, press Ctrl-C in terminal 1. To manage the research
services, rerun the installer with `--status`, `--disable`, `--enable`, or
`--uninstall` (removal moves everything into a timestamped Trash folder; the
model, hf2q, OpenCode, and Agentic Kit are untouched).

## Troubleshooting

- **Server fails to start or generate** — read the output in terminal 1, then
  repeat sections 4 and 5.
- **Port 8081 already in use** — something else is listening; inspect with
  `lsof -nP -iTCP:8081 -sTCP:LISTEN`, or rerun `hf2q setup` and pick another
  port (use the same port in section 7's `baseURL`).
- **Projector binding failed** — read the automatic-projector warning, then run
  `hf2q serve list`. Repeating the model-targeted serve command rechecks local
  authority and the exact repository revision; it never guesses a projector
  from an unrelated file.
- **OpenCode has no tools** — run `opencode debug config` and remove any
  agent-level `permission: "deny"` or `tools: {"*": false}` left by other
  configuration; this guide writes neither.
- **Agentic Kit unhealthy** — run `ak sync`, then `ak status`.
- **Research tools missing** — restart OpenCode, then rerun the installer
  with `--status` to see which check fails.