智能助手网
标签聚合 直接

/tag/直接

linux.do · 2026-04-18 18:23:18+08:00 · tech

低价GPT 账号的问题估计周末就要解决了,已经被人反馈给了openai的官方了,直接糊他们脸上,不解决都不行 啊! OpenAI Developer Community – 17 Apr 26 [Security Report] Apple Pay receipt validation does not bind to purchaser... ChatGPT Bugs chatgpt api ⚠ Disclaimer: This report is for technical research and responsible disclosure purposes only. I do not endorse or encourage any unauthorized use, account sharing, or commercial exploitation of this finding. All testing was conducted on accounts I... Reading time: 1 min 🕑 Likes: 8 ❤ 现在就不要再买哪些pro号了,估计随时可能挂!有的加紧蹬,随时可能挂掉啊! 10 个帖子 - 10 位参与者 阅读完整话题

linux.do · 2026-04-18 16:36:56+08:00 · tech

前情提要: 最近在做一个应用,现在比较急着补一套相对正规的注册登录功能。(主要是怕AI手搓,又是重复造轮子又是四处漏风) 我之前其实没有完整做过认证这块,像注册、登录、验证码、找回密码、第三方登录这些,都是纯用过见过听过,没有真正写过,最多STMP邮箱认证,但是那个太糙了还有bug 在问实现方案的时候,Claude 给我推荐了一个 Casdoor , github.com GitHub - casdoor/casdoor: An open-source Agent-first Identity and Access... An open-source Agent-first Identity and Access Management (IAM) /LLM MCP & agent gateway and auth server with web UI supporting OpenClaw, MCP, OAuth, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, Face ID, Google Workspace, Azure AD 我看了一下,是一个统一认证中心的项目,能管注册登录,也能扩展邮箱、短信、微信、GitHub 之类的登录方式。 所以我现在在想一个事情: 如果目标是尽快把“正规的注册登录能力”上线,是不是直接上 Casdoor 会比自己用AI手搓更合适? 实际诉求大概是这些: 1、应用需要支持公开注册和登录 2、肯定要带验证能力,比如邮箱验证码 / 短信验证码这类 3、后续肯定会接微信登录,或者别的第三方登录方式 4、这套东西肯定尽量正规一点,而不是简单写个账号密码表就先凑合 我现在问完AI后对这件事的理解是: 如果自己手搓,就得自己处理注册、登录、token、验证码、找回密码、第三方登录接入这些问题,还得再次去造轮子 如果用 Casdoor,可能可以直接把认证体系独立出去,业务系统只关心用户身份和权限,最多多部署维护一个认证中心 但我没有实际做过,所以不太确定这个判断是不是对的。 有没有懂的佬 以下是用GPT整理的问题列表 其实就是: 想尽快把注册登录做正规,同时尽量别让自己以后每加一种登录方式都重做一遍认证逻辑。 或者有没有其他更好搞的项目直接使唤 5 个帖子 - 3 位参与者 阅读完整话题

www.ithome.com · 2026-04-18 15:37:25+08:00 · tech

MOVA(魔法原子)是追觅科技旗下的独立子品牌,主打高性价比,同一集团,共享核心技术、算法、工厂、售后体系。 MOVA P60 于 2025 年 2 月上市,标准版官方定价 3999 元, 上下水版 4599 元 。 升级的 P60 甄选版于 2025 年 10 月上市,相较标准版,主要升级点为: 60℃ 热水洗拖布 → 100℃ 高温灭菌洗 24000Pa 吸力 → 26000Pa 大吸力 基础尘盒设计 → 大容量尘袋(官方宣称 100 天免倒污) 今日下单选择“以旧换新”(可选加湿器), P60 甄选上下水版 实付 1066 元破冰新低。 如果选择的是 生活电器 → 美的 / 石头 / 云鲸 / 科沃斯等品牌扫地机器人 * ,可再减 200 元,实付 866 元。 自行安装返 100 元 E 卡(但大多数城市送装一体),需先联系客服确认 **,折合 766 元: 京东 Mova P60 甄选上下水版 不换新 1133 元 以旧换新 1066 元 直达链接 * 以旧换新不看成色, 老旧坏皆可 ,闲鱼上美的 / 科沃斯坏机器人均在 30 元左右。 ** 自行安装须知: 本次京东自营支持买贵双倍赔,PLUS 会员 180 只换不修, 质保 3 年 。 就算只用 3 年,每天仅需 1066/3/365=0.97 元,不到 1 元真真划算。 咨询客服再赠 520 礼包:割毛滚刷 3.0*1+ 尘袋 * 1+ 拖布 * 1 (2 对)+ 外扩防缠毛边刷 * 1。 上下水版首次安装免费安装,但如需改柜、改线路的话,会按官方价目表收费。 京东 Mova P60 甄选上下水版 不换新 1133 元 以旧换新 1066 元 直达链接

