# team-employee

Manage OpenClaw Docker container instances for team members.

## Trigger

When user requests to manage team member OpenClaw containers:
- "add employee" / "添加员工"
- "remove employee" / "删除员工"
- "deploy employee instance"
- "manage team containers"
- "list team"

## Description

Manage OpenClaw Docker container instances for team members on the local machine. Supports adding new employees, removing employees, and viewing the list.

## Quick Usage

```bash
# Shortcut
team-employee add zhangsan
team-employee remove zhangsan
team-employee delete zhangsan
team-employee list
```

Or use the script directly:

```bash
cd ~/.openclaw/workspace/skills/team-employee
bash run.sh <command> [arguments]
```

## Commands

| Command | Description |
|---------|-------------|
| add \<name\> [app_id] [app_secret] | Add new employee and deploy container |
| rebuild \<name\> | Rebuild container using existing config |
| remove \<name\> | Remove container (keep config) |
| delete \<name\> | Remove container and all config |
| list | List all containers with config paths |
| fix-permissions | Fix read permissions for all config files |

### add Parameters

| Parameter | Description | Required |
|-----------|-------------|----------|
| name | Employee name (used for container and config dir) | Yes |
| feishu_app_id | Feishu App ID | No |
| feishu_app_secret | Feishu App Secret | No |

## Features

### add - Add Employee

1. **Check environment**: Docker status, port availability
2. **Create config directory**: `~/openclaw-config/openclaw-{name}/`
3. **Generate config file**: Auto-create openclaw.json
4. **Create workspace dirs**: workspace, identity, cron, canvas
5. **Start container**: Use host network mode
6. **Start Gateway**: Launch OpenClaw Gateway inside container

### rebuild - Rebuild Container

Rebuild an existing container using the existing local configuration:

1. **Stop and remove old container** (config preserved)
2. **Read existing config** from `~/openclaw-config/openclaw-{name}/`
3. **Start new container** with bridge network (fixed port 18789)
4. **Mount config directory** to container's `.openclaw`

**Key features:**
- Uses **bridge network** mode to avoid port conflicts with host
- Preserves all existing config, credentials, and workspace data
- Fixed port 18789 (consistent across all rebuilt containers)
- Useful for: fixing broken containers, changing network mode, applying config changes

**Usage:**
```bash
./run.sh rebuild team-assist
```

### remove - Remove Container (Keep Config)

- Stop and remove Docker container
- Keep config directory `~/openclaw-config/openclaw-{name}/`
- Useful for redeploying while preserving data

### delete - Full Delete

- Stop and remove Docker container
- Delete config directory `~/openclaw-config/openclaw-{name}/`
- **Irreversible**, use with caution

### list - View List

Show all team containers with:
- Container name
- Running status
- Gateway port
- Config directory path
- Feishu integration status

## Environment Variables

### Required

```bash
export MINIMAX_API_KEY=your_minimax_api_key
```

**API Key Priority** (checked in order):
1. Environment variable `MINIMAX_API_KEY`
2. `~/.openclaw/openclaw.json`
3. `~/.config/openclaw/config.json`
4. `/etc/openclaw/config.json`

### Auto-Detection

The script **automatically detects** the container's home directory by:
1. Running a test container to get `$HOME`
2. Inspecting the Docker image for default user
3. Falling back to common paths (`/home/ubuntu`, `/root`)

**No manual configuration needed** - works with any Docker image!

## Prerequisites

- Docker installed and running
- MiniMax API Key (from environment or config file)
- Feishu App (optional, for Feishu integration)
- Python 3 (for JSON parsing)
- openssl (for token generation)

### Feishu App Permissions

For Feishu integration, create a Feishu app with permissions:
1. **im:message** - Send and receive messages
2. **cardkit:card:write** - Send interactive cards

Create app: https://open.feishu.cn/

## Output

| Item | Path/Port |
|------|-----------|
| Config Dir | `~/openclaw-config/openclaw-{name}/` |
| Gateway Port | 18790+ (auto-assigned) |
| Container Name | `openclaw-{name}` |

### Config Directory Structure

```
~/openclaw-config/openclaw-{name}/
├── openclaw.json          # Main config file
├── workspace/             # Workspace directory
│   ├── AGENTS.md
│   ├── SOUL.md
│   └── USER.md
├── identity/              # Identity config
├── cron/                  # Cron jobs
└── canvas/                # Canvas data
```

## Advanced Features

### Automatic Container Path Detection

The script intelligently detects the correct home directory for any Docker image:

