Repository navigation
Expand file tree
/
Copy pathsupport.html
More file actions
94 lines (90 loc) · 6.88 KB
/
Copy pathsupport.html
File metadata and controls
94 lines (90 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!DOCTYPE html>
<html lang="en" data-lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
// Browser language on the root page. navigator.languages is read in order; the first entry
// that is zh-Hant (script Hant, or region TW/HK/MO), ja, ko or en decides. Other entries
// (zh-Hans, zh-CN, fr, …) are skipped, so with none matching the page stays English.
// A language picked with the switcher is stored in localStorage and never overridden.
(function () {
var KEY = "oab-lang";
var PAGES = { en: "/", zh: "/zh/", ja: "/ja/", ko: "/ko/" };
function stored() { try { return localStorage.getItem(KEY); } catch (e) { return null; } }
function pick(tag) {
var p = String(tag).toLowerCase().split("-");
if (p[0] === "en" || p[0] === "ja" || p[0] === "ko") return p[0];
if (p[0] !== "zh" || p.indexOf("hans") >= 0) return null;
var zhHant = p.some(function (s) { return s === "hant" || s === "tw" || s === "hk" || s === "mo"; });
return zhHant ? "zh" : null;
}
if (location.pathname === "/" && !stored()) {
var langs = navigator.languages && navigator.languages.length ? navigator.languages : [navigator.language];
var lang = null;
for (var i = 0; i < langs.length && !lang; i++) lang = pick(langs[i]);
if (lang && lang !== "en") location.replace(PAGES[lang] + location.search + location.hash);
}
document.addEventListener("click", function (e) {
var a = e.target.closest && e.target.closest(".lang a");
if (!a) return;
var code = (a.getAttribute("href") || "").split("/")[1] || "en";
if (!PAGES[code]) return;
try { localStorage.setItem(KEY, code); } catch (err) { /* storage unavailable: nothing to remember */ }
});
})();
</script>
<title>Support — OpenAB Connect</title>
<meta name="description" content="How to try OpenAB Connect without deploying anything, and the failures worth knowing about in advance.">
<link rel="canonical" href="https://connect.openab.dev/support.html">
<meta property="og:type" content="article">
<meta property="og:site_name" content="OpenAB Connect">
<meta property="og:locale" content="en_US">
<meta property="og:title" content="Support — OpenAB Connect">
<meta property="og:description" content="How to try OpenAB Connect without deploying anything, and the failures worth knowing about in advance.">
<meta property="og:url" content="https://connect.openab.dev/support.html">
<link rel="icon" href="/icon.png?v=e698e97e">
<link rel="apple-touch-icon" href="/icon.png?v=e698e97e">
<link rel="stylesheet" href="/style.css?v=7044ef38">
<link rel="alternate" hreflang="zh-Hant" href="https://connect.openab.dev/zh/support.html">
<link rel="alternate" hreflang="ja" href="https://connect.openab.dev/ja/support.html">
<link rel="alternate" hreflang="ko" href="https://connect.openab.dev/ko/support.html">
<link rel="alternate" hreflang="en" href="https://connect.openab.dev/support.html">
<link rel="alternate" hreflang="x-default" href="https://connect.openab.dev/support.html">
</head>
<body>
<nav>
<a class="brand" href="/"><img src="/icon.png?v=e698e97e" alt="" width="28" height="28">OpenAB Connect</a>
<div class="links">
<a href="/#features">Features</a>
<a href="/#faq">FAQ</a>
<a href="/1min/">1-min tutorials</a>
<a href="/notes/">Dev notes</a>
<a href="/releases/">Releases</a>
<a href="/support.html">Support</a>
<span class="lang"><a href="/zh/support.html">中文</a>|<a href="/ja/support.html">日本語</a>|<a href="/ko/support.html">한국어</a>|<a class="active" href="/support.html">EN</a></span>
</div>
</nav>
<div class="wrap doc">
<h1>Support</h1>
<div class="panel"><p style="margin:0"><a href="mailto:support@openab.dev">support@openab.dev</a> — or open an issue at <a href="https://github.com/openabdev/openab-pty/issues">openabdev/openab-pty</a> for anything about the runtime itself.</p><p style="margin:10px 0 0" class="dim">Security issues: please use <a href="https://github.com/openabdev/openab-pty/security/advisories/new">a private advisory</a> rather than a public issue or email.</p></div>
<h2>Trying the app without deploying anything</h2>
<p>Open the <strong>OpenAB Connect</strong> menu and choose <strong>Demo Mode</strong>. Two sample connections appear; double-click a session under either one to open a terminal. It is a canned transcript with local echo — no network connection is made and nothing is executed. Choose Demo Mode again to remove the samples.</p>
<h2>Things that go wrong, and why</h2>
<h3>The first deployment takes a long time</h3><p>It is pulling a container image, and the first pull of any agent variant is the slow part — measured at over two minutes for 156 MB on an ordinary connection. The app reports what it is waiting on. Nothing is wrong until it says so.</p>
<h3>“No tailnet node appeared”</h3><p>Registration normally takes seconds, so this almost never means slowness. In order of likelihood: this Mac is signed out of the tailnet, or on a different one; the auth key was rejected — expired, already consumed, or not marked reusable; or a node of that name already exists, so the new one registered as <code>name-1</code>, which a non-ephemeral key does on every deploy.<br><br>Use a key that is both <strong>Reusable</strong> and <strong>Ephemeral</strong>. Ephemeral is what lets a deleted pod's node leave the tailnet instead of accumulating dead entries.</p>
<h3>A session says it expired, or was taken over</h3><p>Sessions are single-attach by design: a second device attaching takes the keyboard. TTLs are set when you deploy. Both are reported with a specific reason rather than a generic disconnect.</p>
<h3>The workspace lost my work</h3><p>The workspace is ephemeral unless you chose a persistent one at deploy time. It does not survive the pod being replaced. Push your work; lifecycle hooks are a backup, not a primary mechanism. The app says so in every session's header for this reason.</p>
<h3>A process kept running after I killed a session</h3><p>Teardown is best-effort and labelled as such throughout. Only one kill domain is implemented, and a process that leaves its process group may outlive its session until the pod or task is replaced. This is documented behaviour, not a fault. To be certain nothing remains, delete the pod or task.</p>
<h2>Requirements</h2><ul><li>macOS 13 or later.</li><li>A Kubernetes cluster or an AWS account you can deploy into.</li><li>A Tailscale tailnet, and an auth key for it.</li></ul>
<h2>Where things live on your Mac</h2><pre>~/Library/Containers/dev.openab.connect/ app data, sandboxed
Keychain (login) credentials, per connection</pre><p class="dim">Removing the app leaves those; delete them if you want it gone entirely.</p>
</div>
<footer>
<a href="/privacy.html">Privacy</a>
<a href="/support.html">Support</a>
<a href="https://github.com/openabdev/openab-pty">Runtime source</a>
<span class="dim">© 2026 openabdev</span>
</footer>
</body>
</html>