mobile-remote-dev / index.html
Lawrence-cj's picture
Reuse Termux screenshot as video poster
17e3e51
Raw History Blame Contribute Delete
14.7 kB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>用 Pad 远程开发 · Tablet-Driven Remote Dev</title>
<style>
:root{
--bg:#fbfbfa; --fg:#1c1c1a; --muted:#6b6b66;
--line:#e4e3df; --card:#fff; --accent:#2f6f4f; --accent-soft:#eef4f0;
--mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){
:root{ --bg:#151614; --fg:#eceae4; --muted:#9b9a93;
--line:#2e302c; --card:#1d1f1c; --accent:#7fc39a; --accent-soft:#1f2a24; }
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);
font:16px/1.7 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
-webkit-font-smoothing:antialiased;}
.wrap{max-width:800px;margin:0 auto;padding:56px 24px 96px}
header h1{font-size:29px;line-height:1.3;margin:0 0 10px;letter-spacing:-.01em}
header p{margin:0;color:var(--muted);font-size:15px}
header .en{font-size:15px;color:var(--muted);font-weight:400;display:block;margin-top:4px}
nav{display:flex;gap:4px;margin:36px 0 40px;border-bottom:1px solid var(--line);overflow-x:auto}
nav button{appearance:none;background:none;border:0;border-bottom:2px solid transparent;
color:var(--muted);font:inherit;font-size:15px;padding:9px 14px;cursor:pointer;margin-bottom:-1px;white-space:nowrap}
nav button:hover{color:var(--fg)}
nav button[aria-selected="true"]{color:var(--fg);border-bottom-color:var(--accent);font-weight:600}
section[hidden]{display:none}
h2{font-size:13px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
margin:44px 0 16px;font-weight:600}
h2:first-of-type{margin-top:0}
.lead{font-size:17px;margin:0 0 8px}
.lead-en{color:var(--muted);font-size:14px;margin:0 0 4px}
.flow{display:flex;flex-direction:column;gap:0;margin:8px 0 4px}
.node{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:14px 16px}
.node b{display:block;font-size:15px}
.node span{color:var(--muted);font-size:13.5px}
.node.hl{border-color:var(--accent);background:var(--accent-soft)}
.arrow{color:var(--muted);font-size:13px;padding:7px 0 7px 16px;display:flex;align-items:center;gap:9px}
.arrow::before{content:"↓";font-size:15px;color:var(--accent)}
.route-grid,.cards{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.route,.card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px 18px}
.route h3,.card h3{margin:0 0 3px;font-size:15.5px}
.route p,.card p{margin:0;font-size:14px;color:var(--muted);line-height:1.65}
.route code{display:inline-block;margin-top:8px}
.card .en{display:block;color:var(--muted);font-size:12.5px;font-weight:400;margin-bottom:7px}
ol.steps{list-style:none;counter-reset:s;padding:0;margin:0}
ol.steps>li{counter-increment:s;position:relative;padding:0 0 26px 38px;border-left:1px solid var(--line);margin-left:11px}
ol.steps>li:last-child{border-left-color:transparent;padding-bottom:0}
ol.steps>li::before{content:counter(s);position:absolute;left:-11px;top:0;width:22px;height:22px;
border-radius:50%;background:var(--accent);color:#fff;font-size:12px;font-weight:700;
display:flex;align-items:center;justify-content:center}
@media (prefers-color-scheme:dark){ol.steps>li::before{color:#12140f}}
ol.steps h3{margin:0 0 3px;font-size:16px}
ol.steps p{margin:0 0 10px;color:var(--muted);font-size:14px}
pre{background:var(--card);border:1px solid var(--line);border-radius:8px;
padding:12px 14px;overflow-x:auto;margin:0;font:13px/1.65 var(--mono)}
pre .c{color:var(--muted)}
code{font:13.5px var(--mono);background:var(--accent-soft);padding:1px 5px;border-radius:4px}
table{width:100%;border-collapse:collapse;font-size:14px}
th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:12.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);font-weight:600}
td:first-child{white-space:nowrap;color:var(--muted)}
.note{border-left:2px solid var(--accent);padding:2px 0 2px 14px;color:var(--muted);font-size:14px;margin:16px 0}
.shot{margin:24px auto 30px;max-width:620px}
.shot img{display:block;width:100%;height:auto;border:1px solid var(--line);border-radius:12px;background:#000}
.shot video{display:block;width:100%;height:auto;border:1px solid var(--line);border-radius:12px;background:#000}
.shot.clip{max-width:420px}
.shot figcaption{margin-top:9px;color:var(--muted);font-size:13px;line-height:1.6;text-align:center}
.tag{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:1px 8px;margin-right:5px;
color:var(--muted);font-size:12px;background:var(--card)}
footer{margin-top:64px;padding-top:20px;border-top:1px solid var(--line);color:var(--muted);font-size:13px}
@media (max-width:620px){
.route-grid,.cards{grid-template-columns:1fr}
.wrap{padding:36px 18px 72px}
header h1{font-size:24px}
nav button{padding-left:10px;padding-right:10px;font-size:14px}
}
</style>
</head>
<body>
<div class="wrap">
<header>
<h1>用一台 Pad,随时接管 Mac 与 GPU 集群
<span class="en">A real remote-development endpoint, built with Termux and bidirectional SSH</span>
</h1>
<p>近处走局域网,远处走腾讯云;需要公司网络时走 VPN。入口不变,路径自动选择。</p>
</header>
<nav role="tablist">
<button role="tab" aria-selected="true" data-t="connect">怎么连接 · Connect</button>
<button role="tab" aria-selected="false" data-t="termux">Termux 是什么</button>
<button role="tab" aria-selected="false" data-t="why">为什么这样做 · Why</button>
</nav>
<!-- ===================== CONNECT ===================== -->
<section id="connect">
<h2>现在的链路 · The new chain</h2>
<p class="lead">Pad 不再只是一个 SSH 客户端,而是一台能被双向访问的 Linux 终端。</p>
<p class="lead-en">Termux turns the tablet into an addressable Unix endpoint, not just a screen.</p>
<div class="flow">
<div class="node hl"><b>📱 OPPO Pad · Termux</b><span>zsh、SSH、会话切换和本地文件都在这里。</span></div>
<div class="arrow">同一局域网直接连接;在外面时经腾讯云中继</div>
<div class="node hl"><b>💻 Mac · 工作与 Agent 中心</b><span>Codex、git、项目文件和持久 tmux 会话运行在这里。</span></div>
<div class="arrow">Mac 已有的公司网络与 SSH 配置</div>
<div class="node"><b>🖥️ GPU 集群</b><span>NRT、Poly、Prenyx 等训练与推理环境。</span></div>
</div>
<div class="note">
Pad 开启 Sing-box 时可以直连集群;没有 VPN 时则自动借用 Mac 的网络。无论走哪条路,常用命令保持不变。
</div>
<h2>Pad 怎么连接 · From the Pad</h2>
<div class="route-grid">
<div class="route">
<h3>进入 Mac</h3>
<p>普通 Shell、恢复工作现场或直接启动 Codex。</p>
<code>MAC</code> <code>mac-cc</code> <code>CODEX</code>
</div>
<div class="route">
<h3>进入服务器</h3>
<p>SSH alias 已同步;VPN 可用就直连,否则经过 Mac。</p>
<code>NRT</code> <code>poly</code> <code>prenyx</code>
</div>
</div>
<h2>自动选路 · One name, two routes</h2>
<ol class="steps">
<li>
<h3>同一局域网:直连</h3>
<p>Pad 和 Mac 在同一个 Wi-Fi 时,SSH 直接在本地网络传输,延迟最低。</p>
</li>
<li>
<h3>人在外面:腾讯云中继</h3>
<p>Mac 和 Pad 都主动建立反向 SSH 隧道。云端端口只绑定到本机回环地址,不直接暴露给公网。</p>
</li>
<li>
<h3>入口始终不变</h3>
<p>连接命令先探测局域网,失败后自动切到腾讯云;不需要记 IP、端口或当前网络状态。</p>
</li>
</ol>
<h2>Mac 如何反向连接 Pad · Back to the Pad</h2>
<p class="lead">Mac 和运行在 Mac 上的 Agent 使用同一个入口。</p>
<p class="lead-en">The same alias works for a human shell, automation, and file transfer.</p>
<pre><span class="c"># 进入 Pad;局域网优先,腾讯云兜底</span>
ssh pad
<span class="c"># 在 Pad 执行一条独立命令</span>
ssh pad 'command'
<span class="c"># 双向传文件</span>
scp local-file pad:~/
scp pad:~/remote-file .</pre>
<div class="note">
这让 Agent 能直接检查 Pad 状态、读取最新截图、同步文件或打开&#27979;&#35797;页面。Pad 不再是链路末端,而是工作流的一部分。
</div>
<h2>只需要记住 · The essentials</h2>
<table>
<tr><th>入口</th><th>作用</th></tr>
<tr><td><code>mac-cc</code></td><td>从 Pad 回到 Mac 上名为 <code>cc</code> 的 tmux 工作现场</td></tr>
<tr><td><code>CODEX</code></td><td>在 Mac 上运行 Codex,Pad 只负责显示和输入</td></tr>
<tr><td><code>NRT</code> / <code>poly</code></td><td>连接 GPU 集群,自动选择直连或经 Mac</td></tr>
<tr><td><code>ssh pad</code></td><td>从 Mac 或 Agent 反向进入 Pad</td></tr>
</table>
</section>
<!-- ===================== TERMUX ===================== -->
<section id="termux" hidden>
<h2>一句话 · In one line</h2>
<p class="lead">Termux 在 Android 上提供一个真正的 Linux 命令行环境。</p>
<p class="lead-en">Termux turns the Pad into a Unix endpoint that can initiate and accept SSH connections.</p>
<figure class="shot">
<img src="assets/termux-pad.jpg" alt="OPPO Pad 上的 Termux 界面,正在显示 Mac 上的 Codex 会话" loading="lazy">
<figcaption>Pad 上的真实 Termux 界面。这里正在显示 Mac 上的 Codex 会话;Termux 负责终端、输入和连接,计算与 Agent 运行在 Mac 上。</figcaption>
</figure>
<figure class="shot clip">
<video controls playsinline preload="metadata" poster="assets/termux-pad.jpg" aria-label="在 OPPO Pad 上使用 Termux 连接 Mac、NRT 和 Codex 的完整操作录屏">
<source src="assets/termux-pad-workflow.mp4" type="video/mp4">
你的浏览器不支持视频播放,可以<a href="assets/termux-pad-workflow.mp4">下载录屏</a>查看。
</video>
<figcaption>3 分钟真实操作:从 Pad 里的 Termux 进入 NRT 与 Mac 上的 Codex,再切换到浏览器查看工作结果。全屏播放时终端文字更清楚。</figcaption>
</figure>
<div class="flow">
<div class="node hl"><b>📱 Pad 上的 Termux</b><span>运行 zsh、OpenSSH、命令别名和少量本地工具。</span></div>
<div class="arrow">输入 MAC、NRT、poly 或 prenyx</div>
<div class="node"><b>🔐 SSH 连接</b><span>负责把 Termux 这个本地终端接到另一台机器。</span></div>
<div class="arrow">连接成功后,命令在远端执行</div>
<div class="node hl"><b>🖥️ Mac 或 GPU 集群</b><span>真正运行 Codex、代码、训练和持久 tmux 会话。</span></div>
</div>
<div class="note">
刚打开 Termux 时,你仍然在 Pad 本地。只有执行连接命令之后,才会进入 Mac 或集群。
</div>
<h2>不要混淆 · Three different layers</h2>
<table>
<tr><th>工具</th><th>它负责什么</th></tr>
<tr><td><code>Termux</code></td><td>Pad 本地的 Linux 命令行环境</td></tr>
<tr><td><code>SSH</code></td><td>在 Pad、Mac、腾讯云和集群之间建立连接</td></tr>
<tr><td><code>tmux</code></td><td>让 Mac 或服务器上的会话在 SSH 断线后继续运行</td></tr>
</table>
</section>
<!-- ===================== WHY ===================== -->
<section id="why" hidden>
<p class="lead">一句话:把「拿在手里的设备」和「真正运行工作的机器」彻底解耦。</p>
<p class="lead-en">The tablet is the control surface; the Mac and clusters remain the computers.</p>
<h2>好处 · Advantages</h2>
<div class="cards">
<div class="card">
<h3>任何地方,同一个入口<span class="en">One command everywhere</span></h3>
<p>局域网和腾讯云自动切换,不再根据地点修改 Host、端口或跳板设置。</p>
</div>
<div class="card">
<h3>会话不会丢<span class="en">Sessions survive disconnects</span></h3>
<p>tmux 留在 Mac 上。锁屏、换 Wi-Fi 或隧道重连后,工作现场仍然完整。</p>
</div>
<div class="card">
<h3>集群有两条路<span class="en">Direct when possible</span></h3>
<p>Pad 有 Sing-box 时直连公司集群;否则让 Mac 继续承担公司网络入口。</p>
</div>
<div class="card">
<h3>Codex 打通所有设备<span class="en">One agent across every device</span></h3>
<p>Mac 上的 Codex 可以反向 SSH 控制 Pad,也能连接腾讯云和 GPU 集群;同一个 Agent 因此能在全部设备间执行命令、检查状态和传输文件。</p>
</div>
<div class="card">
<h3>Pad 不需要很强<span class="en">The device stops mattering</span></h3>
<p>编译、推理和 Agent 都在 Mac 或 GPU 集群运行,Pad 负责输入、显示与少量本地工具。</p>
</div>
<div class="card">
<h3>家里不暴露端口<span class="en">Nothing exposed at home</span></h3>
<p>Mac 和 Pad 都主动连向云端;家用路由器不需要公网 IP 或端口转发。</p>
</div>
</div>
<h2>边界 · What it is for</h2>
<table>
<tr><th>适合</th><th>不适合</th></tr>
<tr><td>CLI Agent、日志、Git、训练任务</td><td>需要大量拖拽或复杂 GUI 的工作</td></tr>
<tr><td>随时检查、修改和继续任务</td><td>把 Pad 当作本地高性能工作站</td></tr>
</table>
<div class="note">
它没有让计算更快,而是让「必须坐在电脑前」不再是前提。
<br>It makes nothing faster. It removes the requirement of being at your desk.
</div>
</section>
<footer>
<span class="tag">Termux</span><span class="tag">OpenSSH</span><span class="tag">tmux</span><span class="tag">reverse tunnel</span>
<br><br>地址、端口与用户名均为示意;密钥和认证信息不进入页面。
</footer>
</div>
<script>
const tabs = document.querySelectorAll('nav button');
tabs.forEach(button => button.addEventListener('click', () => {
tabs.forEach(item => item.setAttribute('aria-selected', String(item === button)));
document.querySelectorAll('section[id]').forEach(section => {
section.hidden = section.id !== button.dataset.t;
});
window.scrollTo({top:0, behavior:'smooth'});
}));
</script>
</body>
</html>