Skip to content
AtomicBot-aiPublic

About

Atomic Chat terminal workspace with local chat, model setup and an API server console

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

eye-cli

Atomic Chat's terminal workspace: local conversations, model and engine installation, and an OpenAI-compatible server console. Keyboard shortcuts and mouse controls share the same interface, with an animated turquoise eye and layouts that adapt to the terminal window.

Choose Personal terminal for chat or Server console for API controls and credentials. First run installs an engine and model before opening the workspace. The executable is still named atc.

This repository continues the terminal work built on atomic-chat-cli. Build from source with Bun and Node 22:

git clone https://github.com/AtomicBot-ai/eye-cli.git
cd eye-cli
bun install --frozen-lockfile
npm run build:ui
npm run embed:ui
npm run build
node dist/bin.js

Use npm run build:bin to create a standalone executable for the current platform in dist/bin/. The terminal needs at least 54 columns and 24 rows. Ctrl+Q closes the interface; accepted downloads and the background server continue. Ctrl+K shows shortcuts.

Server foundation

Atomic Server keeps models on a machine — Linux, Windows or macOS, usually a headless server — and serves them over an OpenAI-compatible API on http://127.0.0.1:1337/v1. Its command is atc. It embeds atomic-chat-core as a library and ships as one binary per platform, with no engine inside: engines are installed on demand, and the core picks the build for the hardware. The same server has a web admin on 127.0.0.1:1338 and a terminal UI (bare atc) for people who would rather not type commands. Atomic Server and the Atomic Chat desktop app are separate products for different audiences: they share the core (and the core's per-user managed-runtime root) and nothing else. The words used everywhere — server, engine, engine build, model, run, unload — are defined in docs/concepts.md.

Status. The server, its lifecycle and supervision, the terminal UI (chat, server console, model and engine setup), the API with its keyring, the web admin's dashboard, installers, updates and the release pipeline work. Commands marked stub below parse their flags and print their help, but exit with code 3 (ATC_NOT_IMPLEMENTED) and name the iteration that brings them; the terminal UI already does what most of them will. docs/commands.md is generated from the command specs and is the authoritative list.

Quick start on a server

curl -fsSL https://github.com/AtomicBot-ai/eye-cli/releases/latest/download/install.sh | sh

On Windows, in PowerShell: irm https://github.com/AtomicBot-ai/eye-cli/releases/latest/download/install.ps1 | iex.

The installer downloads the release's SHA256SUMS, picks the binary for this machine — the CPU, musl on Alpine, a baseline build for x64 CPUs without AVX2, arm64 under Rosetta — verifies it (and refuses when it cannot), puts it in ~/.local/bin/atc (%LOCALAPPDATA%\atc\atc.exe on Windows) and adds that directory to PATH. ATC_INSTALL_DIR, ATC_VERSION (a tag, e.g. v0.1.0), ATC_NO_PATH=1 and ATC_REPO override the defaults. The macOS and Windows binaries are signed (Developer ID with notarisation, Authenticode), and every binary carries a build provenance attestation (gh attestation verify atc-… -R AtomicBot-ai/eye-cli).

Linux packages

On Debian, Ubuntu, Fedora, RHEL-compatible systems and Arch, atc also comes as a package, and the package manager then updates it with the rest of the system. A package carries the same binary as the release (on x86-64 the baseline build, so it runs on any x86-64 CPU) and the shell completions. The repository and the rpm packages are signed with the Atomic Chat packages key in packaging/atomic-chat.asc, fingerprint 1047 F119 58C6 442D D472 E497 E4C3 D361 FB7F F123.

Debian, Ubuntu (x86-64, arm64):

curl -fsSL https://atc-packages.fsn1.your-objectstorage.com/atomic-chat.gpg | sudo tee /usr/share/keyrings/atomic-chat.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/atomic-chat.gpg] https://atc-packages.fsn1.your-objectstorage.com/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/atomic-chat.list
sudo apt update && sudo apt install atc

Fedora, RHEL, Rocky, Alma (x86-64, aarch64):

sudo curl -fsSL -o /etc/yum.repos.d/atomic-chat.repo https://atc-packages.fsn1.your-objectstorage.com/rpm/atc.repo
sudo dnf install atc

