| name | lark-coding-agent-bridge |
| description | Bridge Feishu/Lark messenger with local Claude Code or Codex CLI for chat-based coding assistance with streaming cards and session management |
| triggers | ["set up lark bridge for claude code","connect feishu to my local coding agent","configure lark channel bridge","manage lark bot workspaces and sessions","troubleshoot lark coding agent bridge","add users to lark bot access control","switch workspace in lark bridge","debug lark bridge connection issues"] |
lark-coding-agent-bridge
Skill by ara.so — AI Agent Skills collection.
A lightweight bot that bridges Feishu/Lark messenger with your local Claude Code or Codex CLI. Send messages in Feishu and get streaming responses with tool calls updating in real-time cards. Each chat/topic maintains its own session with support for multiple workspaces, queueing, and file attachments.
What It Does
- Message forwarding: DM the bot or
@mention in groups to talk to your local coding agent
- Streaming cards: Real-time updates of text replies and tool calls on a single Lark card
- Session continuity: Each chat, topic, or document comment thread maintains its own session
- Queue management: Messages sent quickly are batched; commands like
/new, /cd, /stop interrupt current runs
- Multiple workspaces: Switch projects with
/cd and save common directories with /ws
- Media support: Send images and files directly to the bot
- Access control: Private by default with granular user/group permissions
Prerequisites
- Node.js >= 20.12.0
- At least one local agent installed and authenticated:
- A Feishu/Lark PersonalAgent app (QR wizard creates one on first run)
Installation
npm i -g lark-channel-bridge
pnpm add -g lark-channel-bridge
npx lark-channel-bridge run
First-Time Setup
lark-channel-bridge run
lark-channel-bridge run --app-id cli_xxx
lark-channel-bridge run --app-id cli_xxx --tenant lark
lark-channel-bridge run --agent claude
lark-channel-bridge run --workspace /path/to/project
The QR wizard:
- Displays QR code in terminal
- Scan with Feishu/Lark app
- Pick/create a PersonalAgent app
- Choose agent to initialize (claude or codex)
- Config saved to
~/.lark-channel/config.json
Background Service Management
lark-channel-bridge start
lark-channel-bridge status
lark-channel-bridge stop
lark-channel-bridge restart
lark-channel-bridge unregister
Important: Install globally before using service commands. The daemon records the CLI path, and npx temp cache paths break when cleaned.
Multiple Profiles (Claude + Codex)
lark-channel-bridge profile create claude --agent claude
lark-channel-bridge profile create codex --agent codex
lark-channel-bridge profile list
lark-channel-bridge profile use claude
lark-channel-bridge start --profile claude
lark-channel-bridge start --profile codex
lark-channel-bridge status --profile codex
lark-channel-bridge profile remove codex
lark-channel-bridge profile remove codex --purge --yes
lark-channel-bridge profile export claude --output ./claude-profile.json
lark-channel-bridge profile export claude --include-secrets --yes
In-Chat Slash Commands
Session Management
/new # Clear current session
/reset # Alias for /new
/cd /path/to/dir # Switch working directory and reset session
/resume # Resume compatible history for same agent/directory/permissions
/timeout 30 # Set 30-minute idle timeout
/timeout off # Disable timeout
/timeout default # Restore default timeout
/stop # Stop current run
Workspace Management
/ws list # List all named workspaces
/ws save myproject # Save current directory as "myproject"
/ws use myproject # Switch to "myproject" workspace
/ws remove myproject # Delete "myproject" workspace
Access Control
/invite user @username # Allow user to DM the bot
/invite admin @username # Add access-control admin
/invite group # Allow current group to use bot
/invite all group # Allow all groups bot has joined
/remove user @username # Remove user access
/remove admin @username # Remove admin
/remove group # Remove current group access
Diagnostics & Info
/status # Show profile, agent, working directory, session state
/config # Adjust preferences and view access panel
/help # Display help card
/ps # List local bridge processes
/exit <id|#> # Stop a bridge process
/reconnect # Force WebSocket reconnect
/doctor # Run diagnostics (include description for context)
Configuration
Profile Structure
Config location: ~/.lark-channel/config.json
{
"activeProfile": "default",
"profiles": {
"default": {
"name": "default",
"agent": "claude",
"feishu": {
"appId": "cli_xxx",
"tenant": "feishu"
},
"workspaces": {
"default": "/Users/me/.lark-channel-workspaces/claude/default",
"named": {
"myproject": "/Users/me/projects/myproject",
"webapp": "/Users/me/work/webapp"
}
},
"permissions": {
"defaultAccess": "full",
"maxAccess": "full"
}
}
}
}
Permission Modes
Edit the profile's permissions field:
{
"permissions": {
"defaultAccess": "full",
"maxAccess": "full"
}
}
Mode mappings:
| Bridge Access | Claude Mode | Codex Mode | Capabilities |
|---|
full | bypassPermissions | danger-full-access | All tools, auth flows, file writes |
workspace | acceptEdits | workspace-write | Limited to workspace directory |
read-only | plan | read-only | No file writes or dangerous operations |
Working Directories
The bridge validates directories exist, are actual directories, and aren't overly broad (not /, home root, system dirs, temp roots).
{
"workspaces": {
"default": "/Users/me/projects/default",
"named": {
"backend": "/Users/me/work/backend-api",
"frontend": "/Users/me/work/web-client",
"mobile": "/Users/me/work/mobile-app"
}
}
}
Switch in chat:
/cd /Users/me/work/new-project
/ws save new-project
/ws use backend
Process Management
lark-channel-bridge ps
lark-channel-bridge kill 12345
lark-channel-bridge kill 1
In Feishu chat:
/ps # List processes
/exit 1 # Stop first process
/exit 12345 # Stop by PID
Data Directories
~/.lark-channel/
├── config.json # Root config with profiles
├── active-profile # Last selected profile
├── profiles/
│ └── <profile>/
│ ├── sessions.json # Session state
│ ├── sessions.json.catalog.json # Agent-aware session catalog
│ ├── workspaces.json # Workspace bindings
│ ├── secrets.enc # Encrypted secrets
│ ├── media/ # Attachment cache
│ └── logs/
│ ├── daemon/ # Background service logs
│ └── <timestamp>/ # Structured run logs
└── registry/
├── processes.json # Process registry
└── locks/ # Profile and app locks
Environment Variables
export LARK_CHANNEL_HOME=/custom/path/to/state
export LARK_CHANNEL_LOG_DAYS=30
Code Examples
Starting Multiple Agent Profiles
#!/bin/bash
lark-channel-bridge profile create claude --agent claude --workspace ~/projects
lark-channel-bridge profile create codex --agent codex --workspace ~/projects
lark-channel-bridge start --profile claude
lark-channel-bridge start --profile codex
lark-channel-bridge status --profile claude
lark-channel-bridge status --profile codex
Scripted Deployment
#!/bin/bash
set -e
PROFILE_NAME="${1:-production}"
AGENT_TYPE="${2:-claude}"
WORKSPACE_PATH="${3:-$HOME/workspace}"
APP_ID="${LARK_APP_ID}"
APP_SECRET="${LARK_APP_SECRET}"
if [ -z "$APP_ID" ] || [ -z "$APP_SECRET" ]; then
echo "Error: Set LARK_APP_ID and LARK_APP_SECRET"
exit 1
fi
lark-channel-bridge profile create "$PROFILE_NAME" \
--agent "$AGENT_TYPE" \
--workspace "$WORKSPACE_PATH"
lark-channel-bridge profile use "$PROFILE_NAME"
lark-channel-bridge start --profile "$PROFILE_NAME" --app-id "$APP_ID"
echo "Bridge deployed as profile: $PROFILE_NAME"
Health Check Script
#!/bin/bash
PROFILE="${1:-default}"
if ! lark-channel-bridge status --profile "$PROFILE" | grep -q "running"; then
echo "Bridge not running, attempting restart..."
lark-channel-bridge restart --profile "$PROFILE"
sleep 5
if lark-channel-bridge status --profile "$PROFILE" | grep -q "running"; then
echo "Bridge restarted successfully"
exit 0
else
echo "Bridge failed to restart"
exit 1
fi
fi
echo "Bridge healthy"
exit 0
Programmatic Configuration Update
import { readFileSync, writeFileSync } from 'fs';
import { homedir } from 'os';
import { join } from 'path';
interface Profile {
name: string;
agent: 'claude' | 'codex';
permissions?: {
defaultAccess: 'full' | 'workspace' | 'read-only';
maxAccess: 'full' | 'workspace' | 'read-only';
};
workspaces?: {
default: string;
named?: Record<string, string>;
};
}
interface Config {
activeProfile: string;
profiles: Record<string, Profile>;
}
const configPath = join(homedir(), '.lark-channel', 'config.json');
function updateProfilePermissions(
profileName: string,
mode: 'full' | 'workspace' | 'read-only'
): void {
const config: Config = JSON.parse(readFileSync(configPath, 'utf-8'));
if (!config.profiles[profileName]) {
throw new Error(`Profile ${profileName} not found`);
}
config.profiles[profileName].permissions = {
defaultAccess: mode,
maxAccess: mode,
};
writeFileSync(configPath, JSON.stringify(config, null, 2));
console.log(`Updated ${profileName} to ${mode} mode`);
}
function addWorkspace(
profileName: string,
name: string,
path: string
): void {
const config: Config = JSON.parse(readFileSync(configPath, 'utf-8'));
if (!config.profiles[profileName]) {
throw new Error(`Profile ${profileName} not found`);
}
if (!config.profiles[profileName].workspaces) {
config.profiles[profileName].workspaces = {
default: path,
named: {},
};
}
if (!config.profiles[profileName].workspaces!.named) {
config.profiles[profileName].workspaces!.named = {};
}
config.profiles[profileName].workspaces!.named![name] = path;
writeFileSync(configPath, JSON.stringify(config, null, 2));
console.log(`Added workspace ${name}: ${path} to ${profileName}`);
}
updateProfilePermissions('production', 'workspace');
addWorkspace('production', 'api', '/home/user/projects/api');
Common Patterns
Multi-Workspace Development
# Start with default workspace
lark-channel-bridge run
# In Feishu, save current projects
/cd ~/work/backend
/ws save backend
/cd ~/work/frontend
/ws save frontend
/cd ~/work/mobile
/ws save mobile
# Switch between them quickly
/ws use backend
# ... do backend work ...
/ws use frontend
# ... do frontend work ...
# View all workspaces
/ws list
Team Setup with Access Control
# Creator sets up bot
lark-channel-bridge run --app-id cli_xxx
# Add team leads as admins (they can manage access)
/invite admin @tech-lead
/invite admin @product-lead
# Allow specific developers DM access
/invite user @developer1
/invite user @developer2
# Allow bot in team channels
# (In each channel, as creator or admin)
/invite group
# Or allow all groups at once
/invite all group
Locked-Down Production Setup
lark-channel-bridge profile create production \
--agent claude \
--workspace /opt/production/workspace
cat > /tmp/update-perms.json << 'EOF'
{
"permissions": {
"defaultAccess": "read-only",
"maxAccess": "workspace"
}
}
EOF
lark-channel-bridge start --profile production
In chat, users can still ask questions and get code suggestions, but the agent won't execute dangerous operations or write files outside the workspace.
Session Recovery After Restart
# After bridge restart, sessions persist automatically
# Resume last session in current chat
/resume
# Or start fresh
/new
# Check current state
/status
Troubleshooting
Bridge Won't Start
lark-channel-bridge ps
lark-channel-bridge kill 1
lark-channel-bridge status
tail -f ~/.lark-channel/profiles/default/logs/daemon/*.log
node --version
npm uninstall -g lark-channel-bridge
npm i -g lark-channel-bridge
Bot Not Responding in Feishu
# In chat, check connection
/status
/reconnect
# Verify app credentials
cat ~/.lark-channel/config.json | grep appId
# Run diagnostics
/doctor Cannot receive messages in group chat
# Check if group is allowed
/config # View access panel
/invite group # Add current group
Wrong Agent Type
lark-channel-bridge stop --profile wrong-agent
lark-channel-bridge profile remove wrong-agent
lark-channel-bridge profile create correct-agent --agent codex
lark-channel-bridge start --profile correct-agent
Session Not Resuming
# Sessions are agent + workspace + permission mode specific
# Check current state
/status
# If workspace or permissions changed, /resume won't find history
# Either:
# 1. Switch back to original workspace
/ws use original-project
# 2. Or start fresh
/new
Permission Denied Errors
# Check current permission mode
/status
# If agent complains about restricted access:
# 1. Increase permission level (edit config)
{
"permissions": {
"defaultAccess": "workspace", # or "full"
"maxAccess": "workspace" # or "full"
}
}
# 2. Restart bridge
lark-channel-bridge restart
# 3. Start new session with new permissions
/new
Working Directory Validation Failed
# Common causes:
# - Directory doesn't exist
# - Path is too broad (/, ~, /tmp, /usr, etc.)
# - Not a directory (is a file)
# Check current directory
/status
# Fix:
mkdir -p /path/to/valid/workspace
/cd /path/to/valid/workspace
# Or use an existing project
/cd ~/projects/my-app
Media Files Not Working
# Media downloaded to profile-specific cache
~/.lark-channel/profiles/<profile>/media/
# If files aren't reaching agent:
# 1. Check bridge logs
tail -f ~/.lark-channel/profiles/default/logs/<latest>/bridge.log
# 2. Verify file permissions
ls -la ~/.lark-channel/profiles/default/media/
# 3. Ensure working directory allows file access
/status # Check permission mode
Process Won't Stop
lark-channel-bridge stop
lark-channel-bridge ps
lark-channel-bridge kill 1
lark-channel-bridge unregister
lark-channel-bridge start
Log Retention Issues
du -sh ~/.lark-channel/profiles/*/logs/
export LARK_CHANNEL_LOG_DAYS=3
lark-channel-bridge restart
find ~/.lark-channel/profiles/*/logs -type f -mtime +7 -delete
Multiple Profiles Conflict
lark-channel-bridge ps
cat ~/.lark-channel/config.json | jq '.profiles[].feishu.appId'
lark-channel-bridge profile remove duplicate
This skill enables AI coding agents to help developers set up, configure, and troubleshoot the Lark Channel Bridge for seamless chat-based coding assistance.