{"id":44722321,"url":"https://github.com/sandst1/nav","last_synced_at":"2026-04-17T23:06:24.421Z","repository":{"id":338630969,"uuid":"1157505159","full_name":"sandst1/nav","owner":"sandst1","description":"a minimalistic coding agent","archived":false,"fork":false,"pushed_at":"2026-03-26T10:44:40.000Z","size":2564,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T03:57:18.765Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://sandst1.github.io/nav/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandst1.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-13T22:33:48.000Z","updated_at":"2026-03-26T10:44:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sandst1/nav","commit_stats":null,"previous_names":["sandst1/nav"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/sandst1/nav","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandst1%2Fnav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandst1%2Fnav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandst1%2Fnav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandst1%2Fnav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandst1","download_url":"https://codeload.github.com/sandst1/nav/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandst1%2Fnav/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31949435,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-17T17:29:20.459Z","status":"ssl_error","status_checked_at":"2026-04-17T17:28:47.801Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-15T16:12:58.952Z","updated_at":"2026-04-17T23:06:24.408Z","avatar_url":"https://github.com/sandst1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nav\n\nMinimalist coding agent with hashline-based editing.\n\n**Built for [Bun](https://bun.sh)** — leverages Bun's native APIs for optimal performance.\n\nSee [CHANGELOG.md](CHANGELOG.md) for release history.\n\n## Installation\n\n### Quick install (recommended)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/sandst1/nav/main/install.sh | bash\n```\n\nOr with wget:\n\n```bash\nwget -qO- https://raw.githubusercontent.com/sandst1/nav/main/install.sh | bash\n```\n\nThis installs the latest binary to `~/.local/bin/nav`. To install to a different location:\n\n```bash\nNAV_INSTALL_DIR=/usr/local/bin bash -c \"$(curl -fsSL https://raw.githubusercontent.com/sandst1/nav/main/install.sh)\"\n```\n\n### Manual download\n\nDownload the latest binary for your platform from [GitHub Releases](https://github.com/sandst1/nav/releases):\n\n- **macOS (Apple Silicon)**: `nav-darwin-arm64.tar.gz`\n- **macOS (Intel)**: `nav-darwin-x64.tar.gz`\n- **Linux (x64)**: `nav-linux-x64.tar.gz`\n- **Linux (ARM64)**: `nav-linux-arm64.tar.gz`\n- **Windows (x64)**: `nav-windows-x64.zip`\n\nExtract and move to a directory in your PATH:\n\n```bash\n# macOS/Linux example\ntar -xzf nav-darwin-arm64.tar.gz\nmv nav-darwin-arm64 /usr/local/bin/nav\nchmod +x /usr/local/bin/nav\n```\n\n## Development Setup\n\nRequires [Bun](https://bun.sh) runtime (1.0+).\n\n```bash\n# Install Bun first (if needed)\ncurl -fsSL https://bun.sh/install | bash\n```\n\n\n```bash\n# Install dependencies\nbun install\n\n# Run directly\nbun run src/index.ts\n\n# Or link globally so `nav` is available everywhere\nbun link\n```\n\n## Configuration\n\nThe recommended way to configure nav is with a **config file**. Create one per-project or as a user-level default:\n\n```bash\nnav config-init   # creates .nav/nav.config.json in the current directory\n```\n\nOr create the file manually at `~/.config/nav/nav.config.json` for a global default.\n\nPriority order: **CLI flags \u003e environment variables \u003e project config \u003e user config \u003e defaults**.\n\nOptional **`editMode`** in the config file: default **`hashline`** (LINE:HASH line prefixes and anchor-based `edit` tool). Set **`\"editMode\": \"searchReplace\"`** for plain file contents from `read`/`skim`/`filegrep` and `edit` with `old_string` / `new_string` / optional `replace_all`. See [website/guide/configuration.md](website/guide/configuration.md) for the full key list.\n\n### Provider configs\n\nPick your provider and save as `.nav/nav.config.json` or `~/.config/nav/nav.config.json`. Each example is a complete, ready-to-use config file.\n\n**OpenAI:**\n\n```json\n{\n  \"provider\": \"openai\",\n  \"model\": \"gpt-4.1\",\n  \"apiKey\": \"sk-...\",\n  \"contextWindow\": 1047576,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**Anthropic:**\n\n```json\n{\n  \"provider\": \"anthropic\",\n  \"model\": \"claude-sonnet-4-20250514\",\n  \"apiKey\": \"sk-ant-...\",\n  \"contextWindow\": 200000,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**Google Gemini:**\n\n```json\n{\n  \"provider\": \"google\",\n  \"model\": \"gemini-2.5-flash\",\n  \"apiKey\": \"...\",\n  \"contextWindow\": 1048576,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**Azure OpenAI** (set `model` to your deployment name):\n\n```json\n{\n  \"provider\": \"azure\",\n  \"model\": \"my-gpt4o-deployment\",\n  \"baseUrl\": \"https://my-resource.openai.azure.com/openai/v1\",\n  \"apiKey\": \"...\",\n  \"contextWindow\": 128000,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**Ollama** (no API key needed, context window queried automatically):\n\n```json\n{\n  \"provider\": \"ollama\",\n  \"model\": \"llama3\",\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**LM Studio** (set `contextWindow` manually):\n\n```json\n{\n  \"provider\": \"openai\",\n  \"model\": \"local-model\",\n  \"baseUrl\": \"http://localhost:1234/v1\",\n  \"contextWindow\": 32768,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n**OpenRouter:**\n\n```json\n{\n  \"provider\": \"openai\",\n  \"model\": \"google/gemini-2.5-flash\",\n  \"baseUrl\": \"https://openrouter.ai/api/v1\",\n  \"apiKey\": \"or-...\",\n  \"contextWindow\": 1048576,\n  \"handoverThreshold\": 0.8,\n  \"verbose\": false,\n  \"sandbox\": false\n}\n```\n\n### All config keys\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `provider` | `openai` | `openai`, `anthropic`, `google`, `ollama`, or `azure` |\n| `model` | `gpt-4.1` | Model name |\n| `apiKey` | — | API key for the provider |\n| `baseUrl` | — | API base URL (for Azure, Ollama remote, LM Studio, OpenRouter) |\n| `verbose` | `false` | Show diffs, token counts, timing |\n| `sandbox` | `false` | Enable macOS Seatbelt sandboxing |\n| `contextWindow` | auto-detected | Context window size in tokens |\n| `handoverThreshold` | `0.8` | Auto-handover at this fraction of context (0–1) |\n| `theme` | `nordic` | Color theme (`nordic` or `classic`) |\n| `hooks` | — | Optional lifecycle hooks (`stop`, `taskDone`, `planDone`) — see [Hooks](https://sandst1.github.io/nav/guide/hooks.html) |\n| `hookTimeoutMs` | `600000` | Max wall time per shell hook step (default 10 minutes). Override with `NAV_HOOK_TIMEOUT_MS` |\n| `taskImplementationMaxAttempts` | `3` | Max full work+verify cycles per task in `/tasks run` / `/plans run`; loop stops if still failing. `NAV_TASK_IMPLEMENTATION_MAX_ATTEMPTS` |\n\n### Hooks\n\nRun shell commands (and optional custom slash commands) at fixed points: after each agent turn (`stop`), before a task is marked done (`taskDone`), and when every task in a plan is done (`planDone`). `taskDone` and `planDone` support `maxAttempts`: on failure the hook output is sent back to the model in the **same** conversation so it can fix issues before retrying.\n\nSee the full reference: [Hooks guide](https://sandst1.github.io/nav/guide/hooks.html).\n\n### CLI flags and environment variables\n\nFor one-off overrides, CLI flags and environment variables take precedence over config files.\n\n| Env var | CLI flag | Description |\n|---------|----------|-------------|\n| `NAV_MODEL` | `-m, --model` | Model name |\n| `NAV_PROVIDER` | `-p, --provider` | Provider |\n| `NAV_BASE_URL` | `-b, --base-url` | API base URL |\n| `NAV_SANDBOX` | `-s, --sandbox` | Enable sandbox (macOS only) |\n| `NAV_UI_HOST` | `--ui-host` | Host for `ui-server` mode |\n| `NAV_UI_PORT` | `--ui-port` | Port for `ui-server` mode |\n| `NAV_CONTEXT_WINDOW` | — | Context window size in tokens |\n| `NAV_HANDOVER_THRESHOLD` | — | Auto-handover threshold (0–1) |\n| `NAV_THEME` | — | Color theme |\n| `NAV_HOOK_TIMEOUT_MS` | — | Shell hook step timeout in milliseconds |\n| `NAV_TASK_IMPLEMENTATION_MAX_ATTEMPTS` | — | Max work+verify cycles per task in task/plan runs (default: 3) |\n| — | `-v, --verbose` | Show diffs, tokens, timing |\n\n## Usage\n\n```bash\n# Interactive mode\nnav\n\n# One-shot mode\nnav \"fix the type error in src/app.ts\"\n\n# With a specific model\nnav -m claude-sonnet-4-20250514 \"add error handling to the API routes\"\n\n# Google Gemini\nnav -m gemini-2.5-flash \"refactor the auth module\"\n\n# Verbose mode (shows full diffs, token counts, timing)\nnav -v \"refactor the auth module\"\n\n# Start websocket/http backend for UI clients\nnav ui-server --ui-port 7777\n\n# Reference files with @ — their contents are included in the prompt\nnav \"explain @src/auth.ts and refactor the error handling\"\n```\n\n## UI Server Mode\n\n`nav ui-server` exposes an optional local API transport while keeping terminal mode unchanged as the default.\n\n- HTTP health endpoint: `/health`\n- WebSocket endpoint: `/ws`\n- Protocol docs: [`docs/ui-server-protocol.md`](docs/ui-server-protocol.md)\n\nThis mode is designed for external UIs that want to stream assistant/tool events while still using nav's existing core behavior.\n\n## Commands\n\nType these in interactive mode:\n\n- `/clear` — clear conversation history\n- `/model [name]` — show or switch the current model\n- `/handover [prompt]` — summarize progress and continue in a fresh context\n- `/init` — generate an `AGENTS.md` for the current project\n- `/plan` — enter plan mode: discuss an idea, then save a named plan\n- `/plans` — list all plans with task status summary\n- `/plans split \u003cid\u003e` — generate implementation + test tasks from a plan\n- `/plans microsplit \u003cid\u003e` — generate micro-tasks optimized for small LLMs\n- `/plans run \u003cid\u003e` — work through all tasks belonging to a plan\n- `/tasks` — list planned and in-progress tasks\n- `/tasks add \u003cdescription\u003e` — add a new task (agent drafts name/description for confirmation)\n- `/tasks run [id]` — work on a specific task, or pick the next planned one automatically\n- `/tasks rm \u003cid\u003e` — remove a task\n- `/skills` — list available skills\n- `/create-skill` — create a new skill interactively\n- `/help` — list available commands\n\nTyping `/` shows all available commands. As you continue typing, the list filters in real-time. Press **Tab** to autocomplete when there's a single match.\n\n### Custom commands\n\nYou can create custom slash commands by adding markdown files:\n\n| Location | Scope |\n|----------|-------|\n| `.nav/commands/*.md` | Project-level (takes precedence) |\n| `~/.config/nav/commands/*.md` | User-level |\n\nThe filename (minus `.md`) becomes the command name. The markdown content is sent to the agent as a prompt. For example, `.nav/commands/review.md`:\n\n```markdown\nReview the code I've changed. Focus on correctness, edge cases, and readability.\nCheck for common bugs and suggest improvements.\n```\n\nThen use it with `/review`. You can pass arguments too — use `{input}` as a placeholder:\n\n```markdown\nReview the following file for issues: {input}\n```\n\n```\n\u003e /review src/auth.ts\n```\n\nCustom commands appear in `/help` and in the autocomplete suggestions.\n\n### Skills\n\nSkills are reusable agent capabilities defined in `SKILL.md` files. They provide specialized knowledge or workflows that nav can use automatically based on the skill's description.\n\n| Location | Scope |\n|----------|-------|\n| `.nav/skills/\u003cskill-name\u003e/SKILL.md` | Project-level (takes precedence) |\n| `.claude/skills/\u003cskill-name\u003e/SKILL.md` | Project-level (Claude compatibility) |\n| `~/.config/nav/skills/\u003cskill-name\u003e/SKILL.md` | User-level |\n\nEach skill lives in its own directory and has a `SKILL.md` file with YAML frontmatter:\n\n```markdown\n---\nname: docx-creator\ndescription: \"Use this skill when the user wants to create Word documents (.docx files)\"\n---\n\n# Word Document Creator\n\n## Overview\n\nThis skill creates .docx files using...\n\n## Instructions\n\n1. Install the required package...\n2. Use the following template...\n```\n\nThe `description` field tells nav when to use the skill. Write it as a trigger condition, not just what the skill does.\n\n**Commands:**\n- `/skills` — list all available skills\n- `/create-skill` — interactively create a new skill\n\nSkills are automatically detected and injected into the system prompt. When nav sees a task matching a skill's description, it uses that skill's instructions.\n\n### Plans \u0026 Tasks\n\nnav has a two-level planning system: **plans** capture the high-level design, **tasks** are the concrete units of work.\n\n#### Plans\n\nPlans are stored in `.nav/plans.json`. Start a plan with `/plan`:\n\n```\n\u003e /plan add dark mode to the settings screen\n```\n\nnav enters plan mode — it discusses the idea with you, asking one clarifying question at a time. When the plan is ready, it produces a summary and asks you to confirm:\n\n```\n[y]es to save plan, type feedback to refine, [a]bandon\n\u003e y\nPlan #1 saved: Dark mode settings\n  Use /plans split 1 to generate implementation tasks.\n```\n\nOnce saved, split it into tasks:\n\n```\n\u003e /plans split 1\n```\n\nThe agent reads the plan, explores the codebase, then creates ordered implementation tasks **and** test-writing tasks. Tasks are saved with IDs like `1-1`, `1-2`, etc. (the prefix is the plan ID).\n\nTo work through all tasks in a plan:\n\n```\n\u003e /plans run 1\nWorking plan #1: Dark mode settings\nWorking on task #1-1: Add theme state to settings store\n...\n```\n\nList all plans with a status summary:\n\n```\n\u003e /plans\nPlans:\n  #1  Dark mode settings  [0/5 done, 5 planned]\n```\n\n#### Standalone tasks\n\nTasks without a plan use IDs like `0-1`, `0-2`, etc.\n\n```\n\u003e /tasks add implement rate limiting for the API\n```\n\nThe agent drafts a name and description, shows a preview, and asks for confirmation. Reply `y` to save, `n` (optionally with more instructions) to revise, or `a` to abandon.\n\n```\n\u003e /tasks\nTasks:\n  #0-1   [planned  ]  Rate limiting\n               Add token-bucket rate limiting to the API middleware\n\n\u003e /tasks run 0-1\nWorking on task #0-1: Rate limiting\n...\nTask #0-1 marked as done.\n\n\u003e /tasks run       # picks the next planned task automatically (all tasks)\n```\n\nTasks cycle through three statuses: `planned` → `in_progress` → `done`. When working plan-linked tasks, the plan's description and approach are included in the agent's context alongside the status of all sibling tasks.\n\n### Handover\n\nFor long tasks, `/handover` lets you reset context without losing track of progress. The model summarizes what it's done, the conversation is cleared, and a fresh context starts with the summary, a current file tree, and any instructions you provide:\n\n```\n\u003e /handover now write tests for the auth module\n```\n\nThis is useful when context is getting long and you want to refocus the model on the next phase of work.\n\n### Auto-handover\n\nnav can automatically trigger a handover when the conversation approaches the model's context window limit. This prevents context overflow errors and keeps the model working effectively.\n\nContext window sizes are auto-detected for most providers. For LM Studio or custom endpoints, set `contextWindow` in your config file. You can also adjust the handover threshold:\n\n```json\n{\n  \"contextWindow\": 32768,\n  \"handoverThreshold\": 0.9\n}\n```\n\nWhen the threshold is reached mid-task, the agent completes its current step, generates a summary, and continues in a fresh context. If it's reached after the model finishes responding, the auto-handover triggers on the next user message. In verbose mode (`-v`), each response shows context utilization: `tokens: 45.2k in / 1.2k out (3.1s) (35% of 128k ctx)`.\n\n## Keyboard Shortcuts\n\n- **ESC** — stop the current agent execution and return to prompt\n- **Ctrl-D** — exit nav\n- Type while the agent is working to queue a follow-up message\n\n## Sandboxing\n\n\u003e **By default, nav runs without any sandbox.** Shell commands the agent executes have full access to your system — it can read, write, and delete files anywhere your user account can. This is the fastest way to work, but it means a confused or misbehaving model can cause real damage.\n\nEnable sandboxing to restrict what the agent can do — either via CLI flag or config file:\n\n```bash\nnav -s \"task\"\n```\n\n```json\n{ \"sandbox\": true }\n```\n\nThe sandbox uses **macOS Seatbelt** (`sandbox-exec`) and is **macOS only** for now. On other platforms, `-s` will exit with an error.\n\nWhen enabled, all processes spawned by nav (including shell commands) inherit these restrictions:\n\n- **File writes** are limited to the current project directory, temp, and cache directories. Writes anywhere else are denied by the kernel.\n- **File reads** are unrestricted — the agent can still read your whole filesystem.\n- **Network** is unrestricted — needed for LLM API calls.\n\nThe Seatbelt profile lives in `sandbox/nav-permissive.sb` and can be customized.\n\n## How it works\n\nnav has 7 tools:\n\n- **read** — reads files with hashline-prefixed output: `LINE:HASH|content`\n- **edit** — edits files by referencing `LINE:HASH` anchors from read output\n- **write** — creates new files\n- **skim** — read a specific line range with hashline output (no shell needed)\n- **filegrep** — search within a file with context lines and hashline output\n- **shell** — runs shell commands\n- **shell_status** — check on background processes\n\nThe hashline format (inspired by [can.ac/the-harness-problem](https://blog.can.ac/2026/02/12/the-harness-problem/)) gives each line a short content hash. When the model edits, it references lines by `LINE:HASH` instead of reproducing old content. If the file changed since the last read, hashes won't match and the edit is rejected with corrected hashes shown — so the model can retry without re-reading.\n\n## AGENTS.md\n\nIf an `AGENTS.md` file exists in the working directory, its content is automatically included in the system prompt. This is the standard way to give nav project-specific instructions.\n\n## Logs\n\nSession logs are written to `.nav/logs/` as JSONL files. Each line captures a message, tool call, or result with timestamps — useful for debugging and replay.\n\n## Development\n\n```bash\n# Type check\nbunx tsc --noEmit\n\n# Run with watch mode\nbun run --watch src/index.ts\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandst1%2Fnav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandst1%2Fnav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandst1%2Fnav/lists"}