{"slug": "show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal", "title": "Show HN: Namo_complete: a non-obtrusive AI autocomplete for the bash terminal", "summary": "Namo Robotics released Namo_complete, a Linux-only AI autocomplete tool for the Bash terminal that suggests commands via dim hints and a 'did you mean' feature, using Anthropic's Claude Haiku 4-5 model by default. The tool, written in the Sun programming language, requires an ANTHROPIC_API_KEY and can be installed via a curl script, with options to customize model, history, and output settings.", "body_md": "### A non-obstrusive AI autocomplete for your Bash terminal, written in [Sun](https://namo-robotics.github.io/sun/)\n\n(**Linux-only** until Sun can target MacOS)\n\nType as usual. A moment after you pause, a dim hint appears on the row below\nyour line with the command you are most likely looking for. Press **Alt-O** to accept the hint, which puts it in your line where\nyou can edit it before pressing Enter. If you mistype a command, the *command not found* line comes with a **did you mean** hint.\nPress **Alt-G** to enter **ask>** mode where you can describe the command that you want in plain english.\n\n| Key | Action |\n|---|---|\nAlt-O |\nAccept the hint |\nAlt-A |\nList the other candidates, pick one by number |\nAlt-G |\nDescribe what you want in plain English, pick from described options |\n\n```\ncurl -fsSL https://raw.githubusercontent.com/namo-robotics/namo_complete/main/install.sh | bash\n```\n\nThen open a new terminall. You will also need to set the `ANTHROPIC_API_KEY`\n\nenv var.\n\n```\nexport ANTHROPIC_API_KEY=sk-ant-...\n```\n\nThe install script downloads a release artifact and\nunpacks two files to `~/.local/bin/namo_complete`\n\nand `~/.local/share/namo_complete.bash`\n\n. It then adds a line to your `~/.bashrc`\n\nso new shells source the `namo_complete.bash`\n\nscript.\n\nOptions:\n\n| Option | Env var | Effect |\n|---|---|---|\n`--version vX.Y.Z` |\n`NAMO_VERSION` |\nInstall a particular release; `dev` takes the latest build of `main` . Default: latest stable, or `dev` if there is none |\n`--prefix DIR` |\n`NAMO_PREFIX` |\nInstall root. Default `~/.local` |\n`--no-bashrc` |\n— | Skip the `~/.bashrc` edit; add the source line yourself |\n\n```\nrm -f  ~/.local/bin/namo_complete\nrm -rf ~/.local/share/namo_complete ~/.cache/namo_complete\nsed -i '/# namo_complete/,+1d' ~/.bashrc     # drops the marker and the source line\n```\n\n| Sent | Default | Disable |\n|---|---|---|\n| The partial command line | always | — |\n| A command bash could not find | always | `NAMO_DYM=0` |\n| What the last command printed | last 10 lines | `NAMO_OUTPUT=0` |\n| Current directory path | always | — |\n| Filenames in that directory | 40 | `NAMO_NO_LS=1` |\n| Recent shell history | 50 commands | `NAMO_HISTORY_LINES=0` |\n| Everything | `NAMO_DISABLE=1` |\n\nAny history line or captured output line that contains something shaped like an\nAPI key (`sk-`\n\n, `ghp_`\n\n, `github_pat_`\n\n, `AKIA`\n\n, `xoxb-`\n\n, `xoxp-`\n\n) is thrown away\nbefore the request is built. That is the whole check: it catches a key you\npasted at a prompt, not a secret that looks like anything else. If you handle\nsensitive material in this shell, set `NAMO_HISTORY_LINES=0`\n\nand it sends no\nhistory at all.\n\n| Variable | Default | Meaning |\n|---|---|---|\n`ANTHROPIC_API_KEY` |\n— | Required |\n`NAMO_MODEL` |\n`claude-haiku-4-5` |\nAny Claude model |\n`NAMO_BIN` |\n`namo_complete` |\nBinary path, if not on `PATH` |\n`NAMO_KEY` / `NAMO_ALT_KEY` / `NAMO_ASK_KEY` |\n`\\eo` / `\\ea` / `\\eg` |\nThe three keys, written the way bash's `bind` writes them |\n`NAMO_DEBOUNCE` / `NAMO_QUIET` |\n`0.2` / `0.05` |\nSeconds of not typing before a request; how long a burst of typing is left to settle |\n`NAMO_HINT_MIN` |\n`3` |\nMinimum characters before hinting |\n`NAMO_HINT_PREFIX` |\n`hint: ` |\nText in front of the hint row |\n`NAMO_TIMEOUT` |\n`10` |\nSeconds before giving up |\n`NAMO_DYM` / `NAMO_DYM_PREFIX` |\n`1` / `did you mean: ` |\n\"did you mean\" after command not found, and the text in front of it |\n`NAMO_OUTPUT` |\n`10` |\nLines of the last command's output to send; `0` keeps none (hints still work) |\n`NAMO_HISTORY_LINES` |\n`50` |\nHistory commands sent; `0` disables |\n`NAMO_LS_LIMIT` / `NAMO_NO_LS` |\n`40` / `0` |\nDirectory listing |\n`NAMO_MAX_SUGGESTIONS` |\n`3` |\nCandidates requested |\n`NAMO_CACHE` / `NAMO_CACHE_TTL` |\n`1` / `900` |\nLocal cache |\n`NAMO_DISABLE` |\n`0` |\n`1` turns everything off |\n`NAMO_ENDPOINT` |\nMessages API | Override, for testing |\n\nAnswers are cached in `~/.cache/namo_complete`\n\n, looked up by what you had typed,\nwhich directory you were in, and which model answered. Deleting that directory\nis safe at any time.\n\nThree processes and one program file. Bash owns the line you are typing, because its own line editor is the only thing that can; the rest belongs to two background helpers, both of them the same binary started in a different mode:\n\n**the daemon**— lives as long as your shell, and does all the thinking: waiting for you to pause, looking in the cache, calling the API, drawing the hint row.**the output relay**— holds a*stand-in terminal*(a pseudo-terminal, or pty: a pair of endpoints that looks exactly like a real terminal to anything writing into it). The shell's output goes there instead of straight to your screen, and the relay passes every byte through to the real terminal. On the way past it keeps the last few lines your commands printed — that is what it is named for — and reads the line you are typing.\n\nThe two helpers and the shell talk over *named pipes* — files you write bytes\ninto at one end and read at the other.\n\n```\nflowchart LR\n    BASH[\"bash<br>your prompt, your keys\"]\n    REL[\"the output relay\"]\n    DAE[\"the daemon\"]\n    TTY[\"your terminal\"]\n    CACHE[(\"answers already given\")]\n    API([\"Claude\"])\n\n    BASH -->|\"everything it prints,<br>including your line as you type it\"| REL\n    REL -->|\"all of it, unchanged\"| TTY\n    REL -->|\"your line, and what the last command printed\"| DAE\n    BASH -->|\"Alt-O, Alt-A, Alt-G\"| DAE\n    DAE -->|\"the commands it suggests\"| BASH\n    DAE -->|\"the hint row\"| TTY\n    DAE <-->|\"looked in first, written back after\"| CACHE\n    DAE -->|\"only when the cache has no answer\"| API\n```\n\n**The shell half** is one file, [ shell/namo_complete.bash](/namo-robotics/namo_complete/blob/main/shell/namo_complete.bash),\nand deliberately thin: it does only the things that are impossible outside bash.\n\n- The line you are typing is readable and writable, as\n`READLINE_LINE`\n\n, only inside a key handler bash runs for you. Assigning to it is the one way to put a command into someone's prompt without running it, and that is what Alt-O does — those three keys are the only ones this binds. - Your shell's history can only be read by the shell itself, so it drops the daemon a copy at every prompt.\n- The prompt hooks bash offers (\n`PROMPT_COMMAND`\n\n,`PS0`\n\n,`PS1`\n\n) and its \"command not found\" hook belong to it as well.\n\n**The other half** is [ src/](/namo-robotics/namo_complete/blob/main/src): a single program that behaves differently\ndepending on how it is started — as the daemon, as the output relay, or as a\nplain one-shot run that reads its input, prints candidates and exits. That last\nshape is what\n\n`run.sh`\n\n, the test suite and any script use, and it is the only\none that existed first. Everything else in there is what the daemon calls out\nto: settings read from the environment, the prompt and the context that goes\nwith it, the redaction pass that drops lines looking like keys, the curl client,\nand the cache.Two deliberate properties:\n\n**No shell is ever involved.**`curl`\n\nis started directly, with its arguments passed one by one, so there is never a command string for a filename or a URL to be quoted into. Directories are listed by asking the operating system, not by running`ls`\n\n.**Your API key never shows up in the process list or on disk.** It is fed to`curl`\n\non its standard input; only the harmless parts — the URL, the fixed headers, the path of the request body — are passed as arguments.\n\nEverything the binary needs is inside the one file — it links nothing at run\ntime and depends on nothing but `curl`\n\n. One source file reaches outside Sun's\nstandard library: [ cmd_output_relay.sun](/namo-robotics/namo_complete/blob/main/src/cmd_output_relay.sun) calls a handful of C functions\ndirectly (\n\n`posix_openpt`\n\n, `grantpt`\n\n, `unlockpt`\n\n, `ptsname`\n\n, `ioctl`\n\n, `read`\n\n,\n`open`\n\n), because creating a stand-in terminal is the one thing the standard\nlibrary cannot yet do. No other file in [calls C or uses an](/namo-robotics/namo_complete/blob/main/src)\n\n`src/`\n\n`unsafe`\n\nblock.\n\n```\n./run.sh            # try it here, without installing anything\n./build.sh          # -> bin/namo_complete (needs the Sun compiler)\n./test.sh           # no API key needed: it answers itself with a local stub\n./test.sh --live    # adds one real call, and times it\n```\n\n`run.sh`\n\nand `test.sh`\n\nread `.env`\n\n, which is never committed:\n\n```\ncp .env.example .env && chmod 600 .env\n```\n\n[ .devcontainer/](/namo-robotics/namo_complete/blob/main/.devcontainer) has an Ubuntu 26.04 image with the compiler\nalready installed. Nothing ever fails loudly into your prompt: a missing key, a\ntimeout or a network error leaves your line exactly as it was and explains\nitself separately.\n\nSun is young, and the gaps this project ran into — in the compiler and in its\nstandard library — are written up in [SUN_FEEDBACK.md](/namo-robotics/namo_complete/blob/main/SUN_FEEDBACK.md) as\nready-to-file issues.\n\nSee [LICENSE](/namo-robotics/namo_complete/blob/main/LICENSE).", "url": "https://wpnews.pro/news/show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal", "canonical_source": "https://github.com/namo-robotics/namo_complete", "published_at": "2026-08-22 16:44:53+00:00", "updated_at": "2026-08-22 17:14:18.892531+00:00", "lang": "en", "topics": ["ai-tools", "artificial-intelligence", "developer-tools"], "entities": ["Namo Robotics", "Namo_complete", "Anthropic", "Claude Haiku 4-5", "Sun"], "alternates": {"html": "https://wpnews.pro/news/show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal", "markdown": "https://wpnews.pro/news/show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal.md", "text": "https://wpnews.pro/news/show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal.txt", "jsonld": "https://wpnews.pro/news/show-hn-namo-complete-a-non-obtrusive-ai-autocomplete-for-the-bash-terminal.jsonld"}}