**Detection Process**:
1. **Test Run**: Launches temporary container and reads `$HOME`
2. **Inspect User**: Checks image metadata for default user
3. **Smart Fallback**: Uses common paths based on user type (root → `/root`, others → `/home/username`)

**Supported Images**:
- ✅ Standard Ubuntu images (`ubuntu:latest` → `/home/ubuntu`)
- ✅ Alpine images (`alpine:latest` → `/home/alpine` or `/root`)
- ✅ Root-based images → `/root`
- ✅ Custom user images → `/home/{username}`
- ✅ Any image with proper USER directive

**Example Output**:
```
🔍 检测容器镜像用户目录...
✅ 容器用户目录: /home/ubuntu

📦 容器路径映射:
  配置: ~/openclaw-config/openclaw-zhangsan -> /home/ubuntu/.openclaw
  共享: ~/openclaw-team/shared-dir -> /home/ubuntu/openclaw-team/shared-dir (只读)
```

## Troubleshooting

If issues occur, check:
1. Docker running: `docker ps`
2. Port in use: `lsof -i :18790` (macOS) or `netstat -tlnp | grep 187` (Linux)
3. Container logs: `docker logs openclaw-{name}`
4. API Key available: `echo $MINIMAX_API_KEY`
5. Container path mapping: Check volume mounts with `docker inspect openclaw-{name}`

### Common Issues & Solutions

#### Port Conflict with Host Gateway

**Symptom**: Container fails to start with error:
```
Gateway failed to start: another gateway instance is already listening on ws://127.0.0.1:18791
Port 18791 is already in use
```

**Cause**: The host machine already has an OpenClaw Gateway running on the same port that the container tries to use.

**Solution**: Use **bridge network mode** instead of host mode:

```yaml
# docker-compose.yml
team-code-expert:
  image: openclaw-agent:latest
  container_name: openclaw-team-code-expert
  volumes:
    - /home/ubuntu/openclaw-config/openclaw-team-code-expert:/home/openclaw/.openclaw
  environment:
    - AGENT_ROLE=member
    - GATEWAY_PORT=18791
    - MEMBER_NAME=team-code-expert
    - OPENCLAW_ALLOW_UNCONFIGURED=true
    - MINIMAX_API_KEY=${MINIMAX_API_KEY}
  networks:
    - openclaw-network  # Use bridge network
  restart: unless-stopped
  command: sh -c "openclaw gateway run --allow-unconfigured --port ${GATEWAY_PORT:-18791} > /tmp/gateway.log 2>&1 & tail -f /dev/null"

networks:
  openclaw-network:
    driver: bridge
```

**Why this works**: 
- Bridge mode isolates the container's network stack from the host
- Container gets its own IP address on the docker network
- No port conflict with host's Gateway
- Feishu connects via WebSocket (outbound connection from container to Feishu servers)
- No port mapping / exposure needed

#### Missing Feishu SDK

**Symptom**: 
```
[plugins] feishu failed to load: Cannot find module '@larksuiteoapi/node-sdk'
```

**Solution**: Install the SDK inside the container:
```bash
docker exec --user root <container-name> npm install -g @larksuiteoapi/node-sdk
docker restart <container-name>
```

#### GATEWAY_PORT Environment Variable Not Passed

**Symptom**:
```
error: option '--port <port>' argument missing
```

**Solution**: Use proper shell variable expansion in docker-compose:
```yaml
command: sh -c "openclaw gateway run --allow-unconfigured --port ${GATEWAY_PORT:-18791} > /tmp/gateway.log 2>&1 & tail -f /dev/null"
```

The `:-18791` provides a default value if the variable is not set.


---

## Container Upgrade

Upgrade container image versions using `run.sh`.

### Design

`rebuild` delegates to `upgrade` with the current image tag preserved. `upgrade` handles all config consolidation and container lifecycle.

```
rebuild → do_upgrade (current image, no change)
upgrade → do_upgrade (new image, other config same)
```

### Usage

```bash
# Rebuild: preserve current image version (e.g. 2026.3.7 stays 2026.3.7)
./run.sh rebuild feichen

# Upgrade: change to latest
./run.sh upgrade feichen

# Upgrade: change to specific version
./run.sh upgrade feichen 2026.3.23
./run.sh upgrade feichen 2026.3.1
```

### Notes

- `rebuild` reads the current image tag from the running container via `docker inspect`
- `upgrade` pulls the target image before restarting the container
- All other config (port, volumes, env vars, network mode) is preserved from existing container
- Both commands run entirely on the host, no container exec needed