linux.do · 2026-04-18 15:28:08+08:00 · tech

自写的反代目前看来比较稳定 之前直接分享自己用的key被举报了 没心情分享免费opus4.7了 但是如果有佬自己的号希望反代用 可以找我免费托管,代理我来提供 因为代理是按流量计费的 5​ /GB 所以提供不了太多号 建议最多2个人分享一个号,更多人没测过 有可视化面板可以查使用情况 不用担心有你本人以外的人使用你的账号 5 个帖子 - 2 位参与者 阅读完整话题

linux.do · 2026-04-18 13:53:38+08:00 · tech

我发现最新Claude code已无法直接在Android termux用npm安装来直接使用,会有报错,肯定是Termux环境的兼容问题,毕竟不是标准的Linux。如何解决: 1.非proot方案(推荐) #!/data/data/com.termux/files/usr/bin/bash set -euo pipefail readonly SCRIPT_NAME="$(basename "$0")" readonly PREFIX_DIR="${PREFIX:-/data/data/com.termux/files/usr}" readonly STATE_DIR="${CLAUDE_CODE_HOME:-$HOME/.claude-code-termux}" readonly NODE_DIR="$STATE_DIR/node" readonly WRAPPER_BIN_DIR="$STATE_DIR/bin" readonly PATCH_DIR="$STATE_DIR/patches" readonly GLOBAL_PREFIX_DIR="$STATE_DIR/npm-global" readonly GLOBAL_BIN_DIR="$GLOBAL_PREFIX_DIR/bin" readonly NPM_CACHE_DIR="$STATE_DIR/npm-cache" readonly TMP_ROOT_DIR="${TMPDIR:-$PREFIX_DIR/tmp}" readonly GLIBC_LDSO="$PREFIX_DIR/glibc/lib/ld-linux-aarch64.so.1" readonly GLIBC_RUNNER_BIN="$PREFIX_DIR/bin/grun" readonly GLIBC_MARKER="$STATE_DIR/.glibc-arch" readonly HOST_CLAUDE_PATH="$PREFIX_DIR/bin/claude" readonly BACKUP_DIR="$STATE_DIR/backups" readonly CLAUDE_PACKAGE_NAME="@anthropic-ai/claude-code" readonly CLAUDE_PACKAGE_VERSION="${CLAUDE_CODE_VERSION:-latest}" readonly NODE_VERSION="${CLAUDE_CODE_NODE_VERSION:-22.22.0}" readonly NODE_TARBALL="node-v${NODE_VERSION}-linux-arm64.tar.xz" readonly NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/${NODE_TARBALL}" readonly COMPAT_PATCH_PATH="$PATCH_DIR/claude-glibc-compat.js" readonly CLAUDE_EXE_PATH="$GLOBAL_PREFIX_DIR/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe" readonly HOST_WRAPPER_MARKER="# claude-code-termux-nonproot-wrapper" readonly C_BOLD_BLUE="\033[1;34m" readonly C_BOLD_GREEN="\033[1;32m" readonly C_BOLD_YELLOW="\033[1;33m" readonly C_BOLD_RED="\033[1;31m" readonly C_RESET="\033[0m" info() { printf '%b[INFO]%b %s\n' "$C_BOLD_BLUE" "$C_RESET" "$*" } success() { printf '%b[ OK ]%b %s\n' "$C_BOLD_GREEN" "$C_RESET" "$*" } warn() { printf '%b[WARN]%b %s\n' "$C_BOLD_YELLOW" "$C_RESET" "$*" >&2 } die() { printf '%b[ERR ]%b %s\n' "$C_BOLD_RED" "$C_RESET" "$*" >&2 exit 1 } usage() { cat <<EOF Usage: bash $SCRIPT_NAME What it does: 1. Installs Termux dependencies needed for a glibc-based Node runtime. 2. Installs glibc-runner through pacman (no proot distro). 3. Downloads official Node.js ${NODE_VERSION} linux-arm64. 4. Wraps node/npm with ld.so so they run on Termux. 5. Installs ${CLAUDE_PACKAGE_NAME} and exposes it as: $HOST_CLAUDE_PATH Environment overrides: CLAUDE_CODE_HOME install state dir, default: $STATE_DIR CLAUDE_CODE_VERSION npm package version/tag, default: $CLAUDE_PACKAGE_VERSION CLAUDE_CODE_NODE_VERSION Node.js linux-arm64 version, default: $NODE_VERSION Notes: - This follows the non-proot glibc-wrapper approach used by openclaw-android. - Only aarch64 Termux is supported. - Existing $HOST_CLAUDE_PATH will be backed up if it is not already managed. EOF } command_exists() { command -v "$1" >/dev/null 2>&1 } require_termux() { [ -d "$PREFIX_DIR" ] || die "This script must run in Termux." command_exists pkg || die "pkg not found. This script must run in Termux." } ensure_tmp_root() { mkdir -p "$TMP_ROOT_DIR" } ensure_state_dirs() { mkdir -p "$STATE_DIR" "$WRAPPER_BIN_DIR" "$PATCH_DIR" "$GLOBAL_PREFIX_DIR" \ "$GLOBAL_BIN_DIR" "$NPM_CACHE_DIR" "$BACKUP_DIR" } ensure_termux_package() { local package_name="$1" if dpkg -s "$package_name" >/dev/null 2>&1; then success "Termux package already installed: $package_name" return 0 fi info "Installing Termux package: $package_name" pkg install -y "$package_name" success "Installed Termux package: $package_name" } ensure_glibc_runner() { local arch local pacman_conf local siglevel_patched=0 arch="$(uname -m)" [ "$arch" = "aarch64" ] || die "glibc mode only supports aarch64, got: $arch" if [ -f "$GLIBC_MARKER" ] && [ -x "$GLIBC_LDSO" ]; then success "glibc-runner already available" return 0 fi ensure_termux_package "pacman" pacman_conf="$PREFIX_DIR/etc/pacman.conf" info "Initializing pacman for glibc-runner" if [ -f "$pacman_conf" ] && ! grep -q '^SigLevel = Never' "$pacman_conf"; then cp "$pacman_conf" "${pacman_conf}.bak" sed -i 's/^SigLevel\s*=.*/SigLevel = Never/' "$pacman_conf" siglevel_patched=1 warn "Applied temporary pacman SigLevel workaround" fi pacman-key --init 2>/dev/null || true pacman-key --populate 2>/dev/null || true info "Installing glibc-runner" if ! pacman -Sy glibc-runner --noconfirm --assume-installed bash,patchelf,resolv-conf; then if [ "$siglevel_patched" -eq 1 ] && [ -f "${pacman_conf}.bak" ]; then mv "${pacman_conf}.bak" "$pacman_conf" fi die "Failed to install glibc-runner" fi if [ "$siglevel_patched" -eq 1 ] && [ -f "${pacman_conf}.bak" ]; then mv "${pacman_conf}.bak" "$pacman_conf" success "Restored pacman SigLevel" fi [ -x "$GLIBC_LDSO" ] || die "glibc dynamic linker not found at $GLIBC_LDSO" touch "$GLIBC_MARKER" success "glibc-runner is ready" } write_compat_patch() { info "Writing Node compatibility patch" cat >"$COMPAT_PATCH_PATH" <<'EOF' 'use strict'; const childProcess = require('child_process'); const dns = require('dns'); const fs = require('fs'); const os = require('os'); const path = require('path'); const prefix = process.env.PREFIX || '/data/data/com.termux/files/usr'; const home = process.env.HOME || '/data/data/com.termux/files/home'; const wrapperPath = process.env._CLAUDE_WRAPPER_PATH || path.join(home, '.claude-code-termux', 'bin', 'node'); const termuxExec = path.join(prefix, 'lib', 'libtermux-exec-ld-preload.so'); const termuxShell = path.join(prefix, 'bin', 'sh'); try { if (fs.existsSync(wrapperPath)) { Object.defineProperty(process, 'execPath', { value: wrapperPath, writable: true, configurable: true, }); } } catch {} if (process.env._CLAUDE_ORIG_LD_PRELOAD) { process.env.LD_PRELOAD = process.env._CLAUDE_ORIG_LD_PRELOAD; delete process.env._CLAUDE_ORIG_LD_PRELOAD; } else if (!process.env.LD_PRELOAD) { try { if (fs.existsSync(termuxExec)) { process.env.LD_PRELOAD = termuxExec; } } catch {} } const originalCpus = os.cpus; os.cpus = function cpus() { try { const result = originalCpus.call(os); if (Array.isArray(result) && result.length > 0) { return result; } } catch {} return [{ model: 'unknown', speed: 0, times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 }, }]; }; const originalNetworkInterfaces = os.networkInterfaces; os.networkInterfaces = function networkInterfaces() { try { return originalNetworkInterfaces.call(os); } catch { return { lo: [{ address: '127.0.0.1', netmask: '255.0.0.0', family: 'IPv4', mac: '00:00:00:00:00:00', internal: true, cidr: '127.0.0.1/8', }], }; } }; if (!fs.existsSync('/bin/sh') && fs.existsSync(termuxShell)) { const originalExec = childProcess.exec; const originalExecSync = childProcess.execSync; childProcess.exec = function exec(command, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } options = options || {}; if (!options.shell) { options.shell = termuxShell; } return originalExec.call(childProcess, command, options, callback); }; childProcess.execSync = function execSync(command, options) { options = options || {}; if (!options.shell) { options.shell = termuxShell; } return originalExecSync.call(childProcess, command, options); }; } try { let dnsServers = ['8.8.8.8', '8.8.4.4']; try { const resolvConf = fs.readFileSync(path.join(prefix, 'etc', 'resolv.conf'), 'utf8'); const matches = resolvConf.match(/^nameserver\s+(.+)$/gm); if (matches && matches.length > 0) { dnsServers = matches.map((line) => line.replace(/^nameserver\s+/, '').trim()); } } catch {} try { dns.setServers(dnsServers); } catch {} const originalLookup = dns.lookup; const originalLookupPromise = dns.promises.lookup; dns.lookup = function lookup(hostname, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } const originalOptions = options; const opts = typeof options === 'number' ? { family: options } : (options || {}); const wantAll = opts.all === true; const family = opts.family || 0; const resolveWith = (fam, done) => { const resolver = fam === 6 ? dns.resolve6 : dns.resolve4; resolver(hostname, done); }; const tryResolve = (fam) => { resolveWith(fam, (error, addresses) => { if (!error && Array.isArray(addresses) && addresses.length > 0) { const resolvedFamily = fam === 6 ? 6 : 4; if (wantAll) { callback(null, addresses.map((address) => ({ address, family: resolvedFamily, }))); return; } callback(null, addresses[0], resolvedFamily); return; } if (family === 0 && fam === 4) { tryResolve(6); return; } originalLookup.call(dns, hostname, originalOptions, callback); }); }; tryResolve(family === 6 ? 6 : 4); }; dns.promises.lookup = async function lookup(hostname, options) { const opts = typeof options === 'number' ? { family: options } : (options || {}); const wantAll = opts.all === true; const family = opts.family || 0; const resolveWith = family === 6 ? dns.promises.resolve6 : dns.promises.resolve4; try { const addresses = await resolveWith(hostname); if (addresses.length > 0) { const resolvedFamily = family === 6 ? 6 : 4; if (wantAll) { return addresses.map((address) => ({ address, family: resolvedFamily, })); } return { address: addresses[0], family: resolvedFamily, }; } } catch {} if (family === 0) { try { const addresses = await dns.promises.resolve6(hostname); if (addresses.length > 0) { if (wantAll) { return addresses.map((address) => ({ address, family: 6 })); } return { address: addresses[0], family: 6, }; } } catch {} } return originalLookupPromise.call(dns.promises, hostname, options); }; } catch {} EOF success "Compatibility patch written to $COMPAT_PATCH_PATH" } write_node_wrappers() { local node_bin_path local node_real_path node_bin_path="$NODE_DIR/bin/node" node_real_path="$NODE_DIR/bin/node.real" if [ -f "$node_real_path" ]; then : elif [ -f "$node_bin_path" ]; then mv "$node_bin_path" "$node_real_path" else die "Node binary missing at $node_bin_path" fi info "Writing node/npm wrappers" cat >"$WRAPPER_BIN_DIR/node" <<EOF #!$PREFIX_DIR/bin/bash [ -n "\${LD_PRELOAD:-}" ] && export _CLAUDE_ORIG_LD_PRELOAD="\$LD_PRELOAD" unset LD_PRELOAD export _CLAUDE_WRAPPER_PATH="$WRAPPER_BIN_DIR/node" export TMPDIR="\${TMPDIR:-$TMP_ROOT_DIR}" _CLAUDE_COMPAT="$COMPAT_PATCH_PATH" if [ -f "\$_CLAUDE_COMPAT" ]; then case "\${NODE_OPTIONS:-}" in *"\$_CLAUDE_COMPAT"*) ;; *) export NODE_OPTIONS="\${NODE_OPTIONS:+\$NODE_OPTIONS }-r \$_CLAUDE_COMPAT" ;; esac fi exec "$GLIBC_LDSO" --library-path "$PREFIX_DIR/glibc/lib" "$NODE_DIR/bin/node.real" "\$@" EOF cat >"$WRAPPER_BIN_DIR/npm" <<EOF #!$PREFIX_DIR/bin/bash export PATH="$WRAPPER_BIN_DIR:$NODE_DIR/bin:\$PATH" export TMPDIR="\${TMPDIR:-$TMP_ROOT_DIR}" export NPM_CONFIG_PREFIX="$GLOBAL_PREFIX_DIR" export npm_config_prefix="$GLOBAL_PREFIX_DIR" export NPM_CONFIG_CACHE="$NPM_CACHE_DIR" export npm_config_cache="$NPM_CACHE_DIR" export NPM_CONFIG_SCRIPT_SHELL="$PREFIX_DIR/bin/sh" export npm_config_script_shell="$PREFIX_DIR/bin/sh" exec "$WRAPPER_BIN_DIR/node" "$NODE_DIR/lib/node_modules/npm/bin/npm-cli.js" "\$@" EOF cat >"$WRAPPER_BIN_DIR/npx" <<EOF #!$PREFIX_DIR/bin/bash export PATH="$WRAPPER_BIN_DIR:$NODE_DIR/bin:\$PATH" export TMPDIR="\${TMPDIR:-$TMP_ROOT_DIR}" export NPM_CONFIG_PREFIX="$GLOBAL_PREFIX_DIR" export npm_config_prefix="$GLOBAL_PREFIX_DIR" export NPM_CONFIG_CACHE="$NPM_CACHE_DIR" export npm_config_cache="$NPM_CACHE_DIR" export NPM_CONFIG_SCRIPT_SHELL="$PREFIX_DIR/bin/sh" export npm_config_script_shell="$PREFIX_DIR/bin/sh" exec "$WRAPPER_BIN_DIR/node" "$NODE_DIR/lib/node_modules/npm/bin/npx-cli.js" "\$@" EOF chmod 755 "$WRAPPER_BIN_DIR/node" "$WRAPPER_BIN_DIR/npm" "$WRAPPER_BIN_DIR/npx" success "node/npm wrappers are ready" } install_node_runtime() { local installed_version local tmp_dir local extract_dir local fresh_dir ensure_termux_package "curl" ensure_termux_package "xz-utils" if [ -x "$WRAPPER_BIN_DIR/node" ]; then installed_version="$("$WRAPPER_BIN_DIR/node" --version 2>/dev/null | sed 's/^v//')" if [ "$installed_version" = "$NODE_VERSION" ]; then success "Node.js already installed: v$installed_version" write_compat_patch write_node_wrappers return 0 fi fi info "Downloading official Node.js ${NODE_VERSION} linux-arm64" tmp_dir="$(mktemp -d "$TMP_ROOT_DIR/claude-node.XXXXXX")" curl -fL --max-time 300 "$NODE_URL" -o "$tmp_dir/$NODE_TARBALL" success "Downloaded $NODE_TARBALL" extract_dir="$tmp_dir/extract" fresh_dir="$tmp_dir/node-fresh" mkdir -p "$extract_dir" "$fresh_dir" tar -xJf "$tmp_dir/$NODE_TARBALL" -C "$extract_dir" mv "$extract_dir"/node-v"${NODE_VERSION}"-linux-arm64/* "$fresh_dir"/ rm -rf "$NODE_DIR" mkdir -p "$(dirname "$NODE_DIR")" mv "$fresh_dir" "$NODE_DIR" write_compat_patch write_node_wrappers rm -rf "$tmp_dir" success "Node.js runtime installed in $NODE_DIR" } install_claude_package() { local package_spec package_spec="$CLAUDE_PACKAGE_NAME" if [ "$CLAUDE_PACKAGE_VERSION" != "latest" ]; then package_spec="${CLAUDE_PACKAGE_NAME}@${CLAUDE_PACKAGE_VERSION}" fi info "Installing $package_spec" PATH="$WRAPPER_BIN_DIR:$GLOBAL_BIN_DIR:$PATH" "$WRAPPER_BIN_DIR/npm" install -g "$package_spec" [ -e "$GLOBAL_BIN_DIR/claude" ] || die "npm install completed, but $GLOBAL_BIN_DIR/claude was not created" [ -x "$CLAUDE_EXE_PATH" ] || die "Claude native binary missing at $CLAUDE_EXE_PATH" success "Claude Code is installed under $GLOBAL_PREFIX_DIR" } backup_existing_launcher() { local backup_path if [ ! -e "$HOST_CLAUDE_PATH" ]; then return 0 fi if grep -Fq "$HOST_WRAPPER_MARKER" "$HOST_CLAUDE_PATH" 2>/dev/null; then success "Managed host launcher already present" return 0 fi backup_path="$BACKUP_DIR/claude.host-backup.$(date +%Y%m%d_%H%M%S)" cp "$HOST_CLAUDE_PATH" "$backup_path" success "Backed up existing launcher to $backup_path" } install_host_wrapper() { local tmp_wrapper tmp_wrapper="$(mktemp "$TMP_ROOT_DIR/claude-wrapper.XXXXXX")" cat >"$tmp_wrapper" <<EOF #!$PREFIX_DIR/bin/bash $HOST_WRAPPER_MARKER export PATH="$WRAPPER_BIN_DIR:$GLOBAL_BIN_DIR:\$PATH" export TMPDIR="\${TMPDIR:-$TMP_ROOT_DIR}" exec "$GLIBC_RUNNER_BIN" -t "$CLAUDE_EXE_PATH" "\$@" EOF chmod 755 "$tmp_wrapper" cp "$tmp_wrapper" "$HOST_CLAUDE_PATH" chmod 755 "$HOST_CLAUDE_PATH" rm -f "$tmp_wrapper" success "Installed host launcher: $HOST_CLAUDE_PATH" } verify_install() { info "Verifying Node wrapper" "$WRAPPER_BIN_DIR/node" --version info "Verifying npm wrapper" "$WRAPPER_BIN_DIR/npm" --version info "Verifying Claude Code launcher" "$HOST_CLAUDE_PATH" --version success "Non-proot Claude Code setup completed" } main() { if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then usage exit 0 fi require_termux ensure_tmp_root ensure_state_dirs ensure_glibc_runner install_node_runtime install_claude_package backup_existing_launcher install_host_wrapper verify_install cat <<EOF Run Claude Code with: claude Current configuration: state dir: $STATE_DIR node version: $NODE_VERSION package version: $CLAUDE_PACKAGE_VERSION launcher: $HOST_CLAUDE_PATH EOF } main "$@" 2.proot方案 (会卡顿 卡就对了 卡了就等待) #!/data/data/com.termux/files/usr/bin/bash set -euo pipefail readonly SCRIPT_NAME="$(basename "$0")" readonly DISTRO_NAME="${CLAUDE_CODE_DISTRO:-debian}" readonly CLAUDE_PACKAGE_NAME="@anthropic-ai/claude-code" readonly CLAUDE_PACKAGE_VERSION="${CLAUDE_CODE_VERSION:-latest}" readonly PREFIX_DIR="${PREFIX:-/data/data/com.termux/files/usr}" readonly HOST_CLAUDE_PATH="$PREFIX_DIR/bin/claude" readonly PROOT_ROOT_DIR="$PREFIX_DIR/var/lib/proot-distro/installed-rootfs" readonly BACKUP_DIR="$HOME/.codex/tmp" readonly WRAPPER_MARKER="# claude-code-termux-wrapper" readonly C_BOLD_BLUE="\033[1;34m" readonly C_BOLD_GREEN="\033[1;32m" readonly C_BOLD_YELLOW="\033[1;33m" readonly C_BOLD_RED="\033[1;31m" readonly C_RESET="\033[0m" info() { printf '%b[INFO]%b %s\n' "$C_BOLD_BLUE" "$C_RESET" "$*" } success() { printf '%b[ OK ]%b %s\n' "$C_BOLD_GREEN" "$C_RESET" "$*" } warn() { printf '%b[WARN]%b %s\n' "$C_BOLD_YELLOW" "$C_RESET" "$*" >&2 } die() { printf '%b[ERR ]%b %s\n' "$C_BOLD_RED" "$C_RESET" "$*" >&2 exit 1 } usage() { cat <<EOF Usage: bash $SCRIPT_NAME What it does: 1. Installs proot-distro in Termux if needed. 2. Installs Debian userspace if needed. 3. Installs nodejs + npm inside Debian. 4. Installs ${CLAUDE_PACKAGE_NAME} inside Debian. 5. Replaces Termux's claude launcher with a wrapper that forwards into Debian. Environment overrides: CLAUDE_CODE_DISTRO proot distro alias, default: ${DISTRO_NAME} CLAUDE_CODE_VERSION npm package version/tag, default: ${CLAUDE_PACKAGE_VERSION} Notes: - Official Claude Code npm binaries do not support Termux's android-arm64 host. - This script uses Debian in proot as the supported Linux runtime. EOF } command_exists() { command -v "$1" >/dev/null 2>&1 } require_termux() { [ -d "$PREFIX_DIR" ] || die "This script must run in Termux." command_exists pkg || die "pkg not found. This script must run in Termux." } ensure_termux_package() { local package_name="$1" if dpkg -s "$package_name" >/dev/null 2>&1; then success "Termux package already installed: $package_name" return 0 fi info "Installing Termux package: $package_name" pkg install -y "$package_name" success "Installed Termux package: $package_name" } ensure_distro() { if [ -d "$PROOT_ROOT_DIR/$DISTRO_NAME" ]; then success "proot distro already installed: $DISTRO_NAME" return 0 fi info "Installing proot distro: $DISTRO_NAME" proot-distro install "$DISTRO_NAME" success "Installed proot distro: $DISTRO_NAME" } run_in_distro() { local command_text="$1" proot-distro login "$DISTRO_NAME" -- bash -lc "$command_text" } ensure_distro_packages() { info "Updating apt metadata inside $DISTRO_NAME" run_in_distro "env DEBIAN_FRONTEND=noninteractive apt-get update" info "Installing nodejs and npm inside $DISTRO_NAME" run_in_distro "env DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs npm" success "nodejs and npm are ready inside $DISTRO_NAME" } install_claude_in_distro() { local package_spec="$CLAUDE_PACKAGE_NAME" if [ "$CLAUDE_PACKAGE_VERSION" != "latest" ]; then package_spec="${CLAUDE_PACKAGE_NAME}@${CLAUDE_PACKAGE_VERSION}" fi info "Installing ${package_spec} inside $DISTRO_NAME" run_in_distro "npm install -g ${package_spec@Q}" success "Claude Code is installed inside $DISTRO_NAME" } backup_existing_launcher() { local backup_path mkdir -p "$BACKUP_DIR" if [ ! -e "$HOST_CLAUDE_PATH" ]; then return 0 fi if grep -Fq "$WRAPPER_MARKER" "$HOST_CLAUDE_PATH" 2>/dev/null; then success "Managed Termux launcher already present" return 0 fi backup_path="$BACKUP_DIR/claude.host-backup.$(date +%Y%m%d_%H%M%S)" cp "$HOST_CLAUDE_PATH" "$backup_path" success "Backed up existing launcher to $backup_path" } install_host_wrapper() { local tmp_wrapper tmp_wrapper="$(mktemp "${TMPDIR:-/tmp}/claude-wrapper.XXXXXX")" cat >"$tmp_wrapper" <<EOF #!/data/data/com.termux/files/usr/bin/sh $WRAPPER_MARKER work_dir=\$PWD if [ ! -d "\$work_dir" ]; then work_dir=/root fi exec proot-distro login --shared-tmp --work-dir "\$work_dir" $DISTRO_NAME -- /usr/local/bin/claude "\$@" EOF chmod 755 "$tmp_wrapper" cp "$tmp_wrapper" "$HOST_CLAUDE_PATH" chmod 755 "$HOST_CLAUDE_PATH" rm -f "$tmp_wrapper" success "Installed Termux launcher: $HOST_CLAUDE_PATH" } verify_install() { info "Verifying Claude inside $DISTRO_NAME" run_in_distro "claude --version" info "Verifying Termux launcher" "$HOST_CLAUDE_PATH" --version success "Claude Code setup completed" } main() { if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then usage exit 0 fi require_termux ensure_termux_package "proot-distro" ensure_distro ensure_distro_packages install_claude_in_distro backup_existing_launcher install_host_wrapper verify_install cat <<EOF Run Claude Code with: claude Current configuration: distro: $DISTRO_NAME host launcher: $HOST_CLAUDE_PATH EOF } main "$@" 非proot方案参考 GitHub - AidanPark/openclaw-android: Run OpenClaw on Android with a single command — no proot, no Linux · GitHub 1 个帖子 - 1 位参与者 阅读完整话题

