Download entrypoint.sh from huanbao/code: direct link, hf CLI and curl.
- Browser
- Download file 5.2 kB
-
https://huggingface.co/spaces/huanbao/code/resolve/main/entrypoint.sh
- Command line
-
hf download hf://spaces/huanbao/code/entrypoint.sh
-
curl -L -o entrypoint.sh https://huggingface.co/spaces/huanbao/code/resolve/main/entrypoint.sh
5.2 kB
| set -e | |
| # 1. 创建持久化挂载目录 | |
| mkdir -p /data/.claude /data/.cloudcli /data/app /data/.taskmaster /data/.codex_data/sessions /data/.codex_data/state | |
| # 2. 软链接常规目录 | |
| if [ ! -L "$HOME/.claude" ]; then | |
| rm -rf "$HOME/.claude" | |
| ln -s /data/.claude "$HOME/.claude" | |
| fi | |
| if [ ! -L "$HOME/.claude.json" ]; then | |
| rm -f "$HOME/.claude.json" | |
| ln -s /data/.claude.json "$HOME/.claude.json" | |
| fi | |
| if [ ! -L "$HOME/.cloudcli" ]; then | |
| rm -rf "$HOME/.cloudcli" | |
| ln -s /data/.cloudcli "$HOME/.cloudcli" | |
| fi | |
| if [ ! -L "$HOME/.taskmaster" ]; then | |
| rm -rf "$HOME/.taskmaster" | |
| ln -s /data/.taskmaster "$HOME/.taskmaster" | |
| fi | |
| if [ ! -L "$HOME/app" ]; then | |
| ln -s /data/app "$HOME/app" | |
| fi | |
| # ==================== 针对 .codex 的安全持久化 ==================== | |
| # 清理可能存在的旧软链接 | |
| [ -L "$HOME/.codex" ] && rm -f "$HOME/.codex" | |
| mkdir -p "$HOME/.codex" | |
| # 1. 软链接 sessions(文本 jsonl 在网络卷完全安全) | |
| [ -d "$HOME/.codex/sessions" ] && [ ! -L "$HOME/.codex/sessions" ] && rm -rf "$HOME/.codex/sessions" | |
| ln -sf /data/.codex_data/sessions "$HOME/.codex/sessions" | |
| # 2. 恢复 SQLite 元数据与索引(从网络卷复制到容器本地磁盘,避免网络锁损坏) | |
| if [ -d "/data/.codex_data/state" ]; then | |
| cp -u /data/.codex_data/state/*.sqlite* "$HOME/.codex/" 2>/dev/null || true | |
| cp -u /data/.codex_data/state/*.jsonl "$HOME/.codex/" 2>/dev/null || true | |
| fi | |
| # 3. 后台定时同步线程:定期将本地生成的 SQLite 和 session_index 备份回 /data | |
| ( | |
| while true; do | |
| sleep 60 | |
| if [ -d "$HOME/.codex" ]; then | |
| mkdir -p /data/.codex_data/state | |
| # 同步 sqlite 与 index 文件 | |
| cp -u "$HOME"/.codex/*.sqlite* /data/.codex_data/state/ 2>/dev/null || true | |
| cp -u "$HOME"/.codex/*.jsonl /data/.codex_data/state/ 2>/dev/null || true | |
| fi | |
| done | |
| ) & | |
| # =================================================================== | |
| # 3. 自动生成 Claude Code 配置 | |
| mkdir -p "$HOME/.claude" | |
| cat <<EOF > "$HOME/.claude/settings.json" | |
| { | |
| "cleanupPeriodDays": 720, | |
| "env": { | |
| "API_TIMEOUT_MS": "1800000", | |
| "BASH_DEFAULT_TIMEOUT_MS": "1800000", | |
| "BASH_MAX_TIMEOUT_MS": "7200000", | |
| "ANTHROPIC_BASE_URL": "${ANTHROPIC_BASE_URL:-}", | |
| "ANTHROPIC_AUTH_TOKEN": "${ANTHROPIC_AUTH_TOKEN:-}", | |
| "CLAUDE_CODE_ATTRIBUTION_HEADER": "0", | |
| "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1", | |
| "DISABLE_INSTALLATION_CHECKS": "1", | |
| "CLAUDE_CODE_PROXY_RESOLVES_HOSTS": "1", | |
| "CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1", | |
| "ENABLE_TOOL_SEARCH": "true", | |
| "DISABLE_AUTOUPDATER": "1", | |
| "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-sonnet-x[1m]", | |
| "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-sonnet-x[1m]", | |
| "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-x[1m]", | |
| "ANTHROPIC_MODEL": "claude-sonnet-x[1m]", | |
| "ANTHROPIC_REASONING_MODEL": "claude-sonnet-x[1m]" | |
| }, | |
| "permissions": { | |
| "allow": [ | |
| "Read", | |
| "Write", | |
| "Edit", | |
| "Bash(*)", | |
| "Glob", | |
| "Grep", | |
| "Agent", | |
| "WebFetch", | |
| "WebSearch", | |
| "NotebookEdit", | |
| "mcp__serper__google_search", | |
| "mcp__tavily__tavily_search", | |
| "mcp__tavily__tavily_research" | |
| ], | |
| "deny": [ | |
| "Read(.*env*)", | |
| "Read(~/.ssh/*)", | |
| "Bash(rm -rf / *)" | |
| ] | |
| }, | |
| "skipWebFetchPreflight": true, | |
| "effortLevel": "high", | |
| "autoUpdatesChannel": "latest" | |
| } | |
| EOF | |
| # 4. 自动生成 Codex 配置 | |
| CODEX_KEY_RESOLVED="${CODEX_API_KEY:-}" | |
| if [ -z "$CODEX_KEY_RESOLVED" ] && [ -f /data/.codex/gw_token ]; then | |
| CODEX_KEY_RESOLVED="$(head -n 1 /data/.codex/gw_token | tr -d '[:space:]')" | |
| fi | |
| if [ -n "$CODEX_KEY_RESOLVED" ]; then | |
| export OPENAI_API_KEY="$CODEX_KEY_RESOLVED" | |
| fi | |
| cat <<EOF > "$HOME/.codex/config.toml" | |
| cli_auth_credentials_store = "file" | |
| model_provider = "${CODEX_PROVIDER:-custom}" | |
| model = "${CODEX_MODEL:-gpt-5.6-luna}" | |
| sandbox_mode = "danger-full-access" | |
| approval_policy = "never" | |
| [model_providers.custom] | |
| name = "Custom" | |
| base_url = "${CODEX_BASE_URL:-https://cpa.freecode.eu.cc/v1}" | |
| wire_api = "responses" | |
| env_key = "OPENAI_API_KEY" | |
| EOF | |
| cat <<EOF > "$HOME/.codex/auth.json" | |
| { | |
| "OPENAI_API_KEY": "${CODEX_KEY_RESOLVED:-sk-dummy-key}" | |
| } | |
| EOF | |
| # 5. 创建 codex wrapper 兜底(task-master-ai 内置 codex 不在 PATH 中; | |
| # 集成端无环境变量启动时,wrapper 自动从 gw_token 注入凭证) | |
| if [ -w /usr/local/bin ] && [ ! -e /usr/local/bin/codex ] && [ -x /usr/local/lib/node_modules/task-master-ai/node_modules/.bin/codex ]; then | |
| cat <<'WEOF' > /usr/local/bin/codex | |
| #!/bin/bash | |
| if [ -z "$OPENAI_API_KEY" ] && [ -f /data/.codex/gw_token ]; then | |
| export OPENAI_API_KEY="$(head -n 1 /data/.codex/gw_token)" | |
| fi | |
| exec /usr/local/lib/node_modules/task-master-ai/node_modules/.bin/codex "$@" | |
| WEOF | |
| chmod +x /usr/local/bin/codex 2>/dev/null || true | |
| fi | |
| # 6. 全局读写赋权(随后收紧 gw_token 权限,维持 600 保密要求) | |
| chown -R 1000:1000 /data "$HOME" 2>/dev/null || true | |
| chmod -R 777 /data "$HOME" 2>/dev/null || true | |
| [ -f /data/.codex/gw_token ] && chmod 600 /data/.codex/gw_token 2>/dev/null || true | |
| # 7. 切换并启动 | |
| mkdir -p /home/node/app 2>/dev/null || true | |
| cd /home/node/app || cd / | |
| exec "$@" | |