Arch Linux: yay -S atc-bin, or any other AUR helper.

Updates come with sudo apt upgrade, sudo dnf upgrade or yay -Syu; atc update refuses on a packaged install and names the command to use. After an upgrade, atc restart (or atc service restart) moves a running server onto the new binary. sudo apt remove atc, sudo dnf remove atc or sudo pacman -R atc-bin removes it and leaves the data folder. The repository keeps the last ten releases; older ones are on the releases page as .deb and .rpm files.

atc                  # on a terminal: the terminal UI — choose a workspace, install an engine and a model
atc service install  # keep the server running: systemd, launchd or a scheduled task; back after a crash
atc status           # pid, versions, API endpoint, running models, admin URL   (--json for one document)
atc api start        # the OpenAI-compatible API; every client needs a key from atc/client-keys.json
atc admin            # prints http://127.0.0.1:1338/#token=… and opens a browser
atc update           # the next release, checked against SHA256SUMS and the signature (packages: apt/dnf/yay)
atc doctor           # versions, data folder, config, ports 1337/1338, PATH, GPU driver

atc start / atc stop run the server in the background without a service; atc start --foreground runs it in place (containers). atc logs [-f] shows the server's own log, rotated by size.

Commands

Group Command What it does Status
Server atc start / stop / restart The server: core, API and web admin in the background; start --foreground runs it in place works
Server atc status The server, the API endpoint, running models, the admin URL works (--watch is a stub)
Server atc logs Tail of the server log; -f follows it works
Models & engines atc run <model> / atc unload <model> Start a downloaded model on the active engine; stop it stub (iteration 2)
Models & engines atc models search|pull|list|rm|info The catalog and the model files stub (pull: iteration 2; the rest: 3)
Models & engines atc engines list|install|status|rm Engines (llama.cpp, MLX, TensorRT-LLM) and their builds; installing one prepares what it needs stub (install: iteration 2; the rest: 4)
Models & engines atc hardware show|refresh What the core sees of the GPU and CPU stub (iteration 4)
Access atc api start|stop|status The OpenAI-compatible API on the running server; clients need a key from the keyring works
Access atc chat Send a message to an OpenAI-compatible model works
Access atc api key show|set|rotate|clear The keyring from the command line (the terminal UI manages it today; --api-key adds one) stub (iteration 3)
Access atc admin [open|status|token] Sign-in link, where the admin listens, token rotation works
Access atc tui The terminal UI, explicitly (what bare atc opens on a terminal) works
System atc config get|set|unset|list|path atc settings works (engine.* keys are a stub)
System atc doctor Diagnostic table with hints works (GPU: NVIDIA only; Docker check skipped)
System atc service install|uninstall|status|start|stop|restart The server as an OS service (systemd, launchd, Task Scheduler) works
System atc update Self-update from GitHub Releases: checksum and signature checked, the server restarted onto it; a deb, rpm or AUR install is left to its package manager works
System atc version, atc completion <shell> Versions; bash/zsh/fish/powershell completion works

Hidden: atc daemon (the server process itself, which start spawns) and atc host-step exec <request.json> (the privileged helper for managed runtimes).

Bare atc opens the terminal UI only on an interactive terminal; in a pipe, a script, a service unit or with --json it prints this help and exits 2, as before. Leaving the UI (Ctrl+Q) never stops the server.

Global flags go anywhere on the line: --json, -v/--verbose, -q/--quiet, -y/--yes, --data-folder <path>, --no-color, -h/--help, --version. With --json a command prints exactly one JSON document on stdout; an error is {"error":{"code","message","details?","hint?"}} on stderr.

Exit codes: 0 success, 1 runtime error, 2 usage (also bare atc and bare groups such as atc models), 3 not implemented in this build, 130 interrupted.

Where data lives

