# oh-my-codex explore vs omx sparkshell command routing: Key Differences

> Discover key differences between oh-my-codex explore and omx sparkshell. Understand explore for read-only queries and sparkshell for shell-native command routing in oh-my-codex.

- Repository: [Bellman/oh-my-codex](https://github.com/Yeachan-Heo/oh-my-codex)
- Tags: deep-dive
- Published: 2026-04-03

---

**`omx explore` serves as the primary read-only entry point for repository queries, while `omx sparkshell` acts as a specialized routing target for shell-native commands detected by the `resolveExploreSparkShellRoute` function in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts).**

The oh-my-codex CLI provides two distinct pathways for interacting with your codebase safely. Understanding how `omx explore` automatically routes certain prompts to the `omx sparkshell` binary helps you leverage the right tool for semantic LLM-driven exploration versus high-output shell operations.

## Core Architectural Differences

### omx explore as the Primary Entry Point

**`omx explore`** functions as the default interface for all read-only repository interactions. It accepts natural-language prompts or prompt files and primarily runs the **explore-harness** binary for shell-only operations. According to the source code in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts), this command handles semantic queries like "list all authentication modules" by invoking the richer LLM-driven explorer defined in [`prompts/explore.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/prompts/explore.md).

When you submit a prompt, the system first attempts to classify whether your input requires the full LLM context or qualifies for faster shell-native execution.

### omx sparkshell as the Specialized Routing Target

**`omx sparkshell`** operates as a native side-car binary designed specifically for qualified shell commands. Unlike the explore command's general-purpose harness, sparkshell executes **only** read-only Git sub-commands or utilities that produce large but safe output streams. The binary is located via `resolveSparkShellBinaryPathWithHydration` in [`src/cli/sparkshell.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/sparkshell.ts) (lines 1-78) and supports an optional `--tmux-pane` mode for bounded pane summarization.

## How Command Routing Works in oh-my-codex

### The Routing Detection Logic

The critical decision point occurs in `resolveExploreSparkShellRoute` within [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts) (lines 99-134). This function inspects your prompt for specific patterns:

- **Git commands**: `git log`, `git diff`, and other read-only Git sub-commands
- **File system utilities**: `find`, `ls`, `rg` (ripgrep), `grep`
- **Explicit shell prefix**: Commands prefixed with `run …`

When detected, the function returns an `ExploreSparkShellRoute` object containing the parsed `argv` array and a `reason` field set to either `"shell-native"` or `"long-output"` based on the command's expected output volume.

```typescript
// From src/cli/explore.ts
export function resolveExploreSparkShellRoute(prompt: string): ExploreSparkShellRoute | undefined {
  const explicitShellPrefix = EXPLICIT_SHELL_PREFIX_PATTERN.test(prompt.trim());
  const normalized = prompt.trim().replace(EXPLICIT_SHELL_PREFIX_PATTERN, '');
  const argv = tokenizeExploreShellCommand(normalized);
  
  if (command === 'git' && isReadOnlyGitArgs(argv)) {
    return { argv, reason: classifyLongOutputShellCommand(argv) ? 'long-output' : 'shell-native' };
  }
  
  if (explicitShellPrefix && shellNativeShape && ['find','ls','rg','grep'].includes(command)) {
    return { argv, reason: classifyLongOutputShellCommand(argv) ? 'long-output' : 'shell-native' };
  }
  return undefined;
}

```

### Execution Flow from explore to sparkshell

When routing triggers, the `runExploreViaSparkShell` function (lines 137-156 in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts)) takes over:

1. Resolves the sparkshell binary path using `resolveSparkShellBinaryPathWithHydration`
2. Executes the native `omx-sparkshell` binary with the routed arguments
3. Streams stdout and stderr directly to your terminal

If no route matches, the system falls back to the standard explore-harness via `resolvePackagedExploreHarnessCommand`.

## Practical Usage Examples

### Automatic Routing Through omx explore

For standard Git operations, the routing happens transparently:

