Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b9c9133
fix: stabilize flaky tests and repair stale ecosystem docs
Patel230 Sep 14, 2026
8caa89b
refactor!: remove sandbox, isolation, and container execution
Patel230 Sep 14, 2026
9030b99
refactor!: remove harrier, kestrel, merlin, shrike, and swift engines
Patel230 Sep 14, 2026
5f4104e
refactor(cli): group root commands into a curated help surface
Patel230 Sep 14, 2026
47b6132
docs: align README and guides with engine and sandbox removal
Patel230 Sep 14, 2026
8411379
test(acp): widen image-prompt test deadline to avoid -race flake
Patel230 Sep 14, 2026
6653b25
chore(compat): track eyrie (not falcon) for pin-drift checks
Patel230 Sep 14, 2026
ca30c7b
style: apply gofumpt across the tree
Patel230 Sep 14, 2026
7f21b0c
test(token): cover the local token engine
Patel230 Sep 14, 2026
e8c0f0e
refactor: purge stale engine naming and wire the local memory HUD
Patel230 Sep 14, 2026
3434df4
fix(compact): guard compression reduction ratio against zero tokens
Patel230 Sep 14, 2026
6af494a
docs: retire multi-engine references in current-facing docs
Patel230 Sep 14, 2026
55dd8cd
ci: drop the sandbox-image job and fix stale path references
Patel230 Sep 14, 2026
b1fe6b6
chore: align compatibility matrix and platform capabilities with the …
Patel230 Sep 14, 2026
ca86e0a
fix(mcp): make memory and compress tools actually work
Patel230 Sep 14, 2026
c5680f5
refactor(harness,contracts): drop removed-engine assumptions
Patel230 Sep 14, 2026
e9fd573
docs(code): purge remaining engine-name references in comments
Patel230 Sep 14, 2026
fd59cd4
fix(review): restore 'hawk review run' on Hawk's own review pipeline
Patel230 Sep 14, 2026
68f7b36
test: drop stale shrike guards and neutralize engine fixtures
Patel230 Sep 14, 2026
aa8bc15
feat(token,tool): real structural compression and working SpecLinks
Patel230 Sep 14, 2026
389505f
fix(tool): wire CodeSearch to the local semantic index
Patel230 Sep 14, 2026
579c8b2
feat(vim,mcp): implement undo and drop the unservable session resource
Patel230 Sep 14, 2026
8650ce1
refactor(cli)!: remove undocumented niche commands
Patel230 Sep 14, 2026
4e2b453
style: apply gofumpt v0.10.0 to tool_service_test
Patel230 Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 8 additions & 9 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
* @GrayCodeAI/maintainers

# Engine and core agent loop
/engine/ @GrayCodeAI/core-team
/cmd/ @GrayCodeAI/core-team
/tool/ @GrayCodeAI/core-team
/session/ @GrayCodeAI/core-team
/internal/engine/ @GrayCodeAI/core-team
/cmd/ @GrayCodeAI/core-team
/internal/tool/ @GrayCodeAI/core-team
/internal/session/ @GrayCodeAI/core-team

# Sandbox / container / permissions (security-sensitive)
/sandbox/ @GrayCodeAI/security-team
/permissions/ @GrayCodeAI/security-team
/container/ @GrayCodeAI/security-team
/auth/ @GrayCodeAI/security-team
# Permissions and credential handling (security-sensitive)
/internal/permissions/ @GrayCodeAI/security-team
/internal/credentials/ @GrayCodeAI/security-team
/internal/governance/ @GrayCodeAI/security-team

# CI / release / build tooling
/.github/ @GrayCodeAI/devops-team
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ concurrency:

