Skip to main content
Tutorials Last updated: 11 March 2026

Multi-engine workflows

This tutorial shows you how to use different engines for different tasks and set up defaults so you don't have to think about it. Swap between Claude Code, C...

This tutorial shows you how to use different engines for different tasks and set up defaults so you don’t have to think about it. Swap between Claude Code, Codex, OpenCode, Pi, Gemini CLI, and Amp with a single prefix — from your phone, laptop, or any device with Telegram.

What you’ll learn: Engine directives, persistent defaults, and when to use which engine.

Why multiple engines?

Different engines have different strengths:

EngineGood atUnique features
Claude CodeComplex refactors, architecture, long contextInteractive permissions, plan mode, ask mode, diff preview
CodexFast edits, shell commands, quick fixesReasoning levels, device re-auth (/auth)
OpenCode75+ providers via Models.dev, local modelsBroadest provider support
PiMulti-provider auth, conversationalContext compaction
Gemini CLIGoogle models, plan mode, model routingAuto Pro/Flash routing, sandboxing, extensions
AMPSourcegraph integration, thread sharingMode selection (deep/rush/smart), rich permissions

See the engine compatibility matrix in the README for a full feature-by-feature breakdown.

You might want Codex for quick tasks and Claude Code for deep work—without manually specifying every time.

1. One-off engine selection

Prefix any message with /<engine>:

You /claude refactor this module to use dependency injection

You /codex add a —verbose flag to the CLI

You /pi explain how the event loop works in this codebase

The engine only applies to that message. The response will have a resume line for that engine:

Untether done · claude · 8s
claude --resume abc123

When you reply, Untether sees claude --resume and automatically uses Claude Code—you don’t need to repeat /claude.

2. Engine + project + branch

Directives combine. Order doesn’t matter:

You /claude /happy-gadgets @feat/di refactor to use dependency injection

Or:

You /happy-gadgets @feat/di /claude refactor to use dependency injection

Both do the same thing: run Claude Code in the happy-gadgets project on the feat/di branch.

Directives are only parsed at the start Everything after the first non-directive word is the prompt. /claude fix /this/path uses Claude Code with prompt “fix /this/path”—it doesn’t try to parse /this as a directive.

3. Set a default engine for a chat

Use /agent set to change the default for the current scope:

You /agent set claude

Response:

Untether chat default engine set to claude

Now all new conversations in this chat use Claude Code (unless you explicitly override with /codex).

Check the current default:

You /agent

Example response:

Untether engine: claude (chat default)
defaults: topic: none, chat: claude, project: none, global: codex
available: codex, claude, opencode, pi, gemini, amp

Clear it:

You /agent clear

Response:

Untether chat default engine cleared.

4. Defaults in topics

If you use Telegram forum topics, /agent set applies per-topic:

You topic: Backend work
/agent set claude

You topic: Quick fixes
/agent set codex

Each topic remembers its own default.

5. Per-project defaults

Set a default engine in your project config:

=== “untether config”

```sh
untether config set projects.happy-gadgets.path "~/dev/happy-gadgets"
untether config set projects.happy-gadgets.default_engine "claude"
```

=== “toml”

```toml
[projects.happy-gadgets]
path = "~/dev/happy-gadgets"
default_engine = "claude"
```

Now /happy-gadgets tasks default to Claude Code, even if your global default is Codex.

6. Selection precedence

When Untether picks an engine, it checks (highest to lowest):

  1. Resume line — replying to claude --resume ... uses Claude Code
  2. Explicit directive/codex ... uses Codex
  3. Topic default/agent set in this forum topic
  4. Chat default/agent set in this chat
  5. Project defaultdefault_engine in project config
  6. Global defaultdefault_engine at the top of untether.toml

This means: resume lines always win, then explicit directives, then the most specific default applies.

With session_mode = "chat", stored sessions are per engine. Replying to a resume line for another engine runs that engine and updates its stored session without overwriting other engines.

Example Chat sessions with two engines (assume default engine is codex):

1. You send: `fix the failing tests` -> bot replies with `codex resume A` (stores Codex session A).
2. You reply to an older Claude Code message containing `claude --resume B` -> runs Claude Code and stores Claude Code session B.
3. You send a new message (not a reply) -> auto-resumes Codex session A (default engine), Claude Code session B remains stored for future replies or defaults.

7. Practical patterns

Pattern: Quick questions vs. deep work

=== “untether config”

```sh
# Global default for quick stuff
untether config set default_engine "codex"

# Project default for complex codebase
untether config set projects.backend.path "~/dev/backend"
untether config set projects.backend.default_engine "claude"
```

=== “toml”

```toml
# Global default for quick stuff
default_engine = "codex"

# Project default for complex codebase
[projects.backend]
path = "~/dev/backend"
default_engine = "claude"
```

Simple messages go to Codex. /backend messages go to Claude Code.

Pattern: Topic per engine

Create forum topics like “Claude Code work” and “Codex tasks”, then /agent set in each:

You topic: Claude Code deep-dives
/agent set claude

You topic: Quick Codex fixes
/agent set codex

Drag tasks to the right topic and the engine follows.

Pattern: Override for specific tasks

Even with defaults, you can always override:

You /codex just add a print statement here

Works regardless of what the default is.

Recap

Want to…Do this
Use an engine once/claude ... or /codex ...
Set default for chat/agent set claude
Set default for topic/agent set ... in the topic
Set default for projectdefault_engine = "..." in config
Set global defaultdefault_engine = "..." at top of config
Check current default/agent
Clear default/agent clear

You’re done!

That’s the end of the tutorials. You now know how to:

  • ✅ Install and configure Untether
  • ✅ Send tasks and continue conversations
  • ✅ Cancel runs mid-flight
  • ✅ Control agent actions with approval buttons
  • ✅ Target repos and branches from chat
  • ✅ Use multiple engines effectively

Where to go next

Want to do something specific?

Want to understand the internals?

Need exact syntax?

Was this helpful?

Related Articles