Metadata-Version: 2.4
Name: drydock-cli
Version: 3.0.58
Summary: Drydock — a local, provider-agnostic terminal coding agent for local LLMs
Author: Frank Bobe III
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/fbobe321/drydock
Project-URL: Repository, https://github.com/fbobe321/drydock
Project-URL: Issues, https://github.com/fbobe321/drydock/issues
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: openai>=1.0
Requires-Dist: textual>=0.80
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-timeout; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: pyright; extra == "dev"
Dynamic: license-file

# ⚓ Drydock

A local-first, provider-agnostic **terminal coding agent** for your own LLM.
No accounts, no telemetry, no cloud — the only outbound calls are to the model
endpoint you configure and (optionally) the web-search tools you invoke.
Primary target: **dense Gemma-4-31B** (QAT, 64K) served by llama.cpp on a
single workstation.

> **v3 — clean-room rebuild.** Drydock is being rebuilt as an original,
> Apache-2.0 codebase owned end to end (no upstream fork). Every release is
> gated by a credential-exfiltration scanner that blocks anything reaching
> off-box. See [`HARNESS_DESIGN.md`](HARNESS_DESIGN.md) and
> [`docs/PRD.md`](docs/PRD.md).

## Why

A coding agent should build real projects from your machine without sending
your code or credentials anywhere. Drydock runs entirely against a local
model, feels like a first-class terminal agent, and keeps its data plane on
your box.

## Status

Shipping. Published on PyPI as **`drydock-cli`** (v3.x). The Textual TUI is the
default surface: a scrolling transcript with streamed assistant text, collapsible
tool cards, collapsible reasoning ("thinking") cards, a live nautical activity
line, and a multi-line prompt. The agent loop, OpenAI-compatible provider,
two-tier compaction, and the full agentic toolset (below) are in, with Gemma
reliability hardening verified hands-on.

## Capabilities

A full agentic CLI harness — every tool below is clean-room and dependency-free
(nothing beyond `openai` + `textual`), and the model calls them autonomously:

- **Files & shell** — `Read` (with a structure index for huge files), `Write`,
  `Edit`, `Bash`, `Glob`, `Grep`.
- **Version control** — `GitStatus`, `GitDiff`, `GitLog`, `GitCommit`
  (structured + truncated; commit is local and reversible).
- **Internet** — `WebSearch` + `WebFetch` (DuckDuckGo; offline-safe).
- **Knowledge base (GraphRAG)** — build a local entity-graph index from your
  docs/code with `/graphrag build <path>`; the agent retrieves from it via the
  read-only `Knowledge` tool.
- **Multi-agent** — `Dispatch` runs several read-only sub-agents in parallel;
  `task` runs one — each in a fresh context, for focused investigation.
- **MCP** — connect to Model Context Protocol servers (`~/.drydock/mcp.json`);
  their tools appear as `mcp__<server>__<tool>`. List them with `/mcp`.
- **Skills** — reusable `/<name>` commands authored as markdown in
  `~/.drydock/skills/` (or `<project>/.drydock/skills/`); `$ARGS` substitution.
- **Loops** — `/loop <count> <prompt>` runs a prompt iteratively (Esc stops).

## Install

```bash
pip install drydock-cli
drydock
```

Requires Python 3.11+. From source instead:
`git clone https://github.com/fbobe321/drydock-v3.git && cd drydock-v3 && pip install -e .`

On first launch with no config, Drydock probes localhost for a running local
LLM (llama.cpp/vLLM `:8000`, Ollama `:11434`, LM Studio `:1234`) and wires up
the first one it finds — no account or API-key prompt. Override anytime with
`--model` / `--provider` / `--base-url` or `~/.drydock/config.toml`.

## Using it

Type a task and press **Enter**. Drydock reads/writes/edits files and runs
commands to do the work, showing each as a collapsible tool card.

- **Enter** submits · **Ctrl+J** newline (multi-line prompts)
- **↑ / ↓** recall command history (persists across sessions)
- **PgUp / PgDn** (and **Ctrl+Home/End**) scroll the transcript
- **Ctrl+O** expand/collapse tool output · **drag + Ctrl+C** copy a selection
- **Ctrl+C twice** (or **Ctrl+D**, `/quit`) to exit
- A live activity line shows progress while it works:
  `◡ Keelhauling…  (12s · ↓ 6.2k tokens · thinking with high effort)`
- Submit while it's working and the prompt **queues** (drains in order)
- Slash commands: `/model` · `/cwd` · `/undo` (revert last write) · `/back`
  (rewind last turn) · `/status` · `/compact` (shrink context) · `/graphrag`
  (build/query a knowledge base) · `/skills` (list your `/<name>` skills) ·
  `/loop` (repeat a prompt) · `/mcp` (list MCP servers) · `/clear` · `/help` ·
  `/quit`

It honors `AGENTS.md` / `DRYDOCK.md` in the working directory for project
conventions.

## Safety

Two tiers, plus advisory guards — all designed so legitimate work is never
blocked:

- **Catastrophic denylist** — commands like `rm -rf /`, `mkfs`, raw block-device
  writes, and fork bombs are refused outright (never run).
- **Approval prompt** — sensitive-but-legitimate commands (`sudo`, package
  installs, network fetches, `git push`) pause for **Allow / Always / Deny**.
- **Advisory write guards** — Drydock flags (never blocks) Python syntax errors,
  stub-only files, imports of sibling modules that don't exist yet, bare
  `raise` outside an except, and refuses to write git conflict-marker content.

Point it at a local OpenAI-compatible endpoint (e.g. llama.cpp's `server-cuda`
serving Gemma-4-31B). The web tools (`WebSearch`/`WebFetch`) are read-only and
degrade cleanly offline; the release scanner allowlists only the search backend.

## Model server (reference setup)

Drydock is provider-agnostic, but it's tuned and measured against this rig:

- **Model:** dense **Gemma-4-31B** (QAT `Q4_K_XL` GGUF), served by
  `ghcr.io/ggml-org/llama.cpp:server-cuda` with `--jinja`. Swapped from the
  26B-A4B MoE, whose ~4B active params caused fatal agentic tool-loops; the
  dense 31B is loop-free (slower, but it finishes).
- **GPUs:** 2× NVIDIA RTX 4060 Ti 16GB, **tensor-split** across both cards
  (`--tensor-split 1,1`) so the 31B weights fit.
- **Context:** 64k (`-c 65536`) with `q8_0` KV-cache quantization
  (`-ctk q8_0 -ctv q8_0`); set `context_limit` in `~/.drydock/config.toml` to
  match your server's `-c`.
- **Throughput:** ~15 tok/s decode (tensor-split 31B). Faster single-GPU
  options exist if you drop to a smaller model.
- **Provider-agnostic:** any OpenAI-compatible endpoint (llama.cpp, vLLM,
  Ollama, LM Studio) works — point `--base-url` at it.

## Principles

- **Clean provenance** — original code only; nothing copied from any other
  project.
- **Local-only data plane** — no telemetry, no phone-home, no hardcoded
  third-party hosts, no credential transmission.
- **Advisory, never blocking** — loop/safety mechanisms inject better
  context; they never hard-stop legitimate work.
- **The scanner is law** — `scripts/security_scan.py` gates every release.

## Security scan

```bash
python3 scripts/security_scan.py drydock/      # scan the source tree
python3 scripts/security_scan.py dist/*.whl    # scan a built wheel
```

Exit 2 (HIGH finding) blocks a release.

## License

Apache-2.0, © 2026 Frank Bobe III. See [`LICENSE`](LICENSE) and
[`NOTICE`](NOTICE).
