@fengye404/termpilot 0.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/.env.example ADDED
@@ -0,0 +1,9 @@
1
+ PORT=8787
2
+ HOST=127.0.0.1
3
+ DATABASE_URL=postgresql://<your-user>@127.0.0.1:5432/termpilot
4
+ TERMPILOT_DEVICE_ID=pc-main
5
+ TERMPILOT_AGENT_TOKEN=demo-agent-token
6
+ TERMPILOT_CLIENT_TOKEN=demo-client-token
7
+ TERMPILOT_PAIRING_TTL_MINUTES=10
8
+ TERMPILOT_RELAY_URL=ws://127.0.0.1:8787/ws
9
+ TERMPILOT_POLL_INTERVAL_MS=500
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # TermPilot
2
+
3
+ TermPilot 是一个终端优先的远程控制工具。电脑上跑 `tmux` 会话,手机直接打开 relay 域名查看和控制同一批会话。
4
+
5
+ ## 产品形态
6
+
7
+ - 一个 npm 包:`termpilot`
8
+ - 一个服务器命令:`termpilot relay`
9
+ - 一个电脑命令:`termpilot agent`
10
+ - 手机端不安装,直接打开 relay 域名
11
+ - relay 同时负责消息中继和网页托管
12
+
13
+ ## 快速开始
14
+
15
+ ### 服务器
16
+
17
+ 发布后:
18
+
19
+ ```bash
20
+ npm install -g @fengye404/termpilot
21
+ termpilot relay
22
+ ```
23
+
24
+ 当前仓库内本地验证:
25
+
26
+ ```bash
27
+ pnpm install
28
+ pnpm build
29
+ npm install -g .
30
+ termpilot relay
31
+ ```
32
+
33
+ 常用参数:
34
+
35
+ ```bash
36
+ termpilot relay --host 0.0.0.0 --port 8787
37
+ DATABASE_URL=postgresql://user:pass@127.0.0.1:5432/termpilot termpilot relay
38
+ ```
39
+
40
+ ### 电脑
41
+
42
+ ```bash
43
+ npm install -g @fengye404/termpilot
44
+ termpilot agent --relay ws://your-domain.com/ws
45
+ ```
46
+
47
+ 本地测试:
48
+
49
+ ```bash
50
+ termpilot agent --relay ws://127.0.0.1:8787/ws
51
+ ```
52
+
53
+ ### 手机
54
+
55
+ 直接打开 relay 域名:
56
+
57
+ - `https://your-domain.com`
58
+
59
+ 首次使用时,在电脑上申请一次性配对码:
60
+
61
+ ```bash
62
+ termpilot pair
63
+ ```
64
+
65
+ 然后在手机页面输入配对码。
66
+
67
+ ## 日常使用
68
+
69
+ 创建会话并进入:
70
+
71
+ ```bash
72
+ termpilot create --name claude-main --cwd /path/to/project
73
+ termpilot list
74
+ termpilot attach --sid <sid>
75
+ ```
76
+
77
+ 在会话里运行:
78
+
79
+ ```bash
80
+ claude code
81
+ # 或
82
+ open code
83
+ ```
84
+
85
+ 此时手机和电脑看到的是同一个会话,输出会同步刷新。
86
+
87
+ ## 常用命令
88
+
89
+ ```bash
90
+ termpilot relay
91
+ termpilot agent --relay ws://127.0.0.1:8787/ws
92
+ termpilot pair
93
+ termpilot create --name claude-main
94
+ termpilot list
95
+ termpilot attach --sid <sid>
96
+ termpilot kill --sid <sid>
97
+ termpilot grants
98
+ termpilot audit --limit 30
99
+ termpilot revoke --token <accessToken>
100
+ termpilot doctor
101
+ ```
102
+
103
+ ## 最佳实践
104
+
105
+ 1. 需要跨端同步的任务,一开始就用 `termpilot create` 创建,不要先在普通终端里跑再想着接管。
106
+ 2. 一个长期任务用一个独立会话,名称直接写任务语义,比如 `claude-main`、`deploy-watch`。
107
+ 3. 电脑前重操作优先 `termpilot attach`,手机更适合看进度、补命令和关闭会话。
108
+ 4. 手机优先走一次性配对码,不要长期依赖共享 `client token`。
109
+ 5. 要长期使用 relay,优先接 PostgreSQL;本地演示可以先用内存模式。
110
+ 6. 换手机或访问权变更时,先 `termpilot grants`,再 `termpilot revoke --token ...`。
111
+ 7. 想排查控制历史时先看 `termpilot audit --limit 30`。
112
+
113
+ ## 本地开发
114
+
115
+ ```bash
116
+ pnpm install
117
+ pnpm dev:relay
118
+ pnpm dev:app
119
+ pnpm dev:agent
120
+ ```
121
+
122
+ 常用检查:
123
+
124
+ ```bash
125
+ pnpm typecheck
126
+ pnpm build
127
+ pnpm test:ui-smoke
128
+ pnpm check:stability
129
+ ```
130
+
131
+ 更多实现说明:
132
+
133
+ - [当前架构](/Users/fengye/workspace/TermPilot/docs/architecture.md)
134
+ - [当前协议](/Users/fengye/workspace/TermPilot/docs/protocol.md)
135
+ - [技术选型](/Users/fengye/workspace/TermPilot/docs/tech-selection-2026.md)
@@ -0,0 +1 @@
1
+ .xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;inset:0}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;inset:0;z-index:10;color:transparent;pointer-events:none}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-amber-200:oklch(92.4% .12 95.746);--color-amber-400:oklch(82.8% .189 84.429);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-rose-200:oklch(89.2% .058 10.001);--color-rose-500:oklch(64.5% .246 16.439);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-medium:500;--font-weight-semibold:600;--radius-2xl:1rem;--radius-3xl:1.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.h-full{height:100%}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-32{min-height:calc(var(--spacing) * 32)}.min-h-\[68vh\]{min-height:68vh}.min-h-\[440px\]{min-height:440px}.min-h-screen{min-height:100vh}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-7xl{max-width:var(--container-7xl)}.flex-1{flex:1}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-amber-400\/50{border-color:#fcbb0080}@supports (color:color-mix(in lab,red,red)){.border-amber-400\/50{border-color:color-mix(in oklab,var(--color-amber-400) 50%,transparent)}}.border-emerald-500\/50{border-color:#00bb7f80}@supports (color:color-mix(in lab,red,red)){.border-emerald-500\/50{border-color:color-mix(in oklab,var(--color-emerald-500) 50%,transparent)}}.border-rose-500\/40{border-color:#ff235766}@supports (color:color-mix(in lab,red,red)){.border-rose-500\/40{border-color:color-mix(in oklab,var(--color-rose-500) 40%,transparent)}}.border-sky-400\/70{border-color:#00bcfeb3}@supports (color:color-mix(in lab,red,red)){.border-sky-400\/70{border-color:color-mix(in oklab,var(--color-sky-400) 70%,transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-800\/80{border-color:#1d293dcc}@supports (color:color-mix(in lab,red,red)){.border-slate-800\/80{border-color:color-mix(in oklab,var(--color-slate-800) 80%,transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/10{background-color:color-mix(in oklab,var(--color-emerald-500) 10%,transparent)}}.bg-emerald-500\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/15{background-color:color-mix(in oklab,var(--color-emerald-500) 15%,transparent)}}.bg-rose-500\/10{background-color:#ff23571a}@supports (color:color-mix(in lab,red,red)){.bg-rose-500\/10{background-color:color-mix(in oklab,var(--color-rose-500) 10%,transparent)}}.bg-sky-500{background-color:var(--color-sky-500)}.bg-sky-500\/10{background-color:#00a5ef1a}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/10{background-color:color-mix(in oklab,var(--color-sky-500) 10%,transparent)}}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-900\/70{background-color:#0f172bb3}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/70{background-color:color-mix(in oklab,var(--color-slate-900) 70%,transparent)}}.bg-slate-900\/72{background-color:#0f172bb8}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/72{background-color:color-mix(in oklab,var(--color-slate-900) 72%,transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\/35{background-color:#02061859}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/35{background-color:color-mix(in oklab,var(--color-slate-950) 35%,transparent)}}.bg-slate-950\/40{background-color:#02061866}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/40{background-color:color-mix(in oklab,var(--color-slate-950) 40%,transparent)}}.bg-slate-950\/60{background-color:#02061899}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/60{background-color:color-mix(in oklab,var(--color-slate-950) 60%,transparent)}}.bg-slate-950\/95{background-color:#020618f2}@supports (color:color-mix(in lab,red,red)){.bg-slate-950\/95{background-color:color-mix(in oklab,var(--color-slate-950) 95%,transparent)}}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-5{padding-block:calc(var(--spacing) * 5)}.text-left{text-align:left}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[11px\]{font-size:11px}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.25em\]{--tw-tracking:.25em;letter-spacing:.25em}.text-amber-200{color:var(--color-amber-200)}.text-emerald-200{color:var(--color-emerald-200)}.text-emerald-300{color:var(--color-emerald-300)}.text-rose-200{color:var(--color-rose-200)}.text-sky-300{color:var(--color-sky-300)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-950{color:var(--color-slate-950)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-0{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-slate-950\/30{--tw-shadow-color:#0206184d}@supports (color:color-mix(in lab,red,red)){.shadow-slate-950\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-950) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-slate-950\/40{--tw-shadow-color:#02061866}@supports (color:color-mix(in lab,red,red)){.shadow-slate-950\/40{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-slate-950) 40%, transparent) var(--tw-shadow-alpha), transparent)}}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.placeholder\:text-slate-500::placeholder{color:var(--color-slate-500)}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:40rem){.sm\:flex-row{flex-direction:row}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:48rem){.md\:sticky{position:sticky}.md\:top-0{top:calc(var(--spacing) * 0)}.md\:z-10{z-index:10}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:justify-between{justify-content:space-between}.md\:bg-slate-900\/72{background-color:#0f172bb8}@supports (color:color-mix(in lab,red,red)){.md\:bg-slate-900\/72{background-color:color-mix(in oklab,var(--color-slate-900) 72%,transparent)}}.md\:pb-2{padding-bottom:calc(var(--spacing) * 2)}}@media(min-width:64rem){.lg\:grid-cols-\[360px_minmax\(0\,1fr\)\]{grid-template-columns:360px minmax(0,1fr)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}}}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}:root{color-scheme:dark}body{color:#e2e8f0;background:radial-gradient(circle at 0 0,#38bdf824,#0000 32%),linear-gradient(#020617,#0f172a 48%,#020617);min-height:100vh;margin:0;font-family:SF Pro Display,PingFang SC,Helvetica Neue,sans-serif}#root{min-height:100vh}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}