@xcanwin/manyoyo 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -91
- package/bin/manyoyo.js +67 -9
- package/docker/manyoyo.Dockerfile +1 -1
- package/docs/README_EN.md +233 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,103 +1,121 @@
|
|
|
1
|
+
[English](docs/README_EN.md) | [ [中文](README.md) ]
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# MANYOYO(慢悠悠)
|
|
2
6
|
|
|
3
7
|
**MANYOYO** 是一款 AI 智能体提效安全沙箱,安全、高效、省 token,专为 Agent YOLO 模式设计,保障宿主机安全。
|
|
4
8
|
|
|
5
|
-
预装常见 Agent 与工具,进一步节省 token。循环自由切换 Agent 和
|
|
9
|
+
预装常见 Agent 与工具,进一步节省 token。循环自由切换 Agent 和 `/bin/bash`,进一步提效。
|
|
6
10
|
|
|
7
|
-
MANYOYO
|
|
11
|
+
**MANYOYO** 提供隔离的 Docker/Podman 容器环境,用于安全运行 AI 智能体命令行工具。
|
|
8
12
|
|
|
9
13
|
## 功能亮点
|
|
10
14
|
|
|
11
|
-
-
|
|
15
|
+
- **多智能体支持**:支持 claude code, gemini, codex, opencode
|
|
12
16
|
- **安全隔离**:保护宿主机,支持安全容器嵌套(Docker-in-Docker)
|
|
13
|
-
-
|
|
17
|
+
- **快速启动**:快捷开启常见 Agent YOLO / SOLO 模式(例如 claude --dangerously-skip-permissions)
|
|
14
18
|
- **便捷操作**:快速进入 `/bin/bash`
|
|
15
19
|
- **会话恢复**:安装 Skills Marketplace 可快速恢复会话
|
|
16
|
-
-
|
|
20
|
+
- **灵活自定义**:支持自定义 `BASEURL`、`AUTH_TOKEN` 等变量
|
|
17
21
|
- **配置管理**:快捷导入配置文件
|
|
18
22
|
- **高级模式**:支持危险容器嵌套(mount-docker-socket)、自定义沙箱镜像
|
|
19
23
|
|
|
20
24
|
# 使用方法
|
|
21
25
|
|
|
22
|
-
## 1. 安装
|
|
23
|
-
|
|
24
|
-
- 安装 [podman](https://podman.io/docs/installation)
|
|
26
|
+
## 1. 安装 manyoyo
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
### 全局安装(推荐)
|
|
27
29
|
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
iv=1.4.0-all && podman build -t localhost/xcanwin/manyoyo:$iv -f docker/manyoyo.Dockerfile . --build-arg EXT=all --no-cache
|
|
31
|
-
podman image prune -f
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g @xcanwin/manyoyo
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
### Global Installation (Recommended)
|
|
34
|
+
### 本地开发
|
|
37
35
|
|
|
38
36
|
```bash
|
|
39
|
-
npm install -g
|
|
37
|
+
npm install -g .
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
## 2. 安装 podman
|
|
41
|
+
|
|
42
|
+
- 安装 [podman](https://podman.io/docs/installation)
|
|
43
|
+
|
|
44
|
+
## 3. 编译镜像
|
|
45
|
+
|
|
46
|
+
安装 manyoyo 后,可以使用内置命令构建镜像:
|
|
43
47
|
|
|
44
48
|
```bash
|
|
45
|
-
|
|
49
|
+
# 拉取基础镜像
|
|
50
|
+
podman pull ubuntu:24.04
|
|
51
|
+
|
|
52
|
+
# 使用 manyoyo 构建镜像(推荐)
|
|
53
|
+
manyoyo --ib all # 构建 all 版本(包含所有工具)
|
|
54
|
+
manyoyo --ib common # 构建 common 版本(基础版本)
|
|
55
|
+
manyoyo --ib go,codex,java,gemini # 构建 go 版本(包含 go,codex,java,gemini 工具)
|
|
56
|
+
|
|
57
|
+
# 自定义镜像名称和版本
|
|
58
|
+
manyoyo --ib all --in myimage --iv 2.0.0
|
|
59
|
+
# 构建:myimage:2.0.0-all
|
|
60
|
+
|
|
61
|
+
# 或手动构建(不推荐)
|
|
62
|
+
iv=1.4.0 && podman build -t localhost/xcanwin/manyoyo:$iv-all -f docker/manyoyo.Dockerfile . --build-arg EXT=all --no-cache
|
|
63
|
+
podman image prune -f
|
|
46
64
|
```
|
|
47
65
|
|
|
48
66
|
## 4. 使用方法
|
|
49
67
|
|
|
50
|
-
###
|
|
68
|
+
### 基础命令
|
|
51
69
|
|
|
52
70
|
```bash
|
|
53
|
-
#
|
|
71
|
+
# 显示帮助
|
|
54
72
|
manyoyo -h
|
|
55
73
|
|
|
56
|
-
#
|
|
74
|
+
# 显示版本
|
|
57
75
|
manyoyo -V
|
|
58
76
|
|
|
59
|
-
#
|
|
77
|
+
# 列出所有容器
|
|
60
78
|
manyoyo -l
|
|
61
79
|
|
|
62
|
-
#
|
|
80
|
+
# 创建新容器并使用环境文件
|
|
63
81
|
manyoyo -n test --ef .env -y c
|
|
64
82
|
|
|
65
|
-
#
|
|
83
|
+
# 恢复现有会话
|
|
66
84
|
manyoyo -n test -- -c
|
|
67
85
|
|
|
68
|
-
#
|
|
86
|
+
# 在交互式 shell 中执行命令
|
|
69
87
|
manyoyo -n test -x /bin/bash
|
|
70
88
|
|
|
71
|
-
#
|
|
89
|
+
# 执行自定义命令
|
|
72
90
|
manyoyo -n test -x echo "hello world"
|
|
73
91
|
|
|
74
|
-
#
|
|
92
|
+
# 删除容器
|
|
75
93
|
manyoyo -n test --rm
|
|
76
94
|
```
|
|
77
95
|
|
|
78
|
-
###
|
|
96
|
+
### 环境变量
|
|
79
97
|
|
|
80
|
-
####
|
|
98
|
+
#### 字符串格式
|
|
81
99
|
|
|
82
100
|
```bash
|
|
83
|
-
#
|
|
101
|
+
# 直接传递
|
|
84
102
|
manyoyo -e "VAR=value" -x env
|
|
85
103
|
|
|
86
|
-
#
|
|
104
|
+
# 多个变量
|
|
87
105
|
manyoyo -e "A=1" -e "B=2" -x env
|
|
88
106
|
```
|
|
89
107
|
|
|
90
|
-
####
|
|
108
|
+
#### 文件格式
|
|
91
109
|
|
|
92
110
|
```bash
|
|
93
|
-
#
|
|
111
|
+
# 从文件加载
|
|
94
112
|
manyoyo --ef .env -x env
|
|
95
113
|
```
|
|
96
114
|
|
|
97
|
-
|
|
115
|
+
环境文件(`.env`)支持以下格式:
|
|
98
116
|
|
|
99
117
|
```bash
|
|
100
|
-
#
|
|
118
|
+
# 使用 export 语句
|
|
101
119
|
export ANTHROPIC_BASE_URL="https://api.anthropic.com"
|
|
102
120
|
# export CLAUDE_CODE_OAUTH_TOKEN="sk-xxxxxxxx"
|
|
103
121
|
export ANTHROPIC_AUTH_TOKEN="sk-xxxxxxxx"
|
|
@@ -108,107 +126,108 @@ export ANTHROPIC_DEFAULT_SONNET_MODEL="claude-sonnet-4-5"
|
|
|
108
126
|
export ANTHROPIC_DEFAULT_HAIKU_MODEL="claude-haiku-4-5"
|
|
109
127
|
export CLAUDE_CODE_SUBAGENT_MODEL="claude-sonnet-4-5"
|
|
110
128
|
|
|
111
|
-
#
|
|
129
|
+
# 简单的键值对
|
|
112
130
|
API_KEY=your-api-key-here
|
|
113
131
|
|
|
114
|
-
#
|
|
132
|
+
# 带引号的值(引号会被移除)
|
|
115
133
|
MESSAGE="Hello World"
|
|
116
134
|
PATH='/usr/local/bin'
|
|
117
135
|
```
|
|
118
136
|
|
|
119
|
-
### AI CLI
|
|
137
|
+
### AI CLI 快捷方式(跳过权限确认)
|
|
120
138
|
|
|
121
139
|
```bash
|
|
122
140
|
# Claude Code
|
|
123
|
-
manyoyo -y c #
|
|
141
|
+
manyoyo -y c # 或: claude, cc
|
|
124
142
|
|
|
125
143
|
# Gemini
|
|
126
|
-
manyoyo -y gm #
|
|
144
|
+
manyoyo -y gm # 或: gemini, g
|
|
127
145
|
|
|
128
146
|
# Codex
|
|
129
|
-
manyoyo -y cx #
|
|
147
|
+
manyoyo -y cx # 或: codex
|
|
130
148
|
|
|
131
149
|
# OpenCode
|
|
132
|
-
manyoyo -y oc #
|
|
150
|
+
manyoyo -y oc # 或: opencode
|
|
133
151
|
```
|
|
134
152
|
|
|
135
|
-
###
|
|
153
|
+
### 交互式会话管理
|
|
136
154
|
|
|
137
|
-
|
|
155
|
+
退出容器会话后,系统将提示您选择操作:
|
|
138
156
|
|
|
139
|
-
- `y` -
|
|
140
|
-
- `n` -
|
|
141
|
-
- `1` -
|
|
142
|
-
- `
|
|
143
|
-
- `i` -
|
|
157
|
+
- `y` - 保持容器在后台运行(默认)
|
|
158
|
+
- `n` - 删除容器
|
|
159
|
+
- `1` - 使用首次命令重新进入
|
|
160
|
+
- `x` - 执行新命令
|
|
161
|
+
- `i` - 进入交互式 shell
|
|
144
162
|
|
|
145
|
-
###
|
|
163
|
+
### 容器模式
|
|
146
164
|
|
|
147
|
-
#### Docker-in-Docker
|
|
165
|
+
#### Docker-in-Docker 开发
|
|
148
166
|
|
|
149
167
|
```bash
|
|
150
|
-
# Docker-in-Docker
|
|
151
|
-
#
|
|
168
|
+
# Docker-in-Docker(安全的嵌套容器)
|
|
169
|
+
# 创建支持 Docker-in-Docker 的容器
|
|
152
170
|
manyoyo -n docker-dev -m dind -x /bin/bash
|
|
153
171
|
|
|
154
|
-
#
|
|
172
|
+
# 在容器内启动 dockerd
|
|
155
173
|
nohup dockerd &
|
|
156
174
|
|
|
157
|
-
#
|
|
175
|
+
# 现在可以在容器内使用 docker 命令
|
|
158
176
|
docker run hello-world
|
|
159
177
|
```
|
|
160
178
|
|
|
161
|
-
####
|
|
179
|
+
#### 挂载 Docker Socket 开发
|
|
162
180
|
|
|
163
181
|
```bash
|
|
164
|
-
#
|
|
182
|
+
# 挂载 Docker Socket(危险 - 容器可以访问宿主机)
|
|
165
183
|
manyoyo -n socket-dev -m mdsock -x docker ps
|
|
166
184
|
```
|
|
167
185
|
|
|
168
|
-
###
|
|
169
|
-
|
|
170
|
-
|
|
|
171
|
-
|
|
172
|
-
| `-l` | `--ls`, `--list` |
|
|
173
|
-
| `--hp PATH` | `--host-path` |
|
|
174
|
-
| `-n NAME` | `--cn`, `--cont-name` |
|
|
175
|
-
| `--cp PATH` | `--cont-path` |
|
|
176
|
-
| `--in NAME` | `--image-name` |
|
|
177
|
-
| `--iv VERSION` | `--image-ver` |
|
|
178
|
-
| `-e STRING` | `--env` |
|
|
179
|
-
| `--ef FILE` | `--env-file` |
|
|
180
|
-
| `-v STRING` | `--volume` |
|
|
181
|
-
| `--rm` | `--rmc`, `--remove-cont` |
|
|
182
|
-
| `--sp CMD` | `--shell-prefix` |
|
|
183
|
-
| `-s CMD` | `--shell` |
|
|
184
|
-
| `--` | `--ss`, `--shell-suffix` |
|
|
185
|
-
| `-x CMD` | `--sf`, `--shell-full` |
|
|
186
|
-
| `-y CLI` | `--yolo` |
|
|
187
|
-
| `-m MODE` | `--cm`, `--cont-mode` |
|
|
188
|
-
| `--
|
|
189
|
-
|
|
|
190
|
-
| `-
|
|
186
|
+
### 命令行选项
|
|
187
|
+
|
|
188
|
+
| 选项 | 别名 | 描述 |
|
|
189
|
+
|------|------|------|
|
|
190
|
+
| `-l` | `--ls`, `--list` | 列出所有 manyoyo 容器 |
|
|
191
|
+
| `--hp PATH` | `--host-path` | 设置宿主机工作目录(默认:当前路径) |
|
|
192
|
+
| `-n NAME` | `--cn`, `--cont-name` | 设置容器名称 |
|
|
193
|
+
| `--cp PATH` | `--cont-path` | 设置容器工作目录 |
|
|
194
|
+
| `--in NAME` | `--image-name` | 指定镜像名称 |
|
|
195
|
+
| `--iv VERSION` | `--image-ver` | 指定镜像版本 |
|
|
196
|
+
| `-e STRING` | `--env` | 设置环境变量 |
|
|
197
|
+
| `--ef FILE` | `--env-file` | 从文件加载环境变量 |
|
|
198
|
+
| `-v STRING` | `--volume` | 绑定挂载卷 |
|
|
199
|
+
| `--rm` | `--rmc`, `--remove-cont` | 删除容器 |
|
|
200
|
+
| `--sp CMD` | `--shell-prefix` | 临时环境变量(作为 -s 的前缀) |
|
|
201
|
+
| `-s CMD` | `--shell` | 指定要执行的命令 |
|
|
202
|
+
| `--` | `--ss`, `--shell-suffix` | 命令参数(作为 -s 的后缀) |
|
|
203
|
+
| `-x CMD` | `--sf`, `--shell-full` | 完整命令(替代 --sp, -s 和 --) |
|
|
204
|
+
| `-y CLI` | `--yolo` | 无需确认运行 AI 智能体 |
|
|
205
|
+
| `-m MODE` | `--cm`, `--cont-mode` | 设置容器模式(common, dind, mdsock) |
|
|
206
|
+
| `--ib EXT` | `--image-build` | 构建镜像,EXT 为镜像变体(all, go, common) |
|
|
207
|
+
| `--install NAME` | | 安装 manyoyo 命令 |
|
|
208
|
+
| `-V` | `--version` | 显示版本 |
|
|
209
|
+
| `-h` | `--help` | 显示帮助 |
|
|
191
210
|
|
|
192
211
|
## 其他说明
|
|
193
212
|
|
|
194
|
-
###
|
|
213
|
+
### 默认配置
|
|
195
214
|
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
215
|
+
- **容器名称**:`myy-{月日-时分}`(基于当前时间自动生成)
|
|
216
|
+
- **宿主机路径**:当前工作目录
|
|
217
|
+
- **容器路径**:与宿主机路径相同
|
|
218
|
+
- **镜像**:`localhost/xcanwin/manyoyo:xxx`
|
|
200
219
|
|
|
201
|
-
###
|
|
220
|
+
### 系统要求
|
|
202
221
|
|
|
203
|
-
- Node.js >=
|
|
204
|
-
- Docker
|
|
222
|
+
- Node.js >= 24.0.0
|
|
223
|
+
- Docker 或 Podman
|
|
205
224
|
|
|
206
|
-
###
|
|
225
|
+
### 卸载
|
|
207
226
|
|
|
208
227
|
```bash
|
|
209
228
|
npm uninstall -g @xcanwin/manyoyo
|
|
210
229
|
```
|
|
211
230
|
|
|
212
|
-
##
|
|
231
|
+
## 许可证
|
|
213
232
|
|
|
214
233
|
MIT
|
package/bin/manyoyo.js
CHANGED
|
@@ -8,7 +8,7 @@ const { execSync, spawnSync } = require('child_process');
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const readline = require('readline');
|
|
11
|
-
const { version: BIN_VERSION } = require('../package.json');
|
|
11
|
+
const { version: BIN_VERSION, imageVersion: IMAGE_VERSION_BASE } = require('../package.json');
|
|
12
12
|
|
|
13
13
|
// Helper function to format date like bash $(date +%m%d-%H%M)
|
|
14
14
|
function formatDate() {
|
|
@@ -25,12 +25,14 @@ let CONTAINER_NAME = `myy-${formatDate()}`;
|
|
|
25
25
|
let HOST_PATH = process.cwd();
|
|
26
26
|
let CONTAINER_PATH = HOST_PATH;
|
|
27
27
|
let IMAGE_NAME = "localhost/xcanwin/manyoyo";
|
|
28
|
-
let IMAGE_VERSION =
|
|
28
|
+
let IMAGE_VERSION = `${IMAGE_VERSION_BASE}-all`;
|
|
29
29
|
let EXEC_COMMAND = "";
|
|
30
30
|
let EXEC_COMMAND_PREFIX = "";
|
|
31
31
|
let EXEC_COMMAND_SUFFIX = "";
|
|
32
32
|
let ENV_FILE = "";
|
|
33
33
|
let SHOULD_REMOVE = false;
|
|
34
|
+
let SHOULD_BUILD_IMAGE = false;
|
|
35
|
+
let BUILD_IMAGE_EXT = "";
|
|
34
36
|
let CONTAINER_ENVS = [];
|
|
35
37
|
let CONTAINER_VOLUMES = [];
|
|
36
38
|
let MANYOYO_NAME = "manyoyo";
|
|
@@ -83,12 +85,15 @@ function showHelp() {
|
|
|
83
85
|
console.log(" 例如 claude / c, gemini / gm, codex / cx, opencode / oc");
|
|
84
86
|
console.log(" -m|--cm|--cont-mode STRING 设置容器嵌套容器模式");
|
|
85
87
|
console.log(" 例如 common, dind, mdsock");
|
|
88
|
+
console.log(" --ib|--image-build EXT 构建镜像,EXT 为镜像变体,逗号分割");
|
|
89
|
+
console.log(" 例如 \"common\" (默认值), \"all\", \"go,codex,java,gemini\" ...");
|
|
86
90
|
console.log(" --install NAME 安装manyoyo命令");
|
|
87
91
|
console.log(" 例如 docker-cli-plugin");
|
|
88
92
|
console.log(" -V|--version 显示版本");
|
|
89
93
|
console.log(" -h|--help 显示帮助");
|
|
90
94
|
console.log("");
|
|
91
95
|
console.log(`${BLUE}Example:${NC}`);
|
|
96
|
+
console.log(` ${MANYOYO_NAME} --ib all 构建 all 版本镜像`);
|
|
92
97
|
console.log(` ${MANYOYO_NAME} -n test --ef ./xxx.env -y c 设置环境变量并运行无需确认的AGENT`);
|
|
93
98
|
console.log(` ${MANYOYO_NAME} -n test -- -c 恢复之前会话`);
|
|
94
99
|
console.log(` ${MANYOYO_NAME} -x echo 123 指定命令执行`);
|
|
@@ -295,6 +300,46 @@ function getContList() {
|
|
|
295
300
|
}
|
|
296
301
|
}
|
|
297
302
|
|
|
303
|
+
async function buildImage(ext, imageName, imageVersion) {
|
|
304
|
+
// Use package.json imageVersion if not specified
|
|
305
|
+
const version = imageVersion || IMAGE_VERSION_BASE;
|
|
306
|
+
const fullImageTag = `${imageName}:${version}-${ext}`;
|
|
307
|
+
|
|
308
|
+
console.log(`${CYAN}🔨 正在构建镜像: ${YELLOW}${fullImageTag}${NC}`);
|
|
309
|
+
console.log(`${BLUE}构建参数: EXT=${ext}${NC}\n`);
|
|
310
|
+
|
|
311
|
+
// Find Dockerfile path
|
|
312
|
+
const dockerfilePath = path.join(__dirname, '../docker/manyoyo.Dockerfile');
|
|
313
|
+
if (!fs.existsSync(dockerfilePath)) {
|
|
314
|
+
console.error(`${RED}错误: 找不到 Dockerfile: ${dockerfilePath}${NC}`);
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Build command
|
|
319
|
+
const buildCmd = `${DOCKER_CMD} build -t "${fullImageTag}" -f "${dockerfilePath}" "${path.join(__dirname, '..')}" --build-arg EXT=${ext} --no-cache`;
|
|
320
|
+
|
|
321
|
+
console.log(`${BLUE}准备执行命令:${NC}`);
|
|
322
|
+
console.log(`${buildCmd}\n`);
|
|
323
|
+
|
|
324
|
+
const reply = await askQuestion(`❔ 是否继续构建? [ 直接回车=继续, ctrl+c=取消 ]: `);
|
|
325
|
+
console.log("");
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
execSync(buildCmd, { stdio: 'inherit' });
|
|
329
|
+
console.log(`\n${GREEN}✅ 镜像构建成功: ${fullImageTag}${NC}`);
|
|
330
|
+
console.log(`${BLUE}使用镜像:${NC}`);
|
|
331
|
+
console.log(` manyoyo -n test --in ${imageName} --iv ${version}-${ext} -y c`);
|
|
332
|
+
|
|
333
|
+
// Prune dangling images
|
|
334
|
+
console.log(`\n${YELLOW}清理悬空镜像...${NC}`);
|
|
335
|
+
execSync(`${DOCKER_CMD} image prune -f`, { stdio: 'inherit' });
|
|
336
|
+
console.log(`${GREEN}✅ 清理完成${NC}`);
|
|
337
|
+
} catch (e) {
|
|
338
|
+
console.error(`${RED}错误: 镜像构建失败${NC}`);
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
298
343
|
// ==============================================================================
|
|
299
344
|
// Main Function Helpers
|
|
300
345
|
// ==============================================================================
|
|
@@ -439,6 +484,13 @@ function parseArguments(argv) {
|
|
|
439
484
|
i += 2;
|
|
440
485
|
break;
|
|
441
486
|
|
|
487
|
+
case '--ib':
|
|
488
|
+
case '--image-build':
|
|
489
|
+
SHOULD_BUILD_IMAGE = true;
|
|
490
|
+
BUILD_IMAGE_EXT = args[i + 1];
|
|
491
|
+
i += 2;
|
|
492
|
+
break;
|
|
493
|
+
|
|
442
494
|
case '--install':
|
|
443
495
|
installManyoyo(args[i + 1]);
|
|
444
496
|
process.exit(0);
|
|
@@ -589,7 +641,7 @@ async function handlePostExit(defaultCommand) {
|
|
|
589
641
|
console.log("");
|
|
590
642
|
getHelloTip(CONTAINER_NAME, defaultCommand);
|
|
591
643
|
|
|
592
|
-
const reply = await askQuestion(`❔ 会话已结束。是否保留此后台容器 ${CONTAINER_NAME}? [ y=默认保留, n=删除, 1=首次命令进入,
|
|
644
|
+
const reply = await askQuestion(`❔ 会话已结束。是否保留此后台容器 ${CONTAINER_NAME}? [ y=默认保留, n=删除, 1=首次命令进入, x=执行命令, i=交互式SHELL ]: `);
|
|
593
645
|
console.log("");
|
|
594
646
|
|
|
595
647
|
const firstChar = reply.trim().toLowerCase()[0];
|
|
@@ -605,7 +657,7 @@ async function handlePostExit(defaultCommand) {
|
|
|
605
657
|
const newArgs = ['-n', CONTAINER_NAME];
|
|
606
658
|
process.argv = [process.argv[0], process.argv[1], ...newArgs];
|
|
607
659
|
await main();
|
|
608
|
-
} else if (firstChar === '
|
|
660
|
+
} else if (firstChar === 'x') {
|
|
609
661
|
const command = await askQuestion('❔ 输入要执行的命令: ');
|
|
610
662
|
console.log(`${GREEN}✅ 离开当前连接,执行命令。${NC}`);
|
|
611
663
|
const newArgs = ['-n', CONTAINER_NAME, '-x', command];
|
|
@@ -633,19 +685,25 @@ async function main() {
|
|
|
633
685
|
// 2. Parse command-line arguments
|
|
634
686
|
parseArguments(process.argv);
|
|
635
687
|
|
|
636
|
-
// 3. Handle
|
|
688
|
+
// 3. Handle image build operation
|
|
689
|
+
if (SHOULD_BUILD_IMAGE) {
|
|
690
|
+
await buildImage(BUILD_IMAGE_EXT, IMAGE_NAME, IMAGE_VERSION.split('-')[0]);
|
|
691
|
+
process.exit(0);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// 4. Handle remove container operation
|
|
637
695
|
handleRemoveContainer();
|
|
638
696
|
|
|
639
|
-
//
|
|
697
|
+
// 5. Validate host path safety
|
|
640
698
|
validateHostPath();
|
|
641
699
|
|
|
642
|
-
//
|
|
700
|
+
// 6. Setup container (create or connect)
|
|
643
701
|
const defaultCommand = await setupContainer();
|
|
644
702
|
|
|
645
|
-
//
|
|
703
|
+
// 7. Execute command in container
|
|
646
704
|
executeInContainer(defaultCommand);
|
|
647
705
|
|
|
648
|
-
//
|
|
706
|
+
// 8. Handle post-exit interactions
|
|
649
707
|
await handlePostExit(defaultCommand);
|
|
650
708
|
|
|
651
709
|
} catch (e) {
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
[ [English](README_EN.md) ] | [中文](../README.md)
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# MANYOYO (Man-Yo-Yo)
|
|
6
|
+
|
|
7
|
+
**MANYOYO** is an AI agent security sandbox that is safe, efficient, and token-saving. Designed specifically for Agent YOLO mode to protect the host machine.
|
|
8
|
+
|
|
9
|
+
Pre-installed with common agents and tools to further save tokens. Freely switch between agents and `/bin/bash` in a loop for enhanced efficiency.
|
|
10
|
+
|
|
11
|
+
**MANYOYO** provides an isolated Docker/Podman container environment for running AI agent CLIs safely.
|
|
12
|
+
|
|
13
|
+
## Key Features
|
|
14
|
+
|
|
15
|
+
- **Multi-Agent Support**: Supports claude code, gemini, codex, opencode
|
|
16
|
+
- **Security Isolation**: Protects host machine, supports safe nested containers (Docker-in-Docker)
|
|
17
|
+
- **Quick Launch**: Quickly enable common Agent YOLO / SOLO mode (e.g., claude --dangerously-skip-permissions)
|
|
18
|
+
- **Convenient Operations**: Quick access to `/bin/bash`
|
|
19
|
+
- **Session Recovery**: Install Skills Marketplace to quickly resume sessions
|
|
20
|
+
- **Flexible Customization**: Support custom `BASEURL`, `AUTH_TOKEN`, and other variables
|
|
21
|
+
- **Configuration Management**: Quick import of configuration files
|
|
22
|
+
- **Advanced Mode**: Supports dangerous nested containers (mount-docker-socket), custom sandbox images
|
|
23
|
+
|
|
24
|
+
# Usage
|
|
25
|
+
|
|
26
|
+
## 1. Install manyoyo
|
|
27
|
+
|
|
28
|
+
### Global Installation (Recommended)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g @xcanwin/manyoyo
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Local Development
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 2. Install podman
|
|
41
|
+
|
|
42
|
+
- Install [podman](https://podman.io/docs/installation)
|
|
43
|
+
|
|
44
|
+
## 3. Build Image
|
|
45
|
+
|
|
46
|
+
After installing manyoyo, use the built-in command to build images:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Pull base image
|
|
50
|
+
podman pull ubuntu:24.04
|
|
51
|
+
|
|
52
|
+
# Build using manyoyo (Recommended)
|
|
53
|
+
manyoyo --ib all # Build all version (includes all tools)
|
|
54
|
+
manyoyo --ib common # Build common version (basic version)
|
|
55
|
+
manyoyo --ib go,codex,java,gemini # Build go version (includes go,codex,java,gemini tools)
|
|
56
|
+
|
|
57
|
+
# Custom image name and version
|
|
58
|
+
manyoyo --ib all --in myimage --iv 2.0.0
|
|
59
|
+
# Builds: myimage:2.0.0-all
|
|
60
|
+
|
|
61
|
+
# Or build manually (Not recommended)
|
|
62
|
+
iv=1.4.0 && podman build -t localhost/xcanwin/manyoyo:$iv-all -f docker/manyoyo.Dockerfile . --build-arg EXT=all --no-cache
|
|
63
|
+
podman image prune -f
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 4. Usage
|
|
67
|
+
|
|
68
|
+
### Basic Commands
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Show help
|
|
72
|
+
manyoyo -h
|
|
73
|
+
|
|
74
|
+
# Show version
|
|
75
|
+
manyoyo -V
|
|
76
|
+
|
|
77
|
+
# List all containers
|
|
78
|
+
manyoyo -l
|
|
79
|
+
|
|
80
|
+
# Create new container with environment file
|
|
81
|
+
manyoyo -n test --ef .env -y c
|
|
82
|
+
|
|
83
|
+
# Resume existing session
|
|
84
|
+
manyoyo -n test -- -c
|
|
85
|
+
|
|
86
|
+
# Execute command in interactive shell
|
|
87
|
+
manyoyo -n test -x /bin/bash
|
|
88
|
+
|
|
89
|
+
# Execute custom command
|
|
90
|
+
manyoyo -n test -x echo "hello world"
|
|
91
|
+
|
|
92
|
+
# Remove container
|
|
93
|
+
manyoyo -n test --rm
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Environment Variables
|
|
97
|
+
|
|
98
|
+
#### String Format
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Direct
|
|
102
|
+
manyoyo -e "VAR=value" -x env
|
|
103
|
+
|
|
104
|
+
# Multiple
|
|
105
|
+
manyoyo -e "A=1" -e "B=2" -x env
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### File Format
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# From file
|
|
112
|
+
manyoyo --ef .env -x env
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Environment files (`.env`) support the following formats:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# With export statement
|
|
119
|
+
export ANTHROPIC_BASE_URL="https://api.anthropic.com"
|
|
120
|
+
# export CLAUDE_CODE_OAUTH_TOKEN="sk-xxxxxxxx"
|
|
121
|
+
export ANTHROPIC_AUTH_TOKEN="sk-xxxxxxxx"
|
|
122
|
+
export API_TIMEOUT_MS=3000000
|
|
123
|
+
export ANTHROPIC_MODEL="claude-sonnet-4-5"
|
|
124
|
+
export ANTHROPIC_DEFAULT_OPUS_MODEL="claude-opus-4-5"
|
|
125
|
+
export ANTHROPIC_DEFAULT_SONNET_MODEL="claude-sonnet-4-5"
|
|
126
|
+
export ANTHROPIC_DEFAULT_HAIKU_MODEL="claude-haiku-4-5"
|
|
127
|
+
export CLAUDE_CODE_SUBAGENT_MODEL="claude-sonnet-4-5"
|
|
128
|
+
|
|
129
|
+
# Simple key=value
|
|
130
|
+
API_KEY=your-api-key-here
|
|
131
|
+
|
|
132
|
+
# Quoted values (quotes will be stripped)
|
|
133
|
+
MESSAGE="Hello World"
|
|
134
|
+
PATH='/usr/local/bin'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### AI CLI Shortcuts (skip permissions)
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Claude Code
|
|
141
|
+
manyoyo -y c # or: claude, cc
|
|
142
|
+
|
|
143
|
+
# Gemini
|
|
144
|
+
manyoyo -y gm # or: gemini, g
|
|
145
|
+
|
|
146
|
+
# Codex
|
|
147
|
+
manyoyo -y cx # or: codex
|
|
148
|
+
|
|
149
|
+
# OpenCode
|
|
150
|
+
manyoyo -y oc # or: opencode
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Interactive Session Management
|
|
154
|
+
|
|
155
|
+
After exiting a container session, you'll be prompted with options:
|
|
156
|
+
|
|
157
|
+
- `y` - Keep container running in background (default)
|
|
158
|
+
- `n` - Delete the container
|
|
159
|
+
- `1` - Re-enter with the original command
|
|
160
|
+
- `x` - Execute a new command
|
|
161
|
+
- `i` - Enter interactive shell
|
|
162
|
+
|
|
163
|
+
### Container Modes
|
|
164
|
+
|
|
165
|
+
#### Docker-in-Docker Development
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Docker-in-Docker (safe nested containers)
|
|
169
|
+
# Create a container with Docker-in-Docker support
|
|
170
|
+
manyoyo -n docker-dev -m dind -x /bin/bash
|
|
171
|
+
|
|
172
|
+
# Inside the container, start dockerd
|
|
173
|
+
nohup dockerd &
|
|
174
|
+
|
|
175
|
+
# Now you can use docker commands inside the container
|
|
176
|
+
docker run hello-world
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Mount Docker socket Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Mount Docker socket (dangerous - container can access host)
|
|
183
|
+
manyoyo -n socket-dev -m mdsock -x docker ps
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Command-Line Options
|
|
187
|
+
|
|
188
|
+
| Option | Aliases | Description |
|
|
189
|
+
|--------|---------|-------------|
|
|
190
|
+
| `-l` | `--ls`, `--list` | List all manyoyo containers |
|
|
191
|
+
| `--hp PATH` | `--host-path` | Set host working directory (default: current path) |
|
|
192
|
+
| `-n NAME` | `--cn`, `--cont-name` | Set container name |
|
|
193
|
+
| `--cp PATH` | `--cont-path` | Set container working directory |
|
|
194
|
+
| `--in NAME` | `--image-name` | Specify image name |
|
|
195
|
+
| `--iv VERSION` | `--image-ver` | Specify image version |
|
|
196
|
+
| `-e STRING` | `--env` | Set environment variable |
|
|
197
|
+
| `--ef FILE` | `--env-file` | Load environment variables from file |
|
|
198
|
+
| `-v STRING` | `--volume` | Bind mount volume |
|
|
199
|
+
| `--rm` | `--rmc`, `--remove-cont` | Remove container |
|
|
200
|
+
| `--sp CMD` | `--shell-prefix` | Temporary environment variable (prefix for -s) |
|
|
201
|
+
| `-s CMD` | `--shell` | Specify command to execute |
|
|
202
|
+
| `--` | `--ss`, `--shell-suffix` | Command arguments (suffix for -s) |
|
|
203
|
+
| `-x CMD` | `--sf`, `--shell-full` | Full command (replaces --sp, -s, and --) |
|
|
204
|
+
| `-y CLI` | `--yolo` | Run AI agent without confirmation |
|
|
205
|
+
| `-m MODE` | `--cm`, `--cont-mode` | Set container mode (common, dind, mdsock) |
|
|
206
|
+
| `--ib EXT` | `--image-build` | Build image, EXT is image variant (all, go, common) |
|
|
207
|
+
| `--install NAME` | | Install manyoyo command |
|
|
208
|
+
| `-V` | `--version` | Show version |
|
|
209
|
+
| `-h` | `--help` | Show help |
|
|
210
|
+
|
|
211
|
+
## Additional Information
|
|
212
|
+
|
|
213
|
+
### Default Configuration
|
|
214
|
+
|
|
215
|
+
- **Container Name**: `myy-{MMDD-HHMM}` (auto-generated based on current time)
|
|
216
|
+
- **Host Path**: Current working directory
|
|
217
|
+
- **Container Path**: Same as host path
|
|
218
|
+
- **Image**: `localhost/xcanwin/manyoyo:xxx`
|
|
219
|
+
|
|
220
|
+
### Requirements
|
|
221
|
+
|
|
222
|
+
- Node.js >= 24.0.0
|
|
223
|
+
- Docker or Podman
|
|
224
|
+
|
|
225
|
+
### Uninstall
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
npm uninstall -g @xcanwin/manyoyo
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcanwin/manyoyo",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"imageVersion": "1.5.0",
|
|
4
5
|
"description": "AI Agent CLI Security Sandbox",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"ai", "agent", "sandbox", "docker", "cli", "container", "development"
|
|
@@ -26,8 +27,9 @@
|
|
|
26
27
|
"node": ">=14.0.0"
|
|
27
28
|
},
|
|
28
29
|
"files": [
|
|
29
|
-
"manyoyo.js",
|
|
30
|
+
"bin/manyoyo.js",
|
|
30
31
|
"README.md",
|
|
32
|
+
"docs/README_EN.md",
|
|
31
33
|
"LICENSE",
|
|
32
34
|
"docker/manyoyo.Dockerfile"
|
|
33
35
|
]
|