Web Console

abstractcore serve ships a browser console at http://127.0.0.1:8000/console. Use it to see what this machine can run, browse and download models, delete weights you no longer need, and install local inference engines such as Ollama, without writing a command. Every action the console takes shows the equivalent abstractcore CLI command, so you can repeat it in a terminal or a script.

Table of Contents

Open the console Tabs Authentication Themes Responsive layout Embedding the Models and Engines screens Terminal console Related

The console is a view over the HTTP API described in Server. It adds no logic of its own: presence, fit verdicts, download progress and install plans all come from the server. The same Models and Engines screens are embedded in the AbstractGateway console, so both entry points look and behave the same.

Open the console

pip install abstractcore
abstractcore serve
# then open the printed link: http://127.0.0.1:8000/console#claim=...

The link signs the browser tab in once (it is valid for 10 minutes and one use). Lost it, or opening the console in another browser? abstractcore serve --claim-url --port 8000 prints a fresh one. The server landing page (/) links to the console as well.

Tabs

Tab What you see What you can do CLI equivalent
Overview This machine: OS, architecture, accelerator, RAM or unified memory, the usable model-memory ceiling and its source, free memory now, free disk for each model cache, Python version. An engines summary and server health (version, whether a bearer token is required). Jump to Models or Engines. abstractcore host profile --json, abstractcore engines status --probe
Models The model catalog, one row per downloadable artifact (provider, artifact id, quantization, download size, weights status, fit badge), the models already installed with their sizes, and any running jobs with progress bars. Search, filter, Download, Delete, Cancel a job. abstractcore models search <q> --engine <id> --fits, abstractcore models download, abstractcore models delete, abstractcore models list
Engines Each engine (Ollama, LM Studio, MLX, llama.cpp, vLLM, Hugging Face): supported on this host, installed and version, running and reachable, base URL, model count. Install (with confirmation), Open download page, Refresh (live probe). abstractcore engines status --probe, abstractcore engines install <id>, abstractcore engines open <id>
Email Your email address, the mailbox (connected address, sign-in method, last check), the recipient rules and the send limits with their usage. Save the email address; connect a mailbox (tabs IMAP / Google / Microsoft; IMAP shows the address, password and server fields, pre-filled from the address), Test, Disconnect (inline confirmation); the mailbox's Active switch and the Agent email tools switch; recipient rules, send limits and folder under Recipients and limits (applied at once). See Email. abstractcore email status, abstractcore email connect ... --password-stdin, abstractcore email policy set, abstractcore email limits set, abstractcore email folder, abstractcore email agent-tools on\|off
Providers Read-only list of providers (GET /providers) and the configured capability defaults (GET /v1/config/capability-defaults). Nothing to edit here. abstractcore config providers --probe, abstractcore config defaults

API keys and default models are configured on the host with abstractcore --config; the console does not store or edit keys. See Centralized Config.

Models tab

  • Search box: queries the catalog by name (/ focuses it).
  • Engine and Modality filters: narrow to one provider or to text, vision, audio or embedding models.
  • Fits this machine (on by default): hides artifacts whose fit verdict is too large. The count line tells you how many were hidden.
  • Installed only: shows only artifacts whose weights are already on disk.
  • Search Hugging Face: adds live Hub search results to the curated catalog (slower).

Weights status uses the same four labels everywhere in AbstractFramework:

Label Meaning
installed The weights are on this host.
not downloaded The weights can be downloaded; they are not on disk.
unknown The provider's tool could not be consulted (for example, the engine is not running).
remote Nothing to download: the model runs on a remote API.

Fit badges: fits, tight, too large, partial offload, needs GPU limit, unknown. Hover a badge to see the evidence: memory needed versus the usable ceiling, free memory now, whether the download fits on disk, the maximum context, the confidence of the estimate and any notes. needs GPU limit (Apple silicon) means the model fits once macOS lets the GPU use more memory; the notes carry the exact sudo sysctl iogpu.wired_limit_mb=<MB> command (see Local models).

Download starts immediately (one click). Delete asks for confirmation, shows the files' location and size, and warns when the model is loaded or when the files are shared with another provider (for example MLX and Hugging Face share the Hugging Face cache). In those cases you must tick Force to proceed. Both dialogs offer Preview (dry run), which asks the server for the exact command without running it.

Engines tab

Install opens a confirmation dialog that shows:

  • the exact command as a fixed argument list (for example brew install ollama); the server never runs a shell string built from user input;
  • the host it runs on: the machine running the server, which may not be the computer in front of you;
  • the install method and what it changes, plus host notes (Homebrew needs no sudo, a vendor script may ask for sudo, which a background job cannot answer, winget may raise a UAC prompt on the host's desktop, pip installs into the server's Python environment).

Engines that are installed by hand, such as the LM Studio desktop app, offer Open download page instead. The server may refuse an install (for example when another install is running, or when engine installs are disabled for a remote server); the console shows the server's reason.

Jobs

Downloads, deletes and engine installs run as server-side jobs. The console polls each job every 1.5 seconds and shows its status (queued, running, completed, failed, cancelled), progress, bytes, the last log lines, the command it runs and its CLI equivalent. Active job ids are remembered for the browser tab, so a page reload re-attaches to them. Jobs live in the server process: after a server restart the console reports that the job is no longer known and re-checks what is on disk.

Keyboard

Key Where Action
/ Models Focus the search box
f Models Toggle Fits this machine
r any tab Refresh
w Models, focused row Download
d Models, focused row Delete (confirm)
i Engines, focused row Install (confirm)
o Engines, focused row Open download page
c focused row with a running job Cancel the job
Esc dialog Close

