Elyra
Elyra The coding agent eTerm The terminal that knows where each command ends Huskarl AI colleagues on your own Mac Starf An activity monitor for Apple silicon that never invents a number etrans An SSH and SFTP client for macOS Elyra VM Virtual machines for macOS, Linux and Windows on your Mac Litr A small, native web browser for macOS Notr A notebook for macOS e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Refr Local-first PDF workspace for macOS Elyra Workspace A desktop workspace for coding agents Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Release notes
Changelog
Elyra

Agents

A bot is run by an agent CLI: Elyra, Claude Code or Grok Build. You choose the agent in the bot's settings under Agent. New bots get Elyra.

The same holds for all three:

  • The gateway's tools are the only ones that work. The agent's own tools (shell, files, web search) are turned off.
  • The agent runs in Seatbelt behind the egress proxy. It can reach only its own model provider. See Security.
  • The environment is built from scratch. Only what Huskarl sets reaches the agent.
  • Huskarl stores no model keys. The login is the agent's own.
  • Questions and permission requests from the agent are refused. If the agent asks for permission to use a tool that is not the gateway's, it gets a no ("Huskarl allows only its own tools."). Questions to the user are answered with "cancelled", so the agent is not left waiting.
Elyra Claude Code Grok Build
Program elyra claude grok agent stdio
Protocol RPC stream-json ACP
Login your own, linked in its own for Huskarl, in ~/.huskarl/agents/claude its own for Huskarl, in ~/.huskarl/agents/grok
Own tools off --tools with an exact list --tools "", --strict-mcp-config, --setting-sources "" deny on bash, read, edit, grep, webfetch and websearch
The gateway's tools --tools mcp__huskarl__… --allowedTools mcp__huskarl__… allow on mcp
HOME ~/.huskarl/bots/<id>/home your own HOME ~/.huskarl/bots/<id>/home
Network the model's provider api.anthropic.com, console.anthropic.com, platform.claude.com api.x.ai, auth.x.ai

The status of each agent is shown next to its button in the settings: installed or not, and who is logged in.

Elyra

Elyra uses your own login. Log in with elyra and /login as usual. Huskarl makes a folder per bot, ~/.huskarl/bots/<id>/agent (as ELYRA_CODING_AGENT_DIR), and puts symbolic links to auth.json and models.json in your Elyra folder (~/.elyra/agent, or ELYRA_CODING_AGENT_DIR). The sandbox lets only those two files through. The rest of the Elyra folder is hidden.

Each bot gets its own settings.json. It inherits the default provider, model and thinking level from yours, and turns off what sends traffic elsewhere or lets the agent change itself: providerFailover, oracle, cacheWarming, smartRouting, codebaseMemory, decisionLog, routingLedger, install telemetry, autoSkills and autoExtensions.

Elyra is started with --no-extensions --no-context-files --no-skills --no-prompt-templates, Elyra's MCP extension (@elyracode/mcp, which must sit next to the Elyra CLI) loaded with -e, and ELYRA_OFFLINE=1. The instructions are written to ~/.huskarl/bots/<id>/instructions.md, and the sessions to ~/.huskarl/bots/<id>/agent/sessions.

The egress proxy lets through only the provider of the bot's model (or your default provider):

Provider Hosts
anthropic api.anthropic.com
openai api.openai.com
openai-codex chatgpt.com, auth.openai.com
google generativelanguage.googleapis.com
mistral api.mistral.ai
groq api.groq.com
deepseek api.deepseek.com
xai api.x.ai
openrouter openrouter.ai
cerebras api.cerebras.ai
fireworks api.fireworks.ai
together api.together.xyz
huggingface router.huggingface.co

Any other provider gets no hosts, and the agent then reaches no model. The daemon logs "no known hosts for provider …".

Log in: in the terminal, with elyra and /login. There is no "Connect" button for Elyra.

Claude Code

Claude Code gets one login for Huskarl, shared by all bots. Your own ~/.claude and ~/.claude.json are not used, and are hidden from the bots.

Log in: in the bot's settings, Connect Claude Code next to Claude Code (the button is shown when it is installed and not logged in). Huskarl runs claude auth login with CLAUDE_CONFIG_DIR=~/.huskarl/agents/claude, and the browser opens. The status is read with claude auth status --json in the same folder.

Claude Code runs with your real HOME. That is where it finds its login in the Keychain. With another HOME it is logged out. What is private in your home folder is hidden by the sandbox (see Security), and Claude has no tools of its own.