www.ithome.com · 2026-04-18 12:45:30+08:00 · tech

Apple 产品京东自营旗舰店 4 月大促已开启,iPhone 17 Pro Max 以旧换新至高补贴 1300 元,指定产品享 24 期免息: 点此前往 。 iPhone Air 于去年 10 月 22 日开售,上市起售价为 7999 元。 今日京东自营叠加国补后仅需 5099 元,无需换新等额外操作,本次京东直接降。 此外,若大家所在地区的国补支持京东支付,本次活动还可享 12 期免息分期: 京东 iPhone Air 12+256GB 京东自营 国补后 5099 元 直达链接 iPhone 17 今日也支持 5099 元 +12 期免息哦: 京东 iPhone 17 8+256GB 京东自营 国补后 5099 元 直达链接

linux.do · 2026-04-18 10:43:30+08:00 · tech

可以不需要邀请码了,直接就能用了 需要赞助plus token。 第一天送1850个积分。以后每天送950积分。 之前的用户不受到影响。没有赞助的用户每天只有50积分。 api也弄好了,大家可以试试看。 我之前弄了一个free的gpt图片生成站,然后我今天发现只要改一个模型就能用 GPT-Image2。 现在我遇到的问题如下: 1.我只有5个plus账号。我后面会弄成提供plus账号送积分。我只需要accessToken就可以了。如果你愿意提供cli的格式我也不说什么。之前是1个账号120个图片额度。我不知道 GPT-Image2。是不是也是这样算的。 2.我需要一个公益的图床。我的服务器在日本,传国内免费的图床很慢。还不如直接从服务器下载。 3.暂时没想到 。 记得选gpt-image2 提示词最好告诉ai,需要的是图片,如果ai回复你文字 可能就没有图了。 32 个帖子 - 27 位参与者 阅读完整话题

www.ithome.com · 2026-04-18 08:10:05+08:00 · tech

IT之家 4 月 18 日消息,据新华社报道,法国总统马克龙 16 日在一场欧洲领导人视频会议上说,针对目前讨论的青少年禁用社交媒体平台问题,他建议 直接采取平台对 15 岁以下青少年禁用的措施 , 而非优先采用家长同意机制。 这场视频会议由法国召集,德国、爱尔兰、西班牙、塞浦路斯等 10 多个欧洲国家和欧盟委员会参与。马克龙说, 法国尝试过家长同意机制,但效果不佳 ,尤其是对于那些缺乏数字素养和监管能力的家庭。 IT之家从报道中获悉,家长同意机制是指 未成年人在使用社交媒体前应获得家长同意 。马克龙认为,责任不应该落在家长身上,而应该 由社交媒体平台承担 。社交媒体平台应确保提供多种可靠的年龄验证方案,欧洲也应该有自己的方案。 当前,越来越多的欧洲国家考虑对青少年使用社交媒体设限,并在平台直接禁用和家长同意之间权衡。欧盟委员会官网信息显示,其开发的一款年龄验证应用程序在技术上已准备就绪,将很快向民众开放使用。