<data> = <system data>/atomic-chat-cli/data      --data-folder or ATC_DATA_FOLDER override it
<data>/atomic-core/           the core: instance.lock, control-token (0600), settings.json, processes.json, logs/
<data>/llamacpp/models/       GGUF models, one folder with model.yml each (both llama.cpp providers)
<data>/<provider>/backends/   engine builds the core installs
<data>/atc/                   what only atc owns (owner-only ACL on Windows)
  config.json                 settings (0644, written atomically; unknown keys are kept)
  client-keys.json            0600: the API keyring, created when the server starts
  setup.json, chats/          0600: the terminal UI's setup and conversations
  run/daemon.json             pid, instance_id, state (starting|ready), atc/core versions, control_url, admin_url, started_at
  run/admin-token             0600: the admin login token
  run/host-steps/             0700: <step_id>.request.json (0600), <step_id>.result.json, journal.json
  logs/daemon.log             the server's own log, rotated by size (log.maxSizeMb, log.maxFiles)
  logs/daemon.out.log         the server process's output from its last start (crashes before the logger)
  cache/                      catalog and recommendation caches

<system data> is $XDG_DATA_HOME or ~/.local/share on Linux, ~/Library/Application Support on macOS and %APPDATA% on Windows — the core's own rule, so the core and atc always agree. The desktop app's data folder is refused: the two products never share models, settings or a lock.

Configuration

Precedence: command flags > ATC_<SECTION>_<KEY> environment variables > <data>/atc/config.json > defaults. atc config list shows every key with its value and where it came from.

atc config set api.port 1337              # written to config.json
ATC_API_HOST=0.0.0.0 atc status           # api.host from the environment for this run
atc config set models.autoLoad qwen3-8b,gemma-4b
atc config path

Keys are api.*, admin.*, engines.* (engines.default is the engine atc run falls back on), models.*, managed.*, proxy.*, update.*, telemetry.*, log.* (the table is src/config/schema.ts). Engine parameters (engine.<provider>.<key>) belong to the core's settings; forwarding them through atc config is a stub. A config file written by a newer atc is refused with a hint rather than half-read; an older one is migrated (version 2 dropped the serve.* keys along with the serve command; version 4 dropped api.requireKey, since every API client needs a key from the keyring).

Privacy

The server sends anonymous crash and error reports to Atomic Chat's error tracker: the error, the versions and the platform — never prompts, replies, file paths, keys or personal data (the core scrubs them before anything leaves). Reports are on by default, and the first atc start or terminal UI says so once. Turn them off with any of:

atc config set telemetry.enabled false     # applies to the running server at once
export DO_NOT_TRACK=1                      # or ATC_TELEMETRY_ENABLED=false, for services and containers

The web admin

atc admin                    # http://127.0.0.1:1338/#token=<admin token>, opened in a browser
atc admin status             # where it listens
atc admin token --rotate     # new token; old login links stop working

The admin listens on loopback only. The token in the URL fragment is exchanged once for an HttpOnly cookie, so it never reaches a query string or a log. The core's control token never leaves the server: the page talks to /api/* and the server proxies an allowlist of control routes. From another machine, forward the port instead of exposing it:

ssh -L 1338:127.0.0.1:1338 user@server

--host 0.0.0.0 is refused until the password login lands (iteration 5).

Development

Prerequisites: Bun 1.3.10 (the package manager — bun.lock is committed — and the compiler of the binary) and Node 22 (the development and test runtime; scripts run as npm run …, like in the core). The core is the npm package @atomic-chat/core, pinned to an exact version (docs/release.md, "The core pin").

bun install                  # the pinned core and the admin-ui workspace
npm test                     # unit + contract projects on Node
npm run build:bin            # embeds the admin SPA (or the placeholder) and compiles dist/bin/atc-<triple>
npm run verify               # lint, typecheck, format, tests, build, UI, binary, e2e, runtime-compat

To develop against a local core checkout, build it there (npm run build), run bun link in it and bun link @atomic-chat/core here; package.json and bun.lock stay untouched and bun install --force puts the pinned version back. node dist/bin.js … runs the CLI from source after npm run build; npm run dev in packages/admin-ui runs the SPA against a server started with atc admin --no-open.

Note: the core's own CLI defaults its public API to port 6767; atc uses 1337, like the desktop app.

Documentation

License

Apache-2.0 (LICENSE). The web admin includes files from Atomic Chat, also Apache-2.0; the attribution is in NOTICE. The binary bundles third-party packages, listed with their licenses in THIRD_PARTY_NOTICES.md (npm run notices regenerates it; CI checks it is current and that every license is on the policy in scripts/licenses.mjs).

About

Atomic Chat terminal workspace with local chat, model setup and an API server console

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages