🌐 Translation: Translated from Korean.

TL;DR

5 Lessons Learned to Perfect Mobile Coding Optimization:

  1. Quotation mark input hassle β†’ Solved with Plain text execution
  2. Korean keyboard typos β†’ Solved with /γ„΄γ……γ…μ…˜ β†’ /state auto-conversion
  3. Unable to send keystrokes β†’ Solved with Interactive buttons
  4. Long responses getting cut off β†’ Solved with Automatic message splitting
  5. Difficulty checking files β†’ Solved with /download feature

Complete UI optimization for perfect Claude Code control from your smartphone!


1. The Challenges of Smartphone Development

In our previous post, we covered the snippet system and interactive buttons. In this final installment of the series, we share the trial and error we went throughβ€”and the solutions we foundβ€”to fully utilize Claude Code from a smartphone.

1.1 Why Mobile Coding Is Difficult

There are several barriers to doing development work on a smartphone:

Physical constraints:
β”œβ”€β”€ Small screen size (reduced code readability)
β”œβ”€β”€ Touch keyboard (slower typing speed)
β”œβ”€β”€ Inconvenient special character input (quotes, backticks)
└── No mouse (precise manipulation impossible)

Technical constraints:
β”œβ”€β”€ Inconvenient SSH app usage
β”œβ”€β”€ Difficult terminal operation
β”œβ”€β”€ Complex file transfers
└── Typos in long commands

1.2 The Goal of remote-claude

To use Claude Code on a smartphone as effectively as on a desktop, UI optimization is essential:

Desktop Smartphone (Before) Smartphone (with remote-claude)
Direct terminal access SSH app required Slack app only
Keyboard shortcuts Impossible Button taps
Typing long commands Many typos Plain text
File browsing scp/sftp required /download

Let’s now examine each of the 5 lessons learned and their solutions.


2. Lesson 1: The Quotation Mark Problem

2.1 The Problem

The most frustrating issue when first using remote-claude on a smartphone:

# Original command format
/ask "Fix the TypeScript type error"
/run "npm run build && npm test"

# Entering quotes on a smartphone
1. Tap the special character key
2. Find the quotation mark (may need long press)
3. iOS auto-converts to "smart quotes"
4. Syntax error occurs ❌

Entering " on a smartphone keyboard is more cumbersome than you’d think. Especially on iOS, the “smart quotes” feature converts "" to "", causing parsing errors.

2.2 Solution: Plain Text Execution

We implemented a system where typing regular text without quotes sends it directly to Claude Code:

// src/handlers/input-processor.ts
export function processDefaultInput(input: string): InputProcessingResult {
  // Filter Slack mentions (@user, @channel removed)
  const mentionFilterResult = filterSlackMentions(input.trim());

  return {
    stage: 4,
    action: 'default-input',
    shouldProcess: true,
    processedInput: mentionFilterResult.cleanedInput,
  };
}

2.3 Mobile Coding Improvement

# Before (quotes required)
/ask "Review this code"
/ask "Fix the TypeScript error"

# After (Plain text)
Review this code
Fix the TypeScript error

On a smartphone, you can simply type natural sentences. This solved the first barrier to mobile coding.


3. Lesson 2: Korean Keyboard Typos

3.1 The Problem

When typing Slack messages on a smartphone, it’s common to accidentally enter commands while the Korean keyboard is active:

Intended: /state (check status)
Actually typed: /γ„΄γ……γ…μ…˜ (Korean keyboard active)

Intended: /download
Actually typed: /μ• μ₯γ…γ…γ…‡ (Korean keyboard active)

Switching keyboards on a smartphone is cumbersome, and when quickly typing commands, you often don’t notice which keyboard layout is active.

3.2 Solution: Automatic Korean Keyboard Conversion

We implemented a system that automatically converts Korean keyboard input to English:

// src/utils/korean-mapper.ts

// Korean β†’ English keyboard mapping table
export const KOREAN_TO_ENGLISH_MAP: Record<string, string> = {
  // Initial consonants
  γ„±: 'r', γ„΄: 's', γ„·: 'e', γ„Ή: 'f', ㅁ: 'a',
  γ…‚: 'q', γ……: 't', γ…‡: 'd', γ…ˆ: 'w', γ…Š: 'c',
  // Vowels
  ㅏ: 'k', γ…‘: 'i', γ…“: 'j', γ…•: 'u', γ…—: 'h',
  γ…›: 'y', γ…œ: 'n', γ…£: 'l', γ…‘: 'm',
  // ...
};

// Direct mapping table (frequently used commands)
export const KOREAN_COMMAND_MAP: Record<string, string> = {
  '/γ„΄γ……γ…μ…˜': '/state',
  '/μ• μ₯γ…γ…γ…‡': '/download',
};

3.3 How Korean Keyboard Processing Works

It utilizes a Korean Unicode decomposition algorithm:

// Decompose composed Hangul (e.g., 'ν•œ' β†’ γ…Ž + ㅏ + γ„΄)
export function decomposeKorean(char: string): DecomposedKorean {
  const charCode = char.charCodeAt(0);
  const offset = charCode - 0xAC00; // Hangul start point

  // Initial: offset / (21 Γ— 28)
  // Medial: (offset % (21 Γ— 28)) / 28
  // Final: offset % 28
  return { initial, medial, final };
}

3.4 Mobile Coding Improvement

Input: /γ„΄γ……γ…μ…˜
Auto-converted to: /state
Result: Status check executes normally βœ…

Thanks to Korean keyboard processing, you can enter commands on a smartphone without switching keyboards. This is a core feature of our UI optimization.


4. Lesson 3: Unable to Send Keystrokes

4.1 The Problem

When Claude Code waits for user input (e.g., waiting for Enter key), there was no way to send keystrokes directly to the terminal from a smartphone:



Claude Code: "Press Enter to continue..."

Smartphone user:
β”œβ”€β”€ Open SSH app? β†’ Too cumbersome
β”œβ”€β”€ Type "enter" in Slack? β†’ Claude Code doesn't understand
└── Give up? β†’ Work interrupted ❌

4.2 Solution: Interactive Buttons

We implemented buttons using Slack Block Kit that allow sending keystrokes with a single tap:

// src/bot/interactive-buttons.ts
export function createQuickActionButtons() {
  return [
    // Row 1: Core functions
    {
      type: 'actions',
      elements: [
        { text: 'πŸ“Š Check Status', action_id: 'quick_state' },
        { text: 'πŸ“₯ Download File', action_id: 'quick_download' },
        { text: '🚫 Cancel Job', action_id: 'cancel_job' },
      ],
    },
    // Row 2: Key inputs
    {
      type: 'actions',
      elements: [
        { text: '⏎ Enter', action_id: 'send_enter' },
        { text: '⏎⏎ Enter*2', action_id: 'send_enter_twice' },
        { text: '↑', action_id: 'send_up' },
        { text: '↓', action_id: 'send_down' },
        { text: '←', action_id: 'send_left' },
        { text: 'β†’', action_id: 'send_right' },
      ],
    },
  ];
}

4.3 Interactive Button Layout

Button Function Use Case
πŸ“Š Check Status Capture Claude Code current screen Check progress
πŸ“₯ Download File Send file to Slack Check logs
🚫 Cancel Job Stop running task Cancel wrong command
⏎ Enter Send Enter key Respond to confirmation prompts
↑↓←→ Send arrow keys Menu selection

4.4 Mobile Coding Improvement

Before: Unable to send keystrokes β†’ Work interrupted
After: Tap button β†’ Enter sent β†’ Work continues βœ…

Interactive buttons are the core UI optimization feature that enables complete control of Claude Code from a smartphone.


5. Lesson 4: Message Length Limits

5.1 The Problem

When Claude Code responses are long, they hit Slack’s message limit (4000 characters):

Claude Code response: 8000 characters (code + explanation)
Slack message limit: 4000 characters
Result: Message delivery fails ❌

This happened frequently with code reviews or tasks requiring lengthy explanations.

5.2 Solution: Automatic Message Splitting

We implemented a system that automatically splits and sends long responses:

// src/utils/message-splitter.ts
export function splitMessage(content: string, maxLength: number = 2500): SplitMessageResult {
  // Set to 2500 characters for stability (with buffer below 4000 limit)
  const messages: string[] = [];
  let currentPos = 0;

  while (currentPos < content.length) {
    let splitLength = Math.min(maxLength, content.length - currentPos);

    // Natural splitting at line breaks
    const chunk = content.substring(currentPos, currentPos + splitLength);
    const lastNewlineIndex = chunk.lastIndexOf('\n');

    if (lastNewlineIndex > 0) {
      splitLength = lastNewlineIndex + 1;
    }

    messages.push(content.substring(currentPos, currentPos + splitLength));
    currentPos += splitLength;
  }

  return { messages, totalParts: messages.length };
}

5.3 Message Splitting Strategy

Processing an 8000-character response:

1. Split: [2500 chars] + [2500 chars] + [2500 chars] + [500 chars]
2. Display: [1/4], [2/4], [3/4], [4/4]
3. Send: Sequential delivery at 500ms intervals
4. Buttons: Added only to the last message

Result:
[1/4] First part...
[2/4] Second part...
[3/4] Third part...
[4/4] Final part... + [πŸ“Š] [πŸ“₯] [🚫] buttons

5.4 Mobile Coding Improvement

  • Complete response reception: All responses viewable without length limits
  • Automatic processing: No user intervention required
  • Progress indication: [1/4] format shows current position
  • Sequential delivery: Arrives at readable 500ms intervals

6. Lesson 5: Difficulty Checking Files

6.1 The Problem

When you need to check log files or config files during mobile coding:

Previous method:
1. Connect to server with SSH app
2. Run cat logs/app.log
3. Scroll on tiny screen...
4. Give up because it's too inconvenient ❌

Checking file contents on a smartphone was nearly impossible.

6.2 Solution: /download Feature

We implemented a feature to send files directly to Slack:

// src/handlers/file-download.ts
export async function handleFileDownload(
  app: App,
  channelId: string,
  channelConfig: ChannelConfig,
  filePath: string
): Promise<void> {
  // 1. Security validation (8 steps)
  const validation = validateFilePath(channelConfig.projectPath, filePath);

  // 2. File upload
  await app.client.files.uploadV2({
    channel_id: channelId,
    file: fs.createReadStream(resolvedPath),
    filename: path.basename(resolvedPath),
    title: `${channelConfig.projectName}: ${filePath}`,
  });
}

6.3 Security Validation (8 Steps)

File downloads require thorough security validation:

// src/utils/file-security.ts
export function validateFilePath(projectPath: string, userInputPath: string) {
  // 1. Empty path validation
  // 2. Absolute path conversion
  // 3. Path traversal prevention (blocks ../../etc/passwd)
  // 4. Sensitive file blocking (.env, .key, .pem, SSH keys)
  // 5. File existence check
  // 6. Directory blocking
  // 7. File size limit (10MB)
  // 8. Return success
}

6.4 Mobile Coding Improvement

# Check logs
/download logs/app.log
β†’ File uploaded to Slack
β†’ View immediately on mobile βœ…

# Check config files
/download config/settings.json
β†’ File uploaded to Slack
β†’ View immediately on mobile βœ…

7. Final Result: Smartphone Optimization Summary

7.1 Summary of 5 Lessons Learned

Problem Solution File
Quotation mark input hassle Plain text execution input-processor.ts
Korean keyboard typos Auto-conversion korean-mapper.ts
Unable to send keystrokes Interactive buttons interactive-buttons.ts
Long responses cut off Automatic message splitting message-splitter.ts
Difficulty checking files /download feature file-download.ts

7.2 Mobile Coding Workflow

The complete workflow for using remote-claude on a smartphone:

1. Open Slack app (project channel)

2. Request a task (Plain text)
   "Fix the TypeScript error"

3. Check progress (Button)
   Tap πŸ“Š button β†’ View Claude Code screen

4. When additional input is needed (Button)
   Tap ⏎ button β†’ Send Enter

5. View results (Auto-split)
   Receive [1/3], [2/3], [3/3] messages sequentially

6. When you need to check logs
   /download logs/build.log
   β†’ View file in Slack

7.3 UI Optimization Comparison

Item Before Optimization After Optimization
Command input Quotes + exact syntax Natural sentences
Keyboard switching Required Not needed
Keystroke input SSH app required Button tap
Long responses Truncated/failed Auto-split
File access scp/sftp Slack download
Overall UX 30% of desktop 90% of desktop

8. Wrapping Up the Series

8.1 remote-claude Series Summary

Through this 5-part series, we covered how to remotely control Claude Code via Slack:

Day Topic Key Content
1 Intro + Quick Start Architecture, 5-minute setup
2 Slack Bot Setup Permissions, Socket Mode
3 Multi-Project Management Job queue, channel separation
4 Maximizing Productivity Snippets, buttons
5 Smartphone Optimization Mobile coding complete

8.2 Future Plans

remote-claude continues to evolve:

Phase 2 Plans:
β”œβ”€β”€ Image support (screenshot sharing)
β”œβ”€β”€ File upload (code file transfer)
β”œβ”€β”€ Multiple sessions (multiple sessions in one channel)
└── Web dashboard (statistics and monitoring)

8.3 GitHub Repository

Full source code and installation guide:

8.4 Closing Thoughts

Being able to use Claude Code perfectly on a smartphone is thanks to much trial and error. The UI optimization features we built while overcoming each limitation of mobile coding will make your remote development experience more convenient.

At a cafΓ©, on the subway, in bed… use Claude Code from anywhere! πŸš€


Series Navigation


References