Mobile client for Claude Code, Codex, Gemini, and LM Studio
npm install @cerulin/chellControl Claude Code from your mobile device or integrate with Chell Desktop.
Free. Open source. Code anywhere.
``bashFrom npm registry
npm install -g @cerulin/chell
Usage
`bash
chell claude
`This will:
1. Start a Claude Code session
2. Authenticate via Auth0 (opens browser for login)
3. Allow real-time session sharing between Claude Code and your mobile app
Options
-
-h, --help - Show help
- -v, --version - Show version
- -m, --model - Claude model to use (default: sonnet)
- -p, --permission-mode - Permission mode: auto, default, or plan
- --claude-env KEY=VALUE - Set environment variable for Claude Code
- --claude-arg ARG - Pass additional argument to Claude CLITerminal Status Detection
Chell CLI detects Claude Code's state by monitoring PTY output for specific visual indicators. These indicators are not part of any official API and may break if Anthropic changes Claude Code's UI.
$3
> ⚠️ FRAGILE: These patterns are reverse-engineered from Claude Code's terminal output. If status detection breaks after a Claude Code update, check these patterns first.
#### 1. Spinner Characters (Thinking State)
Claude Code displays an animated spinner while processing. We detect these Unicode characters:
`
✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ (U+2731 - U+2739)
✻ ✼ ✽ ✾ ✿ (U+273B - U+273F)
❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ (U+2740 - U+274B)
`Detection logic:
src/claude/claudeLocal.ts → checkForSpinner()
- Spinner present → thinking state
- No spinner for 1 second → idle state#### 2. "Interrupted" Text (Escape Key Detection)
When user presses Escape to cancel a permission prompt, Claude Code shows:
`
Interrupted · What should Claude do instead?
`Detection logic:
src/claude/claudeLocal.ts → checks for "Interrupted" substring
- Clears permission state and transitions to idle#### 3. Permission Hook (Permission State)
Claude Code's hook system calls
chell notify --hook when permission is requested.Detection logic:
src/claude/utils/startChellServer.ts → /permission-hook endpoint
- Hook triggered → permission state
- Hook resolved → idle state$3
`
┌─────────────┐
│ idle │◄────────────────┐
└──────┬──────┘ │
│ spinner detected │ no spinner for 1s
▼ │
┌─────────────┐ │
┌─────────►│ thinking │─────────────────┘
│ └──────┬──────┘
│ │ permission hook
│ ▼
│ ┌─────────────┐
│ │ permission │
│ └──────┬──────┘
│ │ "Interrupted" or hook resolved or spinner
└─────────────────┘
`$3
Chell emits OSC 777 sequences for Chell Desktop to parse:
`
ESC ] 777 ; chell ; status ; BEL
ESC ] 777 ; chell ; unread ; BEL
ESC ] 777 ; chell ; permission-type ; BEL
`$3
If Claude Code's UI changes, update these files:
| Pattern | File | Function/Location |
|---------|------|-------------------|
| Spinner characters |
src/claude/claudeLocal.ts | spinnerChars regex |
| "Interrupted" text | src/claude/claudeLocal.ts | checkForSpinner() |
| Permission hook | src/claude/utils/injectHook.ts | Hook injection logic |Requirements
- Node.js >= 20.0.0
- Claude CLI installed & logged in (
claude command available in PATH)Developing locally
`bash
npm run dev # runs with tsx
or
npm run build && node bin/chell.mjs
``MIT