The arguments are --strict-mcp-config --tools "" --setting-sources "", --system-prompt with the bot's instructions, and --allowedTools with the gateway's tools. There is no --allow-dangerously-skip-permissions, and "Full access" cannot be turned on. These are set as well: DISABLE_AUTOUPDATER=1, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, DISABLE_TELEMETRY=1, DISABLE_ERROR_REPORTING=1.

The model picker shows opus, sonnet and haiku, which follow the newest of each.

Grok Build

Grok Build also gets one login for Huskarl, in GROK_HOME=~/.huskarl/agents/grok. Your own ~/.grok is hidden from the bots.

Install: curl -fsSL https://x.ai/cli/install.sh | bash. Huskarl finds grok on PATH, or in ~/.grok/bin, ~/.local/bin, ~/.npm-global/bin, ~/.bun/bin, /opt/homebrew/bin and /usr/local/bin.

Log in: Connect Grok Build in the settings. Huskarl runs grok login with Huskarl's GROK_HOME, and the browser opens. It counts as logged in when ~/.huskarl/agents/grok/auth.json exists.

Before every start Huskarl writes ~/.huskarl/agents/grok/config.toml. Changes there are replaced:

# Written by Huskarl at every start; changes here are replaced.
[features]
telemetry = false

[telemetry]
trace_upload = false

[sandbox]
profile = "off"

[permission]
rules = [
  { action = "deny", tool = "bash" },
  { action = "deny", tool = "read" },
  { action = "deny", tool = "edit" },
  { action = "deny", tool = "grep" },
  { action = "deny", tool = "webfetch" },
  { action = "deny", tool = "websearch" },
  { action = "allow", tool = "mcp" },
]

deny always wins in Grok. Grok's own sandbox is off because Huskarl's Seatbelt already holds it in. In addition, GROK_TELEMETRY_ENABLED=false and GROK_SANDBOX=off are set, and Huskarl does not answer ACP requests for files (fs/*). ACP has no system prompt, so the instructions come first in the session's first prompt.

The model picker shows grok-build-0.1, grok-4.7 and grok-code-fast-1.

Model

Model in the settings is what is sent to the agent. A bot without a model uses the agent's default model. Empty the field to set a bot back to the default (see Settings). Below the field is a picker with the models the agent offers, grouped by provider. While the list is being fetched, it says "Fetching the models…".

  • Elyra: the list comes from elyra --list-models, which shows only providers you are logged in with. It is remembered for five minutes. The names are provider/model, for example anthropic/claude-sonnet-5-5.
  • Claude Code: anthropic/opus, anthropic/sonnet, anthropic/haiku. The prefix is removed before the model is given to Claude Code.
  • Grok Build: xai/grok-build-0.1, xai/grok-4.7, xai/grok-code-fast-1. The prefix is removed.

A model from a provider other than the agent's is refused when you save: "Claude Code can only use Anthropic's models, not …", and likewise for Grok Build and xAI.

Grok models via Elyra

You can also use Grok without Grok Build: add an xAI key with /login in Elyra, and xAI (Grok) shows up in Elyra's model picker. Choose an xai/… model. The key stays with Elyra. Huskarl does not store it, and the proxy lets through only api.x.ai.

Switching agents

Choose another agent in the settings and press Save. The new agent starts a new session without the old one's history. Huskarl's thread, the memory and the instructions come along.

The same goes for changes to name, role, instructions and model: they take effect the next time the agent starts. An agent that is not in a turn is stopped when you save, so the next message starts it again with the new settings.

If you save while the bot is in the middle of a turn, it finishes that run first. Afterwards the agent is restarted with the new settings.

The agents and PATH

Started by launchd, the daemon has only /usr/bin:/bin:/usr/sbin:/sbin and finds neither the agents nor the node that runs them. So when the daemon starts, it fetches PATH from your login shell ($SHELL -l, or /bin/zsh) and puts it first. If the shell does not answer within 5 seconds, the daemon keeps the PATH it was given. HUSKARL_LOGIN_PATH=off turns this off.

Not yet

  • Claude Code and Grok Build are built and unit-tested, but not tried end to end against a real login. Nor has it been tried whether the logins are renewed through the egress proxy (phase-5.md).
  • Codex and Pi.
  • Questions from the agent as cards in the thread. Today they are answered with "cancelled".