```bash

# Automatically routed to sparkshell due to git log pattern

omx explore --prompt "git log --oneline -10"

```

The `resolveExploreSparkShellRoute` function recognizes the read-only Git pattern and returns a route with `reason: "long-output"`, allowing sparkshell to stream the concise log efficiently.

### Semantic Queries Bypassing Routing

For natural language questions requiring LLM analysis:

```bash

# Forces use of the explore-harness and LLM contract

omx explore --prompt "Which files import the axios library?"

```

Since this prompt contains no shell-native tokens, `resolveExploreSparkShellRoute` returns `undefined`, and the system invokes the full explorer defined in [`prompts/explore.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/prompts/explore.md).

### Direct sparkshell Invocation

Bypass the routing logic entirely when you know you need shell execution:

```bash

# Direct execution via omx sparkshell

omx sparkshell git diff --stat
omx sparkshell --tmux-pane %12 --tail-lines 400

```

Direct calls require the `OMX_SPARKSHELL_BIN` environment variable for binary resolution and enforce the same strict read-only guarantees as the routed path.

## Safety Guarantees and Configuration

Both execution paths maintain **strict read-only contracts** preventing file modifications or arbitrary pipeline execution. The explore-harness cannot invoke non-allowed binaries, while sparkshell restricts execution to qualified commands with safe output profiles.

Configure the binaries via environment variables:

- **`OMX_EXPLORE_BIN`**: Controls the explore-harness binary location (see [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts))
- **`OMX_SPARKSHELL_BIN`**: Controls the sparkshell binary location (see [`src/cli/sparkshell.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/sparkshell.ts))

## Summary

- **`omx explore`** provides the default entry point for safe, read-only repository queries with automatic routing logic.
- **`resolveExploreSparkShellRoute`** in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts) detects shell-native patterns (git, find, ls, rg, grep) and "run" prefixes to trigger sparkshell routing.
- **`omx sparkshell`** executes as a specialized binary for high-output or shell-native commands, offering efficient streaming and tmux integration.
- Both commands respect the read-only safety contract defined in [`AGENTS.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/AGENTS.md) (lines 6-13) and use distinct environment variables for binary resolution.

## Frequently Asked Questions

### What triggers oh-my-codex to route my explore command to sparkshell?

The `resolveExploreSparkShellRoute` function checks for read-only Git commands (`git log`, `git diff`), file system utilities (`find`, `ls`, `rg`, `grep`), or an explicit `run` prefix. When your prompt matches these patterns in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts), the system returns an `ExploreSparkShellRoute` and delegates execution to the sparkshell binary instead of the LLM-driven explorer.

### Can I force omx explore to use the LLM instead of routing to sparkshell?

Yes. Avoid shell-native command patterns in your prompt. Instead of `omx explore --prompt "git log"`, use natural language like `omx explore --prompt "show me recent commits"`. When `resolveExploreSparkShellRoute` finds no matching tokens, it returns `undefined` and the system invokes the explore-harness with the full LLM contract from [`prompts/explore.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/prompts/explore.md).

### Is omx sparkshell safe to run directly on production codebases?

Yes. According to the source code in [`src/cli/sparkshell.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/sparkshell.ts) and the safety policies in [`AGENTS.md`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/AGENTS.md), the sparkshell binary inherits the same read-only guarantees as `omx explore`. It explicitly validates arguments through `isReadOnlyGitArgs` and similar guards, exiting with an error if you attempt to execute modifying commands like `git push` or `rm`.

### How do I configure custom binary paths for oh-my-codex commands?

Set the **`OMX_EXPLORE_BIN`** environment variable to override the default explore-harness location, or use **`OMX_SPARKSHELL_BIN`** to specify a custom path for the `omx-sparkshell` binary. Both variables are resolved through the hydration functions in [`src/cli/explore.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/explore.ts) and [`src/cli/sparkshell.ts`](https://github.com/Yeachan-Heo/oh-my-codex/blob/main/src/cli/sparkshell.ts) respectively.