Click a row or move to it with Tab to focus it. These are the same verbs as the terminal consoles.

Authentication

The console page and its fragments are static code and never require a token. The data behind them does. There are two ways in:

  • The one-time link printed by abstractcore serve on your own machine (/console#claim=<code>). The console trades the code for the server's token through POST /acore/session/claim, then removes it from the address bar. This works only from the machine running the server; see First run.
  • Pasting the token. When the first API call answers 401, the console asks for the token (abstractcore serve --print-token prints it, or it is the value of ABSTRACTCORE_AUTH_TOKEN).

Either way the token is kept in the browser tab's sessionStorage only (cleared when the tab closes) and sent as Authorization: Bearer <token>. Use Forget token in the top bar to clear it.

A server bound to a non-loopback address with no token configured and ABSTRACTCORE_SERVER_ALLOW_UNAUTHENTICATED unset answers 503 server_auth_not_configured; the console shows that message. See Server for the auth settings.

Themes

The console uses the AbstractFramework UI kit themes. By default it follows your system's light or dark preference; the top bar has a theme picker (every kit theme) and a light/dark toggle. The choice is stored in localStorage.

About (the i button at the end of the top bar) opens the compact About card every AbstractFramework app shows: AbstractCore and its version, the AbstractFramework and AbstractGateway versions installed on this host (or "not installed on this host"), one row of links (Website, Source, Docs, Issues, Feedback, Contact) and the copyright and licence line. It lists no packages. Escape, the Close button or a click outside closes it.

Responsive layout

The console works in any browser window and on phones and tablets. The tab strip scrolls sideways when the tabs do not fit, and long configuration paths wrap inside their pane. On phones, tables scroll sideways inside their frame, and long artifact ids stay on one line with an ellipsis (hover or long-press shows the full id). Below 768 px wide, or in phone landscape, dialogs open as bottom sheets. On touch screens, buttons, tabs and selects are at least 44 px tall, form fields use 16 px text (iOS does not zoom into a focused field), and table text is 14 px. The page respects the notch and home-indicator areas of phones.

On phones (below 768 px) the content uses the full width: cards become flat sections with a hairline divider, forms stack in one column, and the page is the only scroll area. The list panels (Catalog, Installed, Providers, Capability defaults) fold from their heading; they start open and the browser remembers what you folded. Forms are at most 720 px wide, with labels above the fields and short fields (port and security, per hour and per day) side by side from 768 px. Every on/off setting is a switch labelled by its feature, applied at once.

The layout reads the UI kit's responsive tokens (--tap-min, --vh-full, --safe-*, --gutter) and its switch, form, card and tabs rules (KIT_SWITCH_CSS, KIT_FORM_CSS), which abstractcore.console.theme_sync copies verbatim from the kit together with the themes.

Embedding the Models and Engines screens

Hosts such as AbstractGateway embed the Models and Engines screens in their own console. Two ways to obtain them:

  • In Python: abstractcore.console.web.fragment(kind) with kind "models" or "engines" returns {"html": str, "js": str, "css": str}.
  • Over HTTP: GET /console/fragment/{kind} returns the same object plus "kind".

render_console_html(api_base="/acore", title="AbstractCore Console") returns the standalone page served at /console.

Place css in a <style> element, html where the tab body goes, and js in a <script> element (the script is idempotent; both kinds return the same js and css, so include each once). The script defines one global, window.AbstractCoreConsole; then mount each screen:

AbstractCoreConsole.mount("models", document.getElementById("tab-catalog"), {
  apiBase: "/api/gateway",                 // default "/acore"
  request: (method, path, body) =>          // default: fetch + optional bearer token
    api(path, { method, body: body == null ? undefined : JSON.stringify(body) }),
  isAdmin: () => Boolean(currentUser.admin),  // boolean or function; default true
  onJob: (job, kind) => {},                 // called on every job update
  hostName: "gateway-host",                 // shown in install/delete dialogs; default location.hostname
  cliPrefix: "abstractgateway",             // CLI shown for composed commands; default "abstractcore"
});
  • request(method, path, body) receives the full path (apiBase + route) and a JSON-serializable body or undefined; it must resolve to the parsed JSON and reject with an Error carrying status on HTTP errors. The host keeps full control of auth, CSRF headers and timeouts.
  • The screens call these routes under apiBase: GET /host/profile, GET /engines?probe=1, GET /models/catalog?q=&engine=&fits=1&hub=1, GET /models/installed, POST /models/download, POST /models/delete, POST /engines/{id}/install, GET /jobs/{id}, POST /jobs/{id}/cancel. Verbs answer a host_job_v1 job (a {"job": ...} envelope is also accepted).
  • When isAdmin is false, Download, Delete and Install are disabled.
  • mount() returns {kind, refresh(), unmount()}; AbstractCoreConsole.unmount(rootEl) does the same. Mounting injects the tab body itself when the host did not place html.
  • Styles are scoped under .acc-root and read the UI kit's CSS variables (--bg-secondary, --text-primary, --accent, --info, --success, --warning, --error, ...), so the screens follow the host's active theme.

Terminal console

The same Models and Engines screens exist in the terminal: abstractcore-console (a Rust terminal app, cargo install abstractcore-console) shows them as screen 9 "Models" and screen 0 "Engines", with the same labels and keys (w download, d delete, i install, o open download page, / filter, f fits only, c cancel). It drives the abstractcore CLI on this machine, so it needs no server. On a machine without a display (an SSH session, or Linux without DISPLAY/WAYLAND_DISPLAY) o prints the link instead of launching a browser. See Terminal console.