env:
GO_VERSION: "1.26.6"
# Module resolution: the committed third_party/modproxy serves GrayCodeAI pins
# whose repositories no longer exist (and which the public proxy never cached,
# so it 404s them). Public modules resolve from proxy.golang.org as usual;
# direct-VCS fallback is retained for anything else. Do NOT set GOPRIVATE for
# GrayCodeAI paths: it would force direct git and bypass the committed proxy.
GOPROXY: "file://${{ github.workspace }}/third_party/modproxy,https://proxy.golang.org,direct"
# Module resolution: eyrie is the only GrayCodeAI module dependency and it is
# published on the public proxy. Direct-VCS fallback is retained for anything
# else.
GOPROXY: "https://proxy.golang.org,direct"
# CI must resolve the dependency versions pinned in go.mod/go.sum, not whatever
# happens to sit in the sibling checkouts that the committed go.work points at.
# Go's reference is explicit that a committed go.work "may cause a continuous
Expand Down
80 changes: 0 additions & 80 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ on:
branches: [main]
paths:
- "Dockerfile"
- "internal/sandbox/container_version"
- "internal/sandbox/sandbox.Dockerfile"
- "**.go"
- "go.mod"
- "go.sum"
Expand Down Expand Up @@ -234,81 +232,3 @@ jobs:
docker buildx imagetools create -t "$tag" $src
fi
done

sandbox-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

- name: Read sandbox image version
id: sandbox-version
shell: bash
run: echo "tag=$(tr -d '[:space:]' < internal/sandbox/container_version)" >> "$GITHUB_OUTPUT"

- name: Set up QEMU
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build sandbox image for scan
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: internal/sandbox
file: internal/sandbox/sandbox.Dockerfile
platforms: linux/amd64
push: false
load: true
tags: ${{ env.REGISTRY }}/graycodeai/hawk-sandbox:scan
cache-from: type=gha,scope=hawk-sandbox
cache-to: type=gha,mode=max,scope=hawk-sandbox

- name: Scan sandbox image
uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514
with:
version: v0.70.0
cache: true
- name: Run Trivy sandbox scan (sarif)
shell: bash
run: |
# This image gate covers the Debian OS package surface. npm's
# bundled CLI dependency tree is pinned by the Node base image and
# reviewed separately from the runtime OS scan.
trivy image \
--severity CRITICAL,HIGH \
--ignore-unfixed \
--ignorefile "${GITHUB_WORKSPACE}/.trivyignore" \
--vuln-type os \
--format sarif \
--output trivy-sandbox-image.sarif \
--exit-code 1 \
${{ env.REGISTRY }}/graycodeai/hawk-sandbox:scan

- name: Build and publish public sandbox image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: internal/sandbox
file: internal/sandbox/sandbox.Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.REGISTRY }}/graycodeai/hawk-sandbox:${{ steps.sandbox-version.outputs.tag }}
${{ env.REGISTRY }}/graycodeai/hawk-sandbox:latest
cache-from: type=gha,scope=hawk-sandbox
cache-to: type=gha,mode=max,scope=hawk-sandbox

# Publish the sandbox scan to GitHub code scanning. PRs still run the
# scan; they just do not publish the release image artifacts.
- name: Upload sandbox image scan results
if: always()
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
with:
sarif_file: trivy-sandbox-image.sarif
3 changes: 1 addition & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ jobs:
goreleaser:
runs-on: ubuntu-latest
env:
# Deleted-repos pins resolve from the committed file proxy (see ci.yml).
GOPROXY: "file://${{ github.workspace }}/third_party/modproxy,https://proxy.golang.org,direct"
GOPROXY: "https://proxy.golang.org,direct"
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down
79 changes: 27 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@

## Why hawk

hawk is an AI-powered coding agent that lives in your terminal. It reads your codebase, writes and edits files, runs tests, and manages git — all through natural language. Unlike IDE-bound tools, hawk works over SSH, in containers, and on any machine with a shell.
hawk is an AI-powered coding agent that lives in your terminal. It reads your codebase, writes and edits files, runs tests, and manages git — all through natural language. Unlike IDE-bound tools, hawk works over SSH and on any machine with a shell.

**Developer path:** one machine, keychain credentials, local memory. Run `hawk path` to check readiness.

- **Model-agnostic** — supports many first-class providers through [eyrie](https://github.com/GrayCodeAI/eyrie) (the exact count is dynamic — see `hawk --help`), including Anthropic, OpenAI, Gemini, Fireworks AI, Concentrate AI (pay-as-you-go), DeepSeek, and Ollama
- **Zero CGO** — single static binary, cross-compiled for linux/darwin/windows on amd64/arm64
- **Privacy-first** — your code never leaves your machine except to the LLM API you choose
- **Docker-only execution** — agent commands run in an isolated container and
fail closed when Docker is unavailable
- **Runs anywhere** — host execution on any machine with a shell, including over SSH
- **Extensible** — 40+ built-in tools, MCP server support, community skill registry

## Status
Expand Down Expand Up @@ -81,16 +80,12 @@ go build -o hawk ./cmd/hawk
./hawk path
```

**Docker is required before your first run.** Hawk executes agent commands inside a
container — there is no host-execution fallback (fail-closed). Start the Docker daemon
first, then run `hawk path` (or `hawk doctor`) to see an ordered onboarding
checklist: daemon running → sandbox image cached → registry reachable → local build.
Hawk automatically uses the versioned public `graycodeai/hawk-sandbox` image;
when it is not local, Hawk pulls it anonymously, and if the registry is unavailable
it builds the bundled sandbox image locally through Docker.
**No Docker or container runtime is required.** Hawk executes agent commands
directly on the host. Run `hawk path` (or `hawk doctor`) to see an onboarding
checklist: credentials → model → catalog → ecosystem.

See [docs/SECURITY-DEVELOPER.md](docs/SECURITY-DEVELOPER.md) for the credential model and
the sandbox checklist. Do not put API keys in shell env or `.env` for hawk.
See [docs/SECURITY-DEVELOPER.md](docs/SECURITY-DEVELOPER.md) for the credential model.
Do not put API keys in shell env or `.env` for hawk.

Optional for contributors:

Expand Down Expand Up @@ -124,7 +119,6 @@ and lifecycle events:
```bash
hawk graph export
hawk graph export <session-id>
hawk graph export <session-id> --swift-checkpoint abc123def456
hawk graph export --mission-dir /path/to/mission

# Explicitly privacy-normalize and sync the graph for a connected cloud project
Expand All @@ -138,17 +132,11 @@ set `HAWK_CLOUD_URL` to your Hawk Cloud worker URL before running
will reject a device token.

The export contains metadata and hashes, not prompts, tool arguments/results,
policy reasons, verification evidence, or runtime output. Swift remains
available separately as `hawk swift graph export`. Persisted chat sessions
automatically append privacy-safe permission, enabled approval-gate, and
`VerifyPlanExecution` summaries for subsequent graph exports. Harrier memory
subgraphs and Hawk code-index chunks actually selected for inference are also
journaled as metadata-only knowledge nodes and linked to the session. Merlin's
observed bridge path similarly journals bounded, metadata-only report/finding
quality subgraphs. Kestrel exposes the same observed bridge boundary for
metadata-only code-review quality subgraphs. Mission runs also persist a
portable `mission-graph.json`; the mission form is validated and synchronized
explicitly with the `--mission-dir` variants above.
policy reasons, verification evidence, or runtime output. Persisted chat
sessions automatically append privacy-safe permission, enabled approval-gate,
and `VerifyPlanExecution` summaries for subsequent graph exports. Mission runs
also persist a portable `mission-graph.json`; the mission form is validated and
synchronized explicitly with the `--mission-dir` variants above.

### Multi-Agent Mission Mode (optional)

Expand Down Expand Up @@ -178,7 +166,6 @@ spec-driven workflow gate — rather than one merged permission mode:
```text
/autonomy
/autonomy tier <scout|builder|operator|autonomous>
/autonomy sandbox <strict|workspace|off>
/autonomy dry-run <on|off>
/autonomy allow <rule>
/autonomy deny <rule>
Expand All @@ -200,10 +187,6 @@ The model is:
- `Builder`
- `Operator`
- `Autonomous`
- `Sandbox` controls the execution boundary:
- `strict`
- `workspace`
- `off`
- `Dry-run` is a kill switch: denies every tool call unconditionally,
regardless of tier or spec stage.
- `Rules` control explicit allow/deny exceptions.
Expand Down Expand Up @@ -326,7 +309,6 @@ hawk --provider openai --model gpt-4o # Override provider
# Inside the TUI
/autonomy
/autonomy tier builder
/autonomy sandbox workspace
/autonomy allow Bash(git:*)
/autonomy deny Bash(rm -rf *)
/autonomy save project
Expand All @@ -339,7 +321,6 @@ hawk --provider openai --model gpt-4o # Override provider
```bash
hawk -p "explain this repo" # Print response, exit
hawk -p "fix tests" --allowed-tools "Bash(go test:*) Edit Read"
hawk -p "review this repo" --permission-mode plan --sandbox workspace
hawk exec "refactor auth module" # Full engine, non-interactive
hawk exec --auto full "add error handling" # Full autonomy
hawk exec --worktree "add rate limiting" # Isolated branch
Expand All @@ -349,21 +330,19 @@ hawk exec --agent reviewer "review last commit" # Custom persona
### Diagnostics & ecosystem

```bash
hawk path # Developer path readiness (setup + security + sandbox)
hawk doctor # Full health report (eyrie + harrier + shrike panel)
hawk path # Developer path readiness (setup + security)
hawk doctor # Full health report (eyrie + token pipeline panel)
hawk ecosystem # Ecosystem panel only
hawk harrier # Persistent memory graph
hawk harrier search <query> # Search harrier memories
hawk preflight # Quick ready-to-chat check
make path # Developer path verification
make smoke # Build + quick verification script
```

See [docs/SECURITY-DEVELOPER.md](docs/SECURITY-DEVELOPER.md).

See [docs/ecosystem-message-flow.md](docs/ecosystem-message-flow.md) for how eyrie, harrier, and shrike connect during a chat session, and [docs/ECOSYSTEM-WIRING.md](docs/ECOSYSTEM-WIRING.md) for the current-to-proposed architecture and repository boundaries.
See [docs/ecosystem-message-flow.md](docs/ecosystem-message-flow.md) for how eyrie connects during a chat session, and [docs/ECOSYSTEM-WIRING.md](docs/ECOSYSTEM-WIRING.md) for the current-to-proposed architecture and repository boundaries.

In the TUI: `/path`, `/ecosystem`, `/harrier`, `/harrier search <query>`, `/memory` (AGENTS.md).
In the TUI: `/path`, `/ecosystem`, `/memory` (AGENTS.md).

### Daemon Mode

Expand Down Expand Up @@ -428,7 +407,7 @@ hawk/
│ ├── session/ # Persistence (JSONL, WAL, checkpoints)
│ ├── api/ # HTTP API server
│ ├── daemon/ # Background HTTP/SSE server
│ ├── sandbox/ # Command isolation (landlock, seccomp, docker)
│ ├── token/ # Token counting, compression, usage, secrets
│ ├── permissions/ # User approval system with auto-learning
│ ├── hooks/ # Event-driven plugin system
│ ├── mcp/ # Model Context Protocol client
Expand All @@ -437,7 +416,7 @@ hawk/
│ ├── observability/ # Analytics, metrics, logging, tracing
│ ├── resilience/ # Circuit breaker, rate limiting, retries
│ ├── feature/ # eval, fingerprint, voice, IDE integration
│ ├── bridge/ # External bridges (kestrel, merlin, sessioncapture)
│ ├── bridge/ # External bridges (sessioncapture)
│ ├── provider/ # Provider routing
│ └── system/ # Bus, cron, retention, shutdown
├── docs/ # Architecture, security, integration docs
Expand All @@ -454,20 +433,17 @@ hawk is the main CLI/product and integrates these GrayCodeAI repositories in
three runtime layers plus optional tooling/platform services:

- **Primary product:** **hawk** is the only end-user product surface in this ecosystem.
- **Support engines mounted by Hawk:** **eyrie**, **harrier**, **shrike**, **swift**, **kestrel**, **merlin**. Hawk imports or shells into these engines behind its own command surface.
- **Shared foundations:** **falcon**
provides shared MCP server scaffolding.
- **Provider engine mounted by Hawk:** **eyrie** is the LLM provider runtime, consumed through its stable engine facade.
- **API consumers/extensions:** **graycode-skills** provides Hawk skills
installed on demand (`hawk skills install`).
- **Tooling/platform:** **owl** visualizes the generated ecosystem graph;
**graycode-platform** contains the optional web/BFF/Hawk Cloud plane and is
outside the Hawk Go runtime graph.
- **Tooling/platform:** **graycode-platform** contains the optional web/BFF/Hawk
Cloud plane and is outside the Hawk Go runtime graph.

Local development uses:

- **`go.mod` modules:** pinned requirements for the support engines
- **`go.mod` modules:** pinned requirements for `eyrie`
- **Workspace + `go.work`:** sibling support repos are cloned in the `graycode-eco` workspace (as `../<repo>`); `go.work` resolves the module paths to those local checkouts
- **Module-mode builds:** standalone / Docker builds resolve the pinned `go.mod` versions from the module proxy (no workspace)
- **Module-mode builds:** standalone builds resolve the pinned `go.mod` versions from the module proxy (no workspace)

Cross-repo contracts now live in `internal/contracts` (vendored from the
removed `github.com/GrayCodeAI/eagle` module) so support repos do not depend
Expand Down Expand Up @@ -496,13 +472,12 @@ You may keep a **personal** parent **`go.work`** that lists alternate clones on

`ecosystem.yaml` is the canonical inventory of repositories cloned as
siblings in this local workspace; tooling reads it rather than carrying its
own repo-name list. `harrier`, `shrike`, `swift`, `kestrel`, `merlin` and
`falcon` above are consumed as pinned `go.mod` module dependencies rather
than local workspace clones, so they are not listed there.
own repo-name list. `eyrie` is the only Go module dependency outside this
repo; it is consumed through its stable engine facade.

For the consolidated repo map and the current-vs-proposed architecture diagrams, see [docs/architecture/hawk-current-vs-proposed.md](docs/architecture/hawk-current-vs-proposed.md).
For execution-graph ownership, automatic capture seams, export/sync commands,
and the Swift correlation contract, see
For execution-graph ownership, automatic capture seams, and export/sync
commands, see
[docs/architecture/execution-graph.md](docs/architecture/execution-graph.md).

## Development
Expand Down
1 change: 0 additions & 1 deletion cmd/autocomplete.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,6 @@ func (ac *Autocompleter) completeFlags(prefix string) []Suggestion {
{"--max-budget-usd", "Maximum API spend"},
{"--system-prompt", "System prompt to use"},
{"--output-format", "Output format"},
{"--sandbox", "Permission sandbox"},
{"--auto-commit", "Auto-commit changes"},
{"--watch", "Watch for file changes"},
{"--vibe", "Vibe coding mode"},
Expand Down
18 changes: 0 additions & 18 deletions cmd/autonomy_tiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"fmt"
"image/color"
"strings"

lipgloss "charm.land/lipgloss/v2"
"github.com/GrayCodeAI/hawk/internal/engine"
Expand Down Expand Up @@ -131,23 +130,6 @@ func formatAutonomyTierMessage(level engine.AutonomyLevel) string {
return fmt.Sprintf("Autonomy %s — %s", renderAutonomyTierLabel(level), autonomyTierDescription(level))
}

func autonomyLevelForTierName(name string) engine.AutonomyLevel {
switch strings.TrimSpace(name) {
case "Scout":
return engine.AutonomyBasic
case "Builder":
return engine.AutonomySemi
case "Operator":
return engine.AutonomyFull
case "Autonomous":
return engine.AutonomyYOLO
default:
return DefaultContainerAutonomy
}
}

// autonomyFromSettings maps settings.json autonomy (1–4) to a tier level.
// 0 or unset leaves session default until the container is ready.
func autonomyFromSettings(n int) engine.AutonomyLevel {
switch n {
case 1:
Expand Down
3 changes: 0 additions & 3 deletions cmd/bg_sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,6 @@ func collectDaemonArgs() []string {
if provider != "" {
args = append(args, "--provider", provider)
}
if sandboxFlag != "" {
args = append(args, "--sandbox", sandboxFlag)
}
if dangerouslySkipPermissions {
args = append(args, "--dangerously-skip-permissions")
}
Expand Down
Loading
Loading