tYYNpaFLEn$WVGfL z?vK!<_aW+bo{|Blc?-4PPLvKw6upbQWhyyYsFlC@lnbpSq9dSE%410T?U;a|wqH*p zD&Y&|E<`P_^`)zP_272U^uE!fsJ0)FfMLu2nyDd+!%FEQykI!7I)z!k$MMYn9BjZ!!&`SiBU)0yv*V^8&oqN;c_MW*;eM@$u zZ1GFqR3US1GrDcOqf5&WLj{PbsD|s7gjH1Z*WUa}i!h!Tn6xJ;#Vj-8AQHRZwoFSG zMKV(j{64+ay0G%rrd1G8uI_uByDc{lK}j~x)DK?{jvz-z^jGp~1s%h!w~p>btXrsn z1mog*v11jD<(j Dgq{z+z=)S<`0rQ`Q4*yWv2k%ztJ5Sd-OFcU zCjRGsjZKg7g&XFxoSZByJn(6pp%n{kwUA7Sm7%>o++ H4V^3 z*yf*a{a9ww)U~I;B%2WEv~0B*X=G5Ld2OccU9Nd4_v)MXaZgE&;q-C (x~R%yv4ahz3jN1 zY6p23SDkjM=Z6O`wpq-cd|jPG&+WDaai)$hDNkS-`m6yl;L$#_nLHjyHOV`!V6mrg zh09=8I8_g)Jzk3lMb$x2%l-5xB>CU(T~6E!F~fP%$>X?CT4-8@CL1=2N|d_>5yK>t z!YmAl`*ITB>W1?3ur;1MJUqCv4x3n~Kl22GwQ^IWOKg#{{|CJ$0jEp+tJf;*-BtnM z1@(XRTFzTXd>#DZXIt;GIk4u^@8)LpC50J8$+u`FpJYRrvC)$n)n$9n`0VJJ70?Gq zmOn|Mn{5&mb4SWZeldl?P|@&d5K#*MfItRI)}L2?HydKNH+~cff+=PG9zQvrFs3;^ zU0xk-+k3cKh2C%@3`FD5$;C4fp_SqCD(7V!S&q`aw%&Dop&3J+^E F}`S(Bv#u*+LNoZgHd&I3p%@G}x4<25filC0rssFkNn5%&D{-c7F1h1ps8 zKFKCH5EwbOV0DlyZ6qVQc2Lw{&$ 2ap>Tf{Zx z4m3)lDkcU0>~UKw%{erYpk9O?Y}7w&yoOh32WabVq8-QF#Fzf@&Q4w&^K1ny0IxE& z$=fcq=?LvAOPlY7)hrT*alBMXtHl$7;VMbP+;VJ&0Vw)*71&Wv$k8SC27Vv#5P5C0 zrv(vO%Ud-nTi12oshj!M&2yq!4Z5 9I~*;!W7wlX?}(_uH98Zo7_;y21&chFwKzz`j3Je=u|4l)lmca*w@ d z{JtGZIUB-Kh^-}ZHAgo)jP2+P)5c6up<{EghaX6N4XDaZ%UY*Dwf5ID4UQ@(sL5>Z zt0?GNJ}326Y+UyduD8#|TwG8Hx;NrhIDFkO8(?5G8`xAFVSNcOSA|t3qbS4L+m-dN zPtY0zIvG1IVH~FvKZ4q*RvnN{ehCuM$Kdpykxwly#t^VApkQ=y3Ix?i^`9u2Ut>UO zZPk!I CI?c|*AZ6Msb?%Y$S4m(adQHhk* zWH~et^?OKI&R)S9S+p1}|NaTc8Mam?vN+?NG@H$E=gMg~2f>yxw 7l2)sUED!oP=yop8+c`C0G3F!=Adzg`lrUq*vn%OumX(mzy|6SzlY-}VZ z6G)SMAO5?Ic8G5>i^NcTjgneQ@toaJzxz6cpjW%bU)I-GFb#jQuOdl|tKoA{43?#_ z?ccQ-D0w2K=t<_&{MR-c0Rq@-B`za*g>H6M_MY4GyCC}}uS^-fonhv<6<3N`BxZPV z^~YswqMP-C`nu_mIjXo$3x%RG4Qev+K>;0DQ6D(4>1}|-SzHFYyt1p2lg*Y-X(KkV1 zDuN$KNBGijvT 4);>%*$5RH{sxG{ZR`-)CgRdRe~>Ut9>11mm}!cTa}ixmaxd V(e$jGj>Hq#m3bK4+O{bFCz+S!visR>e~8d zGk&3mKOEKA!lJ8@pfgHJN_|ksuI#$LXL2;@tII|nxN5Ta6(h#_2>~wJk8# Bj+_sLgp8=}oNy|Lds!%jYl&Dyp3|2)JVM>VzyLw|B}jVwdpHWQ6Ru*z@wK^R zO{$au>eBD*VeL&YFoy$WB7RYUUw)@}{b#FJne53d^vjno6N8^DC{VID+L%$~@RYv} z+K~M `}p2?)%e@v7iE|FNTB{`i0Ob9OL@ zEf3pwSgMlxe=saCI34z{Vd)n$9|Hi0?0*f*#{f_KIf~(KpX(I$R1CL 4aO`*-rbF{iRKmJB5)XDcc{LpS(!c}s5 zm;8clh@O7&d+0XE%69MRFS5Qy$np3@CvWPn$^4GX0Q&CJiSf=G0Usbjs!*L7AMO9~ zBTcfaZANPW_3_qr|2V`OS=>_|9t~FAp~D->!nEj!o+?7p_prDBn$9hkxJ}Ee&zjC^ z!{-VDd5~~HB(!Y;iBjncLO`6@Y`2#5xCiM3`msQJM~fP;*93GSth4c0_-CyEhtYKm zDI?|2(U^?dz~>*s1o8J7q0 7I+?;Md@k@}tf_D4{ z=nC7iDMeuugtO{I)bn)ofCdmP{SFY6mY|@~r$~^yKmPN!67XMI>dU6iLw1e*7(|fY z$8X(sTBXmP(fGaCI8hi1Ee?9w0g^~J79&6|Q4|O)8{9fiqnL1P<5n)w9E8&-D{gtR zu+K=2-j7 EiYW?3i?MZAo4<3G^#*+?siGaekQxdj(5H^lVq{|i&FHfDezTJ}@o%yj8vj7% zle3X^0tMW{ Hxp$SfE(loWc$o1iX;Lz>|IK(`!1Xo)Q7p%-K-h5TSfTt*R-3MR CY0>babP~u-O=?@$yACWxCA)ZzYI}ju zv!sH@V`ZjmR>eS-n>tyQz*Oc=cGXOy^MK$dxfXkaVff*ld!GmRXYY;Km(^`g(!O=z zkmu9_Ym}tdR~6v27KdS;c#=vjz7{5}U;Z?3kp}qNaXw`eT*rr3`f9mEU`qRvtD&wN z(+Ld(-{*4!2!;*z8*U;DFvb`Gd1o`oDIsOQ7FfZ )Snu&`) zBhJI^F+mlOb+)JpA7ocUl`t14Bn&$)sj0!L={_gqcX=XeZ-1{)HaoJv7)H4~6hLo_ zY$p~O>WYI#M-%_xz)&<>iOozR9AG5K2%Dexez@-1DX$4e`b&d$!f!C|h rxCcHg~B>l@htcs Y&B zQf gmbGR^s&Lz(A6gt zvKl|cArqgb{GC`n(67rQYv12Z0#*^JN@`lrRl~nbWwW*6_@Kbs4StcoKk;~^gyfdn zTT+}KYG&=T -f)Y;O4vKFkP`OfI}vV|V5uiO~Fn#>_mI;HuOuIL+JJI7zS zmvwdeLWg-q5%u+F&*C}$4_3Lpo2ccT8;twy_p-^WjTplwJD!AXbPu>wbLsaP-Vlch zalHpMq04xo*0%=~D2TtrH|hl#g4>0u;GLTL7@#-S_&F8pZiS?5@;V$P4d{|!OuZ)! zaxr~2@4g8|@f|WOrqFwdTw{2%SupG?iD=TN11=Bn$1te~_L|yCLpko(0dt`v#8r2r z9xYVzhOiqk0A~3p&PIW8xFPgLOn^j;1Y xY#bMEPlmO6trakxYm{7G7_} ~&V$-3z#a(f?ugF^m9+I TcAYIzqFgMxuUCel_=Y)@)4k-OnZT8bTn%FNC_ zP;$wMOEE-{>v7$pVN!hp>KaJbGm1=M@aw|;z60OxKI}*7K|e;?e?p JMb!5x?$n k5 z3?>>Jr1|B2kE`a4cP~q9soz>a3YU|Qsz^OuOIgiz*n4Lkg6Mr;Arph&qB1RKKE>R% zy5+iU4Q+<(bocfl>Gfi8&iqoVd4mAympGKntDJ|Ay?0jaOJBZeAj#VWv8aTE91%CU zv%A17{@=dv@fhU>OuRV>0LNq AQSr~s zp4a=j^u9i+fvp{8Hi+fL_Lh<82bxHs6a|YjCR@y&M!@^{r`QKuzqmKh2t+=mv~->3 z93F16;zqtzw1Tm!k5Yoh8?F`|Z|G*hX7M CqqPxHvByK|Z9(FwRYi`ih91 zkocQEk_=v0iy3ykrC_CEQo~$lO;8M<0W34m&lFwwZITkk^dDLUO~sr4Ah;5igMKnX z16kZ*wbScQY` l$uc} F3@Sp@Rp|^L9lkJH z_#n8Rg4+dd!$V%8$;*Gi-Z0YFvJ=$2!;TUI^%Se~M(T0_RXogGlG^8>5L+06V#(4_ zSb0W>G5R_R3Ad;URmdTVK5l}pGXaH)gMcMZHv5d-x`;#$BvJ_Qt4T3Islp4_Q`|bj zpgVJ9Crq8k+p~kd6<#q>6i%=uB}0&-0c2$y74m6_i-Ul7)Xi~xf1|niqWWX_%Puwl z-_9!Bb>-%}qsq!zV~igE n-azvHg@nKKwCn z&_p0ZX;7g{B4dLPKHet4ed&5CYTGSNYy5*$!F_V^KG&mr&EP?P;)&<@G|!C+7X80X zj!d4&Q<6#~(Sr_Z2wbRyjFM(WAeFRaI;3Q}kQ5*iVPu9p{dgLwKnwVdYe#_no6r@& zMK&`Nr@oP;wPX#)E gY(>1FwBDX3pFBlv5F)f+a@Fk3mjm@VNs_~_Mp;7DkP+pW^N{DdCZua)| zoqM(S|Lna)n$k5Si$UI5ff=EhWu1tm5w_Ex&ALW@ QzZ|{zC9>RCEFr oXHvB *<3OuDEHLW`jhe8s3x&`GNG^mzQk>{F z!9yj^P^R??ILD+smQQu4? O KN7RaatpkGf^MzRlE)N1VA&@OH(0xPa}SHrg;WjY^@&DYTb4MRS#&QGk&v z%2{uis0$e7U_$DXdX4#L!-agpN(pcHyePm@Vh$w1QuAljBJHE)J*m*_Uc&UN{JCKb zUN+P-vOq&l(JRO++o|HFCRXuPwrdD=5gS4ZgfC(%E6vzo>64|aQveWSvSp$gM2r6? z(lxWXx9J%4V_|^^DPi0EY>-R_n9Altz=KB>iYk!j>yfef#+Q3W)jY?~)O)_l4)=V! z0mSqd%Wx$U59?xnDK{fYjq=Q$QmA(!n=$f?^^U6jp`nFlqrcP@t+)VVOPQ4UtI%>{ zV+&MJYT1Kiiko;rDmp@pDYgniZH0yY?cZq931P{aN3XGDoQV+APH5QJ;9~@hRO%$i zZ_8?~lcu*Iv$4VK8oh;YW1WjqS^T;Sl@<-Zq!UO;j6ie}WVfv|XgD-qW%Nk{wLtU> zsq!2)B{T^o62vo3)*;#p5f+YQP1ZL!hKis8i>9(rfoE(CZD&3MQOQAx3QQ0q3u)8{ zQ8>2JZu|#utv( l5K#tU0hKpP_WP_R4-A#!a%e h{Iy z)%J%k&R=bGH?MqO;RZi@?x{^UD=HkfSp1|)+VD9CCNLBGkv7gp+!vM_+gM*{XaX;| zG%JWliv7(kq`!h|7?OGr1@{OJLt^yaN1eC7iD)aFb@g`5H4J)CGD#|Pz=ECrJsJ+M z;mwOam5Mu_qhR>rHAWvqv=-HZ+tkWvNlF`ejZ~R7PNI_ul4m9z=B0-v#Gr}HUka!O z5q*B| iV*U7`#~>x1rkUPjoaw`^F#Fl@{KRNTkqGE zp@EzmVL4yl05bORND^s7aERN-SAv5TjEzMxDa1m*eJi$eaFFxy5om8m?#BPoG3tOk z)0T>ZNt;X}C+H$rKeTN*aEnr}1ffP>MLqDgHw9v3z%`CR1UUjOy<{$334i^6bB3Qq zsH+m9*{DctRLyc7@@nCbW`Bm_zC&anpm $hCvi>f!`lay4pF#jL&bVt*ATfG-b+#Nedb9d z(m$s^ `_hBkLMr7%Kb(&hU}4Dfy=d{hMHZJbBs-m5U}(PrKCA{} zZPjEa#3*xy;;80`OX?}b FrBpBh<$A|Pd#Bq>`^ihY;=Z@nl2}i+yqn7sj|#d zusGd4@vNuN$-B*kz7@JNF5gl|Xy))ke;r&oMZw^7*A85ttVA7EbIN
xykz{3y z^>m%?RUUk2yrMDl-UU)nUyrsk)*ZjQYqO%UPhS-t^V>%}=I{3aPkBXX7yCbBi_5Iu z-oC-MH~8sys%5v5Dkh-b7IKQ#Q_miFRqawxJz-kos)TH#26kC%qm0o#(&g;cXt&+Utnmc!Ox>bZ>vs-?fdnR)OB>isGhA7PKeWr{=V**zFi7h;hqVtL0b<& z?hf<)bw9?3Q@a;1Db46tRyrG~1q9rj^jFq6&ryUq&gjg>AMUjrC2j dS>;NRKntv~j|j$n{*9t7{p>*!$Q z`3-fY+v|h3<=A0(x7X5Z!+D|sPRo?auwRi#uHcoG75%TC1m363-G~?N9!|@Q)9Q7A zYSEW36w2RzbB4@S1`ps;!<8mN4=#1L1qdBm8TJs3#D&5Rx*#L$p{_$5QPT&c{~?-z z&~e~I7*aAg1Ms7OP|L! GpeEBt)X0`+lkb!2kARv11!`VQp8vM+jw0%^LTaH%R2i?#Ws|Vz*_9R0a z13h^VURu@)HYO=K>6`Lh!Ex*d*Jghlevnv;>3(i~ 5=oMy1aS)RI|DBItRXl7{>aft$ZRHaK?3jW8dg$ut#4R?HaPrGer`T8G>riGjwHS z*iTIOT09adnHHWOBkFg3?JJCqvZCQQJO*P~-@fVIKrvU`MUTgR`ihi;#3hsa@RXT= z&Q8LQ5Yg8iS62%}!cy0sX=x$KJT?UqRtJfj%y2xoUEHs2OW=r6i6Ok9t%AmG=>uUs zqo*!!P&U_i7&o;-G*>jz%;7L%>JE-DTOVJy3*`3{j=cY4Wg7es$VN}q-q40;hfKFp zYeza#Rh A;pYKr%qp=?DT1m=^ebq$B~hd zo`sWk1gW1MH$+Uq4%O)Sh0svWlAEVV)bVVO!k0(4pxlRT6Lwfo;9*sEvtv|h{;znX zsie)#&9oM{TkE`c2Ob%B-F5yVBa*kY;Bm3cNY_twblR4(2cc#g%SIwytrX =(%GCYn?q2WpZ)wkMeO;oX&qB56?b!SR^3|){hY4nn zeIFGuW*F+$82R$G=*?=9ou}F9pRH}5iCdn%py7jwOC&C*CH&!LW79Pl8R5(RjedF6 z+h+pU^A+f8y;uCJj9Vz* zym>P+IVmk4fDCVsf-Lo~N{%pzUt3$dZZ*!sW|b; zNet8g@*f8H;;F<{ebDRQ2$B!|YV+_MK6_<~55oovm;`_M$B?kqw4%3RuIx#^gMSaW zE?Qr5J7^!?oTfs xS+vrA#PqTJI})nmHT5Kr@5zM%n5PVUJe+5`CW4K z3fTr5_@FCkD2_6-n>H)>#5b;2!bvWxJ_4L%ep%+kt ~n*ZurVUq$-Z*@0UAXQ t6@9`OYh{oNT~IWfcr&oqc=eqe0NZ|pCgn~Utf27#ksJ4WZHqSxM*al znyJnl%@9{JOqKVDVKcF9*~L^~HNpIO)z0z?6QrWYJul(u?Y-I39e`Q6P$kRGUrP|o z{HjnL`*PPLG$(_zx7F?7^6zha$0Ypp30Hq?1|;maRY6ESNUTGo@vEyQUmq@P9yZ#D z{)xxZrYIaHZnH(2n=Snq%@Pmh*!|uSj&+S5IZ&$Lc3_)JDK||iG3NlP(;w8Ao|~Nw zYiar2lSpw|P_)UFs7)#B;lbP9?hn6J@fn&|X>Da?c6+ul^8LHyn??P2PPYC(2U=&J z8*JQV*JyBY#a}XW81McObf^X^Sc->>+}S^YY^D%w`kFpOwZBI|otNwBl*--)M zZ6d-4Z6LObgti;L_siy0nt%s05MEDzU<5=UGM?_IMEHp;_)=M_Sf6&qU|lX&aj|vL zB5EVgTHJS_h)FO?h@LilV`-0@qm5Bg1*nXIsYy}H4ZfjCEWZA!sZ`8jpap@k`QTpF zG#9w4e8zUD&S4Wl#LhsRuOv+xi3?Be)_rvcnmYoaY!N99(_IjoOCFGG7yuCw#Vw$p zCGIM;HP}6g51VzT<>Xp-nnIefUKPXi7l?(|vs6>+K#2OJC19YPq`d9^MULyd^-waM zNFwOz^A~_pN0cKaN0EhUVk~E>$lvH?rFG=iEe9Vbp4>L=M-rR$DB&0Ln!sX7$!lEw zFP4t9EjUtQ??wGRRmOe_zd(YYXjMGO)ciy)P}h4wOJs) N^;Mv09ba?Av0g7&9BMvUm sUrdA+)nOfB@(|~-0f1d~%?DPD2L-8zIQYbYEg<9DXac{M z#r5;pf%ULGWYV|QVLj47tmj@~;}3eIlUSJ{k<$CmU4<8pAoAH6&Fsv5j6h=)b_6aX zA4(+%h17_Ag4qS=W1QbVaX?oULno(C0%p~?Qoq2|YX8Ivy(J#Tr5+4rW$_NZqUyq2 z(AKkdcVo$C$MwN65#X#+D3)J7qBkk{NT$FiA%}9iF6 PKjOhw~ literal 0 HcmV?d00001 diff --git a/docs/features.md b/docs/features.md deleted file mode 100644 index 7310b805..00000000 --- a/docs/features.md +++ /dev/null @@ -1,158 +0,0 @@ -# Features - -English · [简体中文](features.zh-CN.md) - -## Input - -- **Ghost suggestions** — your history completes the whole line as you type; → to accept -- **Explained tab completion** — every flag and subcommand with its description, for ~100 common commands; when tty7 has nothing to offer the Tab falls through to your shell's own completion, and the whole feature can be turned off (Settings → Input → Prompt, or `tab_completion` in `config.json`) -- **Syntax highlighting** — as you type, nothing to install -- **Fuzzy history search** — ⌃ R shows what you ran, where, and whether it failed; turn it off (Settings → Input → Prompt, or `history_search` in `config.json`) and ⌃ R goes to your shell instead, so an fzf / percol binding keeps working -- **History from day one** — your existing shell history works as-is and carries across sessions -- **Line editing** — click to place the caret, mouse selection, word motion, undo -- **Multi-line editing** — wrapped and multi-line commands edit in place; the grid shifts to keep the caret visible. ⇧ ⏎ · ⌥ ⏎ insert a newline instead of submitting (rebindable as `InsertNewline`); a plain ⏎ submits the whole buffer - -## In the window - -- **Tabs & splits** — always open in the current directory -- **Rearrange splits by dragging** — hover a pane and a small grip appears along its top edge; drag it over the layout to put the pane somewhere else in the tab. Dropping on a pane's side goes in beside it — taking an equal share of the row or column it joins, or splitting that pane in half when the side faces across the layout rather than along it — dropping on its middle trades the two panes' places, and carrying it past a pane's outer side — the one facing the window rather than another pane — makes it a full-width or full-height band beside everything else, sized to an even share of what that side already holds — so a pane in the middle of a 2×2 becomes a full-height third column in one drag. The landing lights up while you drag, and only ever lights up when the drop would really change the layout -- **Repo-grouped sidebar** — the left tab sidebar groups rows under a header per git repository, non-repo tabs in a trailing *Scratch* section; branch switches and in-repo `cd`s never move a row (`sidebar_grouping` in `config.json`: `repo` default, `none` for a flat list) -- **Command palette** ⌘ P · scrollback search ⌘ F -- **⌘/Ctrl-click links** (⌘ on macOS, Ctrl on Windows/Linux) · desktop notifications · copy on select (opt-in, Settings → Input → Selection & clipboard) -- **Smart double-click selection** — double-click grabs the whole URL, file path, bracket/quote pair, or dictionary-segmented CJK word under the cursor; Shift-click extends a selection (toggle in Settings → Input → Selection & clipboard; word separators via `word_separators` in `config.json`) -- **Nine themes, plus your own** — YAML seed themes with solid, gradient, or image backgrounds; iTerm2 `.itermcolors` import; in-app color editor with a background-image picker -- **Sync with system** — Settings → Appearance; pick separate light and dark themes and tty7 follows the OS appearance live (`theme_follow_system`, `theme_preset_light` / `theme_preset_dark` in `config.json`) -- **Window opacity & blur** — Settings → Appearance → Transparency; applies to every theme, *Follow theme* returns to the theme's own `opacity` / `blur` -- **CJK / IME input** -- **Windows Explorer menu** — the installer offers *Add “Open in tty7” to the folder context menu* as a setup task, off by default, and the uninstaller always takes it back out. Writing shell verbs is an install-time decision, so there is no runtime setting; a portable-zip install can do it itself with `tty7-app.exe --register-explorer-menu` (or `--unregister-explorer-menu`). Either way the keys land under `HKCU`, so only your own Windows account is affected - -## Fonts - -- **Hack is bundled** — it ships inside the binary, so the default renders identically everywhere without relying on a system install -- **Primary + ordered fallbacks** — `font_family` and `font_fallbacks` in `config.json`; optional `font_family_bold` / `font_family_italic` for distinct faces, and `font_features` to pass OpenType features through (contextual ligatures stay off unless you ask for them) -- **Platform-aware defaults** — the fallback list names faces the host OS actually ships (PingFang SC / Apple Color Emoji on macOS, Microsoft YaHei / Segoe UI Emoji on Windows, Noto on Linux). Those stock names are appended to a hand-written list too, so a `config.json` written on another platform still resolves - -### CJK and the two-column grid - -A cell is one advance of the primary face, and a wide (CJK) character is pinned -to exactly two of them. A CJK fallback therefore sits flush in its slot only if -its ideographs advance **twice** the primary's Latin advance. - -Bundled Hack advances 0.60205em, so a two-column slot is 1.2041em — while every -stock CJK face (Microsoft YaHei, PingFang SC, Noto Sans CJK) advances 1.0em. -Those glyphs get left-aligned in the slot and the leftover ~0.2em lands as a gap -on the right of every character. - -[Maple Mono NF CN](https://github.com/subframe7536/maple-font) is tried first on -every platform for exactly this reason — 0.6em Latin, 1.2em CJK, an exact -two-cell fit against Hack. It is referenced by name only, never bundled (~20MB -per weight): install it and tty7 picks it up with no config change. - -For CJK set *tight* rather than merely even, change the primary face instead — -one that advances 0.5em (Sarasa Mono SC, say) makes two columns exactly 1.0em. - -## Coding agents - -tty7 recognizes third-party coding agents running in a pane (Claude Code, -Codex, Gemini CLI, Aider, Amp, OpenCode, and 12 more) and adds around them — -it never wraps or replaces the agent. - -- **Brand avatars** — the tab chip / sidebar row shows which agent runs where; custom wrappers map in via `agent_commands` in `config.json` -- **Status dot** — working (blue) / needs your input (amber) / done (green), driven by agent-reported events over an OSC channel; Settings → Agents installs the hooks that feed it (Claude Code, Codex, Copilot CLI, OpenCode, Pi, Grok Build, Oh My Pi) -- **Notifications** — "needs your permission…" the moment an agent blocks on you, and "finished after Ns" per turn, honoring your notification policy -- **Branch at a glance** — each sidebar row shows its pane's git branch and working-tree diff (`+N −M`), refreshed on `cd` and when a command finishes; clicking the counts opens the diff overlay, and turning that off (Settings → Window & Tabs, or `sidebar_diff_preview: false` in `config.json`) keeps the readout while making it non-clickable -- **Session resume** — panes lost to a reboot re-launch their agent conversation on restore, carrying the original launch flags (`claude --dangerously-skip-permissions --resume …`) (`restore_agent_sessions`, on by default) -- **Fork session** — branch a live agent conversation into a second, independent one by shelling the agent's own fork command (`codex fork `, `claude --resume --fork-session`, also OpenCode, Grok Build, and Oh My Pi); the original is untouched and both continue separately. Right-click a pane to pick a split placement, or right-click the tab / sidebar row to open the fork in a new tab. Needs the agent's hooks installed, since the fork targets the session id they report; a remote pane can't fork, because the command would run against the local agent — and note a fork copies the whole transcript, so repeated forking costs real disk in the agent's own session store -- **Copy Session ID** — put the agent's native session id on the clipboard, beside *Copy Working Directory*, for pasting into `codex resume`, a bug report, or another tool -- **Context feed** — palette commands send the current selection or the repo's `git diff` to the running agent as a ready-made prompt -- **Tray icon** — a system tray / menu bar item that flips to an attention state the moment any agent needs your input; its menu lists every agent pane (brand avatar + status dot, click to reveal), switches the notification policy, and offers *Quit and Stop Server…* alongside the plain session-keeping quit (`show_tray_icon`, on by default) -- **`tty7 wait`** — the CLI's orchestration primitive: block until a pane's agent needs input or finishes its turn (`tty7 wait %3 --until waiting,done --changed --timeout 600`, exit 124 on timeout), so one agent can sleep until its peer blocks on a permission prompt instead of screen-scraping — then `tty7 capture %3 --plain` to read the result. The agent status is a level, not an event, so `--changed` ignores the state the pane was already in when the wait began; without it, the JSON's `stale` flag says whether the answer might belong to the previous turn -- **`tty7` on PATH** — the CLI ships inside every installer and is put on PATH at launch, so a script or a coding agent can drive tty7 from any terminal. Inside a tty7 pane it works regardless, since panes inherit the app's environment. On Unix it is a symlink into whichever of `/opt/homebrew/bin`, `/usr/local/bin`, `~/.local/bin`, `~/bin`, `~/.cargo/bin` your PATH already covers; on Windows the install directory is appended to your user PATH, and the uninstaller takes it back out. A `tty7` you installed yourself is left alone, never replaced. Off via Settings → Agents or `install_cli_on_path: false` in `config.json` - -## SSH - -A native Rust SSH stack (russh) is the **only** path — profiles, credentials, -and SFTP without shelling out to `ssh`. There is no system-ssh compat mode. - -- **QuickConnect** — type `user@host[:port]` in the palette and connect; IPv6 `[::1]:port` supported -- **Saved profiles** — full connection config with passwords / passphrases in the OS keychain, never on disk -- **`~/.ssh/config` aliases** — type one to connect (resolved natively — common fields, best-effort — over russh), or import them as profiles in Settings -- **GUI auth** — in-pane sheets for password, key passphrase, 2FA, and host-key confirmation (new vs. changed) -- **Built-in SFTP** — a slide-in file panel: browse, upload / download, rename / delete / chmod, drag to Finder -- **Port forwarding** — Local / Remote / Dynamic, preconfigured or added live, plus ⌘/Ctrl-click `localhost:PORT` to auto-forward -- **Jump hosts & proxies** — multi-hop via profile references or `ProxyJump`, ProxyCommand, SOCKS5 / HTTP - -| Entry point | Connects via | -|---|---| -| Saved profiles · QuickConnect · typed `user@host[:port]` | Native russh — SFTP · keychain · GUI auth · L/R/D forwards | -| `~/.ssh/config` aliases | Resolved natively, then russh (`Match`/canonicalize/GSSAPI unsupported — no fallback) | - -## Keybindings - -Keys are shown in macOS notation — on Windows and Linux, read ⌘ as -Ctrl. The essentials: - -| | | -|---|---| -| ⌘ T · ⌘ W · ⌘ ⇧ T | new tab · close tab · reopen closed tab | -| ⌘ 1…⌘ 9 | jump to tab 1–9 | -| ⌃ ⇥ · ⌃ ⇧ ⇥ | hold to walk the switcher forwards · backwards; it commits when you let go | -| ⌘ D · ⌘ ⇧ D | split right · split down | -| ⌘ ] · ⌘ [ | next pane · previous pane | -| ⌘ ⌥ ←→↑↓ | focus the pane in that direction | -| ⌘ ⏎ · ⌘ ⇧ ⏎ | toggle fullscreen · zoom pane | -| ⌘ K | clear scrollback | -| ⌘ P | command palette | -| ⌘ F | search the scrollback | -| ⌃ R | fuzzy-search shell history | -| ⌘ + · ⌘ − · ⌘ 0 | font size up · down · reset | -| ⌘ + wheel | zoom the font by scrolling over a terminal | - -**Settings → Keybindings** (⌘ ,) lists every shortcut. Click one, -press the new keys (Esc cancels, Backspace resets to -default), and it takes effect immediately. Pane resize and swap have no default -keys — bind them here or run them from the command palette. - -**tmux preset** — remaps pane/tab actions onto a prefix (default ⌃ B): -⌃ B C opens a tab, ⌃ B % splits, -⌃ B then an arrow moves focus. A bare prefix reaches the shell after -a brief pause; `prefix` + an unbound key passes straight through. - -## Performance notes - -- The PTY is read at device speed and parsed in large batches, off the render path -- Hot paths are lock-free — a big `cat` never waits on drawing -- The server buffers up to 16 MiB ahead of the window before backpressure applies - -## macOS privacy - -Panes are forked from the bundled executable, so macOS attributes a program's -request for a protected resource to tty7.app. tty7 declares the matching TCC -usage strings (camera, microphone, contacts, calendar, reminders, photos, -location, local network, Bluetooth, speech recognition, Apple Events, system -administration) so that program gets the normal one-time prompt instead of -being denied outright with no prompt at all. - -Not covered by usage strings: - -- **Full Disk Access** — Apple defines no usage-string key for it. Reaching - `~/Library/Mail`, `~/Library/Messages`, `~/Library/Safari` or - `~/Library/Containers` needs a manual grant in System Settings. - -Declaring a usage string is not the same as holding the permission: tty7.app -itself is granted none of these resources. Every prompt you see belongs to -whatever you ran in the pane, and you can revoke it under Privacy & Security. - -## Localization - -The GUI ships English, Simplified Chinese and Japanese strings. Pick one in -Settings → Appearance → Language, or in `config.json`: - -```json -{ "gui_language": "zh-CN" } -``` - -`en`, `zh-CN` and `ja-JP` are the only accepted values; anything else falls back -to `en`. -The choice is explicit — the system language is never inferred. CLI output stays -English so agent and script integrations keep a stable, predictable surface. diff --git a/docs/features.zh-CN.md b/docs/features.zh-CN.md deleted file mode 100644 index abeda9e7..00000000 --- a/docs/features.zh-CN.md +++ /dev/null @@ -1,150 +0,0 @@ -# 功能 - -[English](features.md) · 简体中文 - -## 输入 - -- **影子建议** —— 边打字边用你的历史补全整条命令,→ 接受 -- **带说明的 Tab 补全** —— 每个 flag、每个子命令都带说明,覆盖约 100 个常用命令;tty7 没有候选时 Tab 自动交给 shell 自己的补全,整个功能也可关闭(设置 → 输入 → 提示符,或 `config.json` 里的 `tab_completion`) -- **语法高亮** —— 边打边亮,什么都不用装 -- **模糊历史搜索** —— ⌃ R 看到每条命令在哪跑的、什么时候、有没有失败;关掉它(设置 → 输入 → 提示符,或 `config.json` 里的 `history_search`)后 ⌃ R 直接交给 shell,你绑的 fzf / percol 照常可用 -- **历史开箱即用** —— 你已有的 shell 历史直接生效,并跨会话延续 -- **行编辑** —— 点击定位光标、鼠标选区、词级移动、撤销 -- **多行编辑** —— 折行和多行命令原地编辑;网格自动上移,光标始终可见。⇧ ⏎ · ⌥ ⏎ 插入换行而不提交(可改绑,动作名 `InsertNewline`),单独按 ⏎ 提交整个缓冲区 - -## 窗口 - -- **标签页与分屏** —— 永远开在当前目录 -- **拖动重排分屏** —— 鼠标移到某个 pane 上,它顶边中间会浮出一个小抓手;拖着它在布局里走,就能把这个 pane 挪到标签页内的别处。落在某个 pane 的某一侧=插到它旁边:那一侧要是朝着同一排的邻居,就并入那一排、和它们等分;要是横着切过这一排(没有排可并),才是把那个 pane 一分为二、自己占住那一半。落在它正中=两个 pane 互换位置;继续推到某个 pane 朝着窗口那一侧的外缘(不是朝着另一个 pane 的那侧)=变成贴着窗口某一边、跨满整行或整列的一条,宽度按那条轴上已有的份数均分 —— 2×2 里的一个 pane 一次拖动就能变成通高的第三列(各占三分之一),而不是独占半屏。拖动过程中落点会高亮,且只有当这一放确实会改变布局时才会亮 -- **侧栏按仓库分组** —— 左侧标签栏按 git 仓库分组、每组一个标题行,不在仓库里的标签归入末尾的 *草稿* 组;切分支、仓库内 `cd` 都不会挪动行(`config.json` 的 `sidebar_grouping`:默认 `repo`,`none` 恢复扁平列表) -- **命令面板** ⌘ P · scrollback 搜索 ⌘ F -- **⌘ 点击打开链接** · 桌面通知 · 划选即复制(可选,设置 → 输入 → 选择与剪贴板) -- **智能双击选中** —— 双击直接选中整条 URL、文件路径、括号/引号对,中文按词典分词出词;Shift 点击扩展选区(设置 → 输入 → 选择与剪贴板可开关;分隔符用 `config.json` 的 `word_separators` 配置) -- **9 套主题,也能自定义** — YAML 种子主题,背景支持纯色、渐变或图片;可导入 iTerm2 `.itermcolors`;应用内颜色编辑器带背景图选择 -- **跟随系统外观** — 设置 → 外观;分别选好浅色和深色主题,tty7 随系统深浅模式实时切换(`config.json` 中的 `theme_follow_system`、`theme_preset_light` / `theme_preset_dark`) -- **窗口透明与模糊** — 设置 → 外观 → 透明度;对所有主题生效,*跟随主题* 恢复主题自带的 `opacity` / `blur` -- **CJK / 输入法输入** -- **Windows 资源管理器右键菜单** —— 安装程序提供 *Add “Open in tty7” to the folder context menu* 这个安装任务,默认不勾选,卸载时一律移除。写 shell verb 是安装期的决定,所以没有运行时开关;用 portable zip 的话可以自己执行 `tty7-app.exe --register-explorer-menu`(或 `--unregister-explorer-menu`)。两种方式写入的键都在 `HKCU` 下,只影响你自己的 Windows 账户 - -## 字体 - -- **内置 Hack** —— 打包进二进制,默认配置在各平台渲染完全一致,不依赖系统安装 -- **主字体 + 有序 fallback** —— `config.json` 里的 `font_family` 和 `font_fallbacks`;可选 `font_family_bold` / `font_family_italic` 指定独立字面,`font_features` 透传 OpenType 特性(上下文连字默认关闭) -- **默认列表按平台分支** —— fallback 只写宿主系统真正自带的字体(macOS 用 PingFang SC / Apple Color Emoji,Windows 用 Microsoft YaHei / Segoe UI Emoji,Linux 用 Noto)。这些名字也会追加到你手写的列表后面,所以在别的平台写出来的 `config.json` 一样能落地 - -### 中文与两列网格 - -一个格子等于主字体的一个 advance,宽字符(CJK)被钉死在正好两格上。所以中文 -fallback 只有在**汉字 advance 等于主字体西文 advance 的两倍**时,才能严丝合缝地 -填满自己的槽。 - -内置 Hack 的 advance 是 0.60205em,两格就是 1.2041em —— 而系统自带的中文字体 -(Microsoft YaHei、PingFang SC、Noto Sans CJK)全都是 1.0em。这些字形在槽里左 -对齐,多出来的约 0.2em 就变成每个字右边的一道空隙。 - -[Maple Mono NF CN](https://github.com/subframe7536/maple-font) 在所有平台都排在 -第一位正是因为这个 —— 西文 0.6em、中文 1.2em,对上 Hack 正好两格。它只按名字引 -用,不打包(每字重约 20MB):装上即生效,不用改配置。 - -想让中文排得**紧**而不只是均匀,要换的是主字体:选一个 advance 为 0.5em 的 -(比如 Sarasa Mono SC 更纱黑体等宽),两格就正好 1.0em。 - -## Coding agent - -tty7 能识别 pane 里跑着的第三方 coding agent(Claude Code、Codex、Gemini CLI、 -Aider、Amp、OpenCode 等共 18 个)并在其外围加功能 —— 绝不包裹或替代 agent 本身。 - -- **品牌头像** —— 标签 chip / 侧栏行显示每个 pane 跑的是哪个 agent;自定义包装命令可通过 `config.json` 的 `agent_commands` 映射 -- **状态点** —— 工作中(蓝)/ 等你输入(琥珀)/ 完成(绿),由 agent 自己上报的 OSC 事件驱动;在 设置 → Agents 一键装好对应 hooks(Claude Code、Codex、Copilot CLI、OpenCode、Pi、Grok Build、Oh My Pi) -- **通知** —— agent 卡在等你批准的那一刻弹 "needs your permission…",每轮结束弹 "finished after Ns",遵循你的通知策略 -- **一眼看分支** —— 侧栏每行显示该 pane 的 git 分支和工作区改动(`+N −M`),`cd` 或命令跑完时自动刷新;点改动数字会打开 diff 浮层,关掉它(设置 → 窗口与标签页,或 `config.json` 的 `sidebar_diff_preview: false`)分支和数字照常显示,只是不再可点 -- **会话恢复** —— 重启后无法重连的 pane 会自动续上 agent 对话,并带上原始启动 flags(`claude --dangerously-skip-permissions --resume …`;`restore_agent_sessions`,默认开启) -- **Fork 会话** —— 直接调 agent 自己的 fork 命令(`codex fork `、`claude --resume --fork-session`,OpenCode、Grok Build 和 Oh My Pi 同样支持),把当前对话分叉成一个独立会话;原会话原封不动,两边各自往下走。在 pane 上右键可选择分屏位置,在标签 / 侧栏行上右键则直接开新标签。需要先装好该 agent 的 hooks(fork 认的是 hooks 上报的 session id);远程 pane 不能 fork,因为命令会跑在本机的 agent 上;另外 fork 会整份复制对话历史,反复 fork 会在 agent 自己的会话目录里占掉不少磁盘 -- **复制会话 ID** —— 把 agent 的原生 session id 复制到剪贴板,就在 *复制工作目录* 旁边,方便粘进 `codex resume`、bug 报告或别的工具 -- **上下文回填** —— 面板命令把当前选区或仓库 `git diff` 打包成 prompt 直接喂给正在跑的 agent -- **托盘图标** —— 系统托盘 / 菜单栏常驻图标,任何 agent 等你输入时立即切换为提醒态;菜单列出所有 agent pane(品牌头像 + 状态点,点击直达)、可切换通知策略,并在保留会话的普通退出之外提供 *退出并停止服务器…*(`show_tray_icon`,默认开启) -- **`tty7 wait`** —— CLI 的编排原语:阻塞到某个 pane 的 agent 等待输入或完成一轮(`tty7 wait %3 --until waiting,done --changed --timeout 600`,超时退出码 124),让一个 agent 睡到同伴卡在权限确认的那一刻,而不是抓屏猜——然后 `tty7 capture %3 --plain` 收结果。agent 状态是电平不是边沿,所以 `--changed` 会忽略 wait 开始时 pane 本来就处在的那个状态;不加它的话,JSON 里的 `stale` 标记会告诉你这个答案是不是上一轮留下的 -- **`tty7` 上 PATH** —— CLI 随每个安装包一起发布,启动时自动放到 PATH 上,脚本和 coding agent 在任何终端里都能驱动 tty7。tty7 自己的 pane 里则一定可用,因为 pane 继承 app 的环境。Unix 上是往 `/opt/homebrew/bin`、`/usr/local/bin`、`~/.local/bin`、`~/bin`、`~/.cargo/bin` 中你 PATH 已经覆盖的那个目录里放一个软链;Windows 上是把安装目录追加到用户 PATH,卸载时再摘掉。你自己装的 `tty7` 一律保持原样,不会被覆盖。关掉:设置 → Agents,或 `config.json` 里 `install_cli_on_path: false` - -## SSH - -**唯一**路径就是原生 Rust SSH 栈(russh)—— profile、凭据、SFTP 全部内置, -不 shell 出 `ssh`,也没有系统 ssh 兼容模式。 - -- **QuickConnect** —— 面板里打 `user@host[:port]` 回车即连;支持 IPv6 `[::1]:port` -- **保存 profile** —— 完整连接配置,密码 / passphrase 进 OS keychain,不落盘 -- **`~/.ssh/config` alias** —— 直接输入 alias 即连(原生解析常用字段,尽力而为,走 russh),也可在设置页一键导入为 profile -- **GUI 认证** —— pane 内 sheet 输入密码、私钥 passphrase、2FA,并确认主机密钥(新主机 vs 已变更) -- **内置 SFTP** —— 滑入式文件面板:浏览、上传 / 下载、重命名 / 删除 / chmod,可拖进 Finder -- **端口转发** —— Local / Remote / Dynamic,预配置或运行时增删,外加 ⌘ 点击 `localhost:PORT` 一键转发 -- **跳板与代理** —— 经 profile 引用或 `ProxyJump` 多跳、ProxyCommand、SOCKS5 / HTTP - -| 入口 | 连接方式 | -|---|---| -| 保存 profile · QuickConnect · 输入 `user@host[:port]` | 原生 russh —— SFTP · keychain · GUI 认证 · L/R/D 转发 | -| `~/.ssh/config` alias | 原生解析后走 russh(`Match`/canonicalize/GSSAPI 不支持,且无回退) | - -## 快捷键 - -下表按 macOS 记法书写 —— 在 Windows 和 Linux 上,把 ⌘ 读作 -Ctrl。最常用的几个: - -| | | -|---|---| -| ⌘ T · ⌘ W · ⌘ ⇧ T | 新建标签页 · 关闭标签页 · 恢复关闭的标签页 | -| ⌘ 1…⌘ 9 | 跳到第 1–9 个标签页 | -| ⌃ ⇥ · ⌃ ⇧ ⇥ | 按住不放在切换面板里向后 · 向前走,松手即切换 | -| ⌘ D · ⌘ ⇧ D | 向右分屏 · 向下分屏 | -| ⌘ ] · ⌘ [ | 下一个窗格 · 上一个窗格 | -| ⌘ ⌥ ←→↑↓ | 按方向切换焦点窗格 | -| ⌘ ⏎ · ⌘ ⇧ ⏎ | 切换全屏 · 缩放窗格 | -| ⌘ K | 清除 scrollback | -| ⌘ P | 命令面板 | -| ⌘ F | 搜索 scrollback | -| ⌃ R | 模糊搜索 shell 历史 | -| ⌘ + · ⌘ − · ⌘ 0 | 字号增大 · 减小 · 重置 | -| ⌘ + 滚轮 | 在终端上滚动缩放字号,演示时随手放大 | - -**设置 → 按键绑定**(⌘ ,)列出全部快捷键。点一行、按下新键即可 -(Esc 取消,Backspace 恢复默认),改完立即生效。窗格缩放与 -交换默认不绑定键 —— 在这里绑定,或从命令面板执行。 - -**tmux 预设** —— 把窗格/标签页操作映射到前缀键(默认 ⌃ B): -⌃ B C 新建标签页,⌃ B % 分屏, -⌃ B 接方向键切换焦点。单独按前缀键会在短暂延迟后送达 shell, -`前缀` + 未绑定的键原样透传给终端。 - -## 性能说明 - -- 以设备速度读取 PTY,在渲染路径之外成批解析 -- 热路径全程无锁 —— 再大的 `cat` 也不会阻塞在渲染上 -- 触发背压前,服务器最多可领先窗口缓冲 16 MiB - -## macOS 隐私 - -窗格是从 app bundle 里的可执行文件 fork 出来的,所以程序申请受保护资源时, -macOS 会把这次请求算到 tty7.app 头上。tty7 声明了对应的 TCC usage strings -(摄像头、麦克风、通讯录、日历、提醒、照片、定位、本地网络、蓝牙、语音识别、 -Apple Events、系统管理),这样程序才能正常弹出一次性授权窗口,而不是连弹窗都 -没有就被直接拒绝。 - -不受 usage strings 覆盖的: - -- **完全磁盘访问** —— 苹果没有为它定义 usage-string 键。要读写 - `~/Library/Mail`、`~/Library/Messages`、`~/Library/Safari` 或 - `~/Library/Containers`,需要在「系统设置」中手动授权。 - -声明 usage string 不等于持有权限:tty7.app 自己一项都没有拿到。你看到的每个 -授权弹窗都属于你在窗格里运行的那个程序,也可以在「隐私与安全性」中撤销。 - -## 本地化 - -GUI 目前提供英文、简体中文和日文三套文案。在「设置 → 外观 → 语言」中选择,或直接改 -`config.json`: - -```json -{ "gui_language": "zh-CN" } -``` - -只接受 `en`、`zh-CN` 和 `ja-JP` 三个值,其它值一律回落到 `en`。语言必须显式指定,不会 -去猜系统语言。CLI 输出保持英文,保证 agent、脚本和开发者工作流的输出稳定可预测。 diff --git a/docs/getting-started/concepts.mdx b/docs/getting-started/concepts.mdx new file mode 100644 index 00000000..1f6bb2ec --- /dev/null +++ b/docs/getting-started/concepts.mdx @@ -0,0 +1,108 @@ +--- +title: "Core concepts" +description: "Workspaces, tabs, panes — and the background server that owns them all." +--- + +Four words explain most of tty7. Three of them you can see; the fourth is the +reason the other three survive a reboot. + +## Pane + +A **pane** is one terminal: one shell (or one program) attached to one PTY. It +is the only thing in tty7 that actually runs something. + +Panes have stable ids — `%42` — for their whole life. That id is what the +[CLI](/cli/overview) addresses, and what `$TTY7_PANE` holds inside the pane +itself. + +## Tab + +A **tab** is a layout of panes. One pane to start with; split it and the tab +holds two, arranged in rows and columns you can drag around. + +Tabs appear in the sidebar (or the top strip, if you move it there). A tab's +label is the best evidence tty7 has: a name you set, else the coding agent +running in it, else the last segment of its working directory. + +## Workspace + +A **workspace** is a named set of tabs — a project, usually. One window shows +one workspace at a time, and ⌘ ⇧ O opens the switcher to move between +them or open a second window on another one. + +Workspaces are how tty7 keeps ten repositories from becoming forty +indistinguishable tabs. They also travel: a workspace on a remote machine is +still a workspace, opened from the same switcher. + + + + + +## The server + +Here is the part that matters. **The window does not own your shells — a +background server does.** + +Quitting tty7 closes the window and leaves that server running. Your build keeps +building, your agent keeps working, your SSH session stays up. Open tty7 again +and it reattaches to exactly what was there. + +This is also why: + +- **`tty7` works from any terminal.** The CLI talks to the same server. The GUI + does not have to be running at all. +- **A crash is not a catastrophe.** Panes come back showing what was on them: + a capped tail of each pane's output is kept on disk and handed to the pane + that reopens on its id. +- **Stopping is explicit.** *Quit and Stop Server…* in the tray menu is the only + ordinary way to end everything, and it warns you first. + +
+ Restarting the server ends every process in every pane on that machine — + shells, agents, and SSH sessions alike. Layouts are kept and come back with + fresh shells. Never do it on someone else's behalf without asking. + + +### What survives what + +| | Close a tab | Quit tty7 | Stop the server | Reboot | +|---|:--:|:--:|:--:|:--:| +| The shell keeps running | ✗ | ✓ | ✗ | ✗ | +| The layout comes back | ✗ | ✓ | ✓ | ✓ | +| What was on screen comes back | ✗ | ✓ | ✓ | ✓ 1 | +| A supported agent session resumes | ✗ | ✓ | ✓ | ✓ | + +1 A capped tail of each pane, restored once. See +[session restore](/reference/troubleshooting#panes-came-back-empty). + +## Machines + +Everything above exists per **machine**. Your laptop is one; a dev box you +connect to over SSH is another, with its own server, its own workspaces, and its +own panes. + +The switcher lists them together, and the CLI reaches them with `-m`: + +```bash +tty7 -m devbox ls +``` + +Remote panes run on the remote machine — the files, the repository, the git +data, and the process tree are all over there. +[Remote workspaces →](/remote/workspaces) + +## The three environment variables + +Every pane exports these, and anything you launch from one inherits them: + +| Variable | What it holds | +|---|---| +| `TTY7_PANE` | This pane's id — the default target of `tty7 split`, `send`, `capture`, `procs`. | +| `TTY7_WS` | This pane's workspace id. | +| `TTY7_CONFIG_DIR` | The config directory, which is how the CLI finds the right server. | + +`echo $TTY7_PANE` is the fastest way to tell whether you are inside tty7 at all. + ++ Those ids are the whole interface. The CLI page starts there. + diff --git a/docs/getting-started/first-launch.mdx b/docs/getting-started/first-launch.mdx new file mode 100644 index 00000000..cb83ceb7 --- /dev/null +++ b/docs/getting-started/first-launch.mdx @@ -0,0 +1,126 @@ +--- +title: "First launch" +description: "The handful of settings worth changing before you start working." +--- + +Open tty7 and you get a window with one tab and one shell, and a tab sidebar +down the left. Everything below is optional — but these are the settings people +end up changing anyway, so they are worth five minutes now. + +Open Settings with ⌘ , (Ctrl , on Windows and Linux), or +from the command palette (⌘ P → *Settings*). + + ++ + +## 1. Pick a theme + +**Settings → Appearance → Theme.** Nine themes ship built in — Light, One Light, +Catppuccin Latte, Rosé Pine Dawn, Dark, Dracula, Harbor, One Dark Pro, and +Rosé Pine. The default is **Light**. + +Turn on **Sync with system** to pick a light theme and a dark theme separately; +tty7 then follows the OS appearance live. + +Transparency lives on the same page, under **Transparency** — opacity applies to +every theme, and *Follow theme* hands the decision back to the theme's own +setting. On Windows there is also a **Background material** picker (Mica, +Acrylic, and friends). + +[More about themes →](/customization/themes) + +## 2. Choose your shell + +**Settings → Terminal → Shell.** Leave **Program** empty to use the platform +default. Otherwise it takes an executable name on PATH or an absolute path +(`zsh`, `fish`, `pwsh`, `nu`, `/opt/homebrew/bin/bash`), plus space-separated +**Arguments** — `-l` for a login shell, say. + +**Start in** decides what a *fresh* shell opens in: tty7's launch directory +(the default), your home folder, or a fixed path. New tabs and splits keep +inheriting the active pane's directory either way. + +## 3. macOS only: decide what Option does + +**Settings → Input → Keyboard → Option (⌥) acts as Meta.** + +Off (the default), ⌥ B types `∫`, which is what macOS has always +done. On, it sends the escape chord shells expect, so ⌥ B moves back +a word and ⌥ ⌫ deletes one. Turn it on if you live in readline; +leave it off if you type accented characters. + +## 4. If you use coding agents, install the hooks + +**Settings → Agents.** tty7 detects 18 coding CLIs by process name on its own — +you get brand avatars and tab labels for free. The *status dots*, the "needs +your permission" notifications, and `tty7 wait` all need one more thing: a small +hook the agent calls to report what it is doing. + +Click **Install** next to Claude Code, Codex, Copilot CLI, OpenCode, Pi, Grok +Build, or Oh My Pi. It writes into that agent's own config directory and can be +removed from the same row. + +[More about agents →](/agents/status) + +## 5. Know what Quit does + +Plain **Quit** closes the window and leaves the background server running. +Your shells, builds, and agent turns keep going, and reopening tty7 reattaches +to them. + +To actually stop everything, use **Quit and Stop Server…** from the tray icon's +menu. It says so plainly before it does it: anything still running in your +shells is terminated, while your tabs and layout are kept and reopen with fresh +shells. + +
+ This is why there is no tmux in the picture. The persistence is not a feature + of your shell setup — it belongs to the server underneath. + [Core concepts →](/getting-started/concepts) + + +## 6. Tune the notifications + +**Settings → Window & Tabs → Notifications.** By default tty7 posts a desktop +notification when a foreground command that ran longer than 10 seconds +finishes — but only while the window is unfocused. Set **Notify on command +finish** to *Never* or *Always*, and move the threshold if 10 seconds is the +wrong number for your work. + +Agent notifications ("needs your permission…", "finished after 42s") follow the +same policy. + +## 7. Coming from tmux? + +**Settings → Keybindings → Preset → tmux** remaps pane and tab actions onto a +prefix, ⌃ B by default. ⌃ B C opens a tab, +⌃ B % splits, ⌃ B then an arrow moves focus. + +A bare prefix reaches the shell after about a second, and prefix plus an unbound +key passes straight through — so a tmux binding you did not remap still lands in +whatever is running. + +[More about keybindings →](/customization/keybindings) + +## Where things live + +| | macOS / Linux | Windows | +|---|---|---| +| Settings file | `~/.config/tty7/config.json` | `%APPDATA%\tty7\config.json` | +| Custom themes | `~/.config/tty7/themes/` | `%APPDATA%\tty7\themes\` | + +Everything in the Settings window writes to `config.json`, and you can edit it +by hand instead — see the [configuration reference](/reference/configuration). +Set `TTY7_CONFIG_DIR` to move the whole directory somewhere else. + +## Next + ++ diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx new file mode 100644 index 00000000..4f5f3e59 --- /dev/null +++ b/docs/getting-started/installation.mdx @@ -0,0 +1,151 @@ +--- +title: "Installation" +description: "Native builds for macOS, Windows, and Linux — plus building from source." +--- + +Every release publishes native builds on +[**GitHub Releases**](https://github.com/l0ng-ai/tty7/releases). There is no +runtime to install first: fonts are embedded in the binary, and the Linux +AppImage bundles its own X11/Wayland/font libraries. + ++ Workspaces, tabs, panes, and the server that owns them. + ++ Suggestions, completion, and history search — the part you touch most. + ++ + +## The `tty7` command + +Every installer ships the `tty7` CLI beside the app, and the app puts it on your +PATH the first time it launches. That is what lets a script — or a coding agent +in some other terminal — open panes and read them back. + +- **On Unix** it is a symlink into whichever of `/opt/homebrew/bin`, + `/usr/local/bin`, `~/.local/bin`, `~/bin`, or `~/.cargo/bin` your PATH already + covers. +- **On Windows** the install directory is appended to your user PATH, and the + uninstaller removes it again. + +A `tty7` you installed yourself — a `cargo install` build, a package manager's +copy — is never replaced. To turn the whole thing off, uncheck **Settings → +Agents → Install the tty7 command on PATH**. + ++ Download the DMG that matches your Mac and drag **tty7** into Applications. + + | Mac | File | + |---|---| + | Apple silicon (M1 and later) | `tty7- + +-macos-arm64.dmg` | + | Intel | `tty7- -macos-x86_64.dmg` | + + Builds are signed with a Developer ID certificate and notarized by Apple, so + Gatekeeper opens them without a right-click dance. + + + Builds are produced on macOS 14 and macOS 15. macOS 14 (Sonoma) or later + is the tested range. + ++ Two shapes, both x86-64: + + | File | Use it when | + |---|---| + | `tty7- + +-windows-x86_64-setup.exe` | You want a normal install with Start-menu entries and an uninstaller. | + | `tty7- -windows-x86_64.zip` | You want it portable — unzip anywhere and run `tty7-app.exe`. | + + The installer offers one optional setup task, off by default: **Add "Open in + tty7" to the folder context menu**. It writes shell verbs under `HKCU`, so + only your own Windows account is affected, and the uninstaller always takes + them back out. + + A portable install can add or remove the same entries itself: + + ```powershell + tty7-app.exe --register-explorer-menu + tty7-app.exe --unregister-explorer-menu + ``` + + + The Windows package also carries a Linux `tty7-server` binary so a WSL + distro can be served locally instead of downloading one. See + [Remote workspaces](/remote/workspaces). + ++ | File | Use it when | + |---|---| + | `tty7- +-linux-x86_64.AppImage` | Almost always. `chmod +x` and run — the X11, Wayland, xkb, and font libraries are bundled, so it works on Fedora, Arch, Debian and friends, not just Ubuntu. | + | `tty7- -linux-x86_64.tar.gz` | You would rather unpack the plain binary and place it yourself. | + + ```bash + chmod +x tty7-*-linux-x86_64.AppImage + ./tty7-*-linux-x86_64.AppImage + ``` + + Inside a tty7 pane the CLI works regardless of PATH, because panes inherit the + app's environment. + + +## Updating + +tty7 checks for updates every six hours and can update itself: **Settings → +About → Check now**, then **Update and relaunch**. Releases are downloaded and +verified in the background so applying one is just a restart. + +Pick **Stable** or **Nightly** under **Settings → About → Update channel**. See +[Updates and channels](/reference/updates) for what each feed publishes and how +switching behaves. + +## Building from source + +You need a stable Rust toolchain. The build is a plain `cargo build`; the app +binary is `tty7-app`. + ++ + ++ ```bash + git clone https://github.com/l0ng-ai/tty7 + cd tty7 + cargo build --release + ``` + ++ gpui resolves its X11/Wayland/font backends through `pkg-config` at build + time, so the development packages have to be present: + + ```bash + sudo apt-get install -y pkg-config cmake clang \ + libxkbcommon-dev libxkbcommon-x11-dev \ + libfontconfig1-dev libfreetype6-dev \ + libwayland-dev libx11-dev libxcb1-dev \ + libzstd-dev libssl-dev libkrb5-dev + cargo build --release + ``` + ++ A source build does not update itself, and it will not replace an installed + copy's server. If you run both, see + [Troubleshooting](/reference/troubleshooting). + + +## Uninstalling + ++ diff --git a/docs/git/diffs.mdx b/docs/git/diffs.mdx new file mode 100644 index 00000000..5c2441f3 --- /dev/null +++ b/docs/git/diffs.mdx @@ -0,0 +1,48 @@ +--- +title: "Diffs" +description: "The diff overlay: side-by-side or unified, from the sidebar or the panel." +--- + +## Opening one + +| From | How | +|---|---| +| The sidebar | Click a row's `+N −M` counts | +| Source Control | **Open Changes** on a file, or click the row | +| History | Click a file inside a commit's detail view | + +The overlay covers the window; Esc closes it. + + ++ Quit tty7 (use **Quit and Stop Server** from the tray menu so the background + server stops too), then drag the app to the Trash. Your settings live in + `~/.config/tty7` and are left alone; delete that folder to remove them. + ++ Use **Add or remove programs**. The uninstaller removes the PATH entry and + any Explorer context-menu keys it added. Settings live in + `%APPDATA%\tty7`. + ++ Delete the AppImage or the unpacked directory. Settings live in + `~/.config/tty7`. + ++ + +## Side-by-side or unified + +**Toggle Unified / Side-by-Side Diff** in the command palette switches between +the two. The choice is global — one setting for every diff, the same call VS +Code's `diffEditor.renderSideBySide` makes — and persists as `diff_view` in +`config.json`. + +## What it shows + +- Every changed file, with its status and `+N −M` +- **Untracked files** as a preview of their contents, up to 4 MB — past that the + card says the read failed rather than showing a silently cut-off file +- A commit's files, when the diff came from the history + +Two limits keep a huge diff from becoming a huge wait: + +| Limit | Value | What happens | +|---|---|---| +| Files rendered | 300 | *"Showing the first 300 of N changes."* | +| Lines before auto-collapse | 400 per file | Big files start collapsed; expand the ones you care about | + +Both are stated in the overlay when they apply — nothing is dropped silently. + +## Turning the sidebar shortcut off + +If you would rather the sidebar's counts not be clickable, turn off **Settings → +Window & Tabs → Open diff preview from sidebar counts** +(`sidebar_diff_preview: false`). The branch and counts stay on the row; they +just stop opening the overlay. diff --git a/docs/git/source-control.mdx b/docs/git/source-control.mdx new file mode 100644 index 00000000..da3f23f2 --- /dev/null +++ b/docs/git/source-control.mdx @@ -0,0 +1,86 @@ +--- +title: "Source control" +description: "Stage, commit, branch, and push from the panel beside your terminal." +--- + +The **Source Control** tab of the [side panel](/window/side-panel) (⌘ J) +is a full git client for whichever repository the focused pane is in. It follows +the pane: `cd` into another repository and the panel switches with you. + + +
+ + +## Changes + +Files are grouped by what git thinks of them: + +| Group | | +|---|---| +| **Merge Changes** | Conflicts, with *Resolve Conflict* and *Mark as Resolved* | +| **Staged Changes** | What the next commit will contain | +| **Changes** | Modified but not staged | +| **Untracked** | New files | + +Each row has **Stage Changes**, **Unstage Changes**, **Discard Changes**, and +**Open Changes** — which opens the [diff](/git/diffs). Group-level *Stage All*, +*Unstage All*, and *Discard All* sit on the headers, and the destructive ones +confirm first. + +## Committing + +Write the message in the box at the top and pick a commit action: + +| | | +|---|---| +| **Commit** | Commit what is staged | +| **Commit All** | Stage everything, then commit | +| **Commit (Amend)** | Replace the last commit — confirms first, because anyone who already has it has to reconcile | +| **Commit & Push** | Commit, then push | +| **Commit & Sync** | Commit, then pull and push | + +⌘ ⏎ commits while the caret is in the message box. **Stash All** is +there too. + +## Branches and remotes + +| | | +|---|---| +| **Checkout to…** | Switch branches, with a search box; offers **Stash & Switch** when the tree is dirty | +| **Create Branch…** | From here, or from any commit in the history | +| **Publish Branch** | For a branch with no upstream yet | +| **Sync Changes** | Pull, then push | +| **Push** · **Pull** · **Fetch** | Individually | + +All of these are also in the command palette under **Git**, so they are +bindable. + +When a repository is mid-operation — merging, rebasing, cherry-picking, +reverting, bisecting, applying — the panel says so instead of pretending +everything is normal. + +## History + +**Git: Toggle Commit History** (or the *History* section header) opens the +commit graph: branches drawn as lanes, a filter box, **Current Branch** or +**All Branches**, and *Load more* at the bottom. + +Click a commit for its detail view — message, parents, and the files it touched, +each openable as a diff. From a commit's menu: + +| | | +|---|---| +| **Checkout Commit** · **Create Branch Here…** | Move to it | +| **Cherry Pick** · **Revert Commit** | Apply or undo it here | +| **Reset (Soft / Mixed / Hard)** | Move the branch to it — Hard confirms, since commits after it fall off the branch and uncommitted changes are discarded | +| **Copy Commit SHA** | | + +The history section starts collapsed and remembers whether you opened it +(`scm_graph_expanded`). + +## In the sidebar + +You do not have to open the panel to know where you stand: every +[sidebar row](/window/sidebar) carries its pane's branch and a `+N −M` count of +the working tree, refreshed on `cd` and when a command finishes. Clicking the +counts opens the diff overlay. diff --git a/docs/git/worktrees.mdx b/docs/git/worktrees.mdx new file mode 100644 index 00000000..74d33edb --- /dev/null +++ b/docs/git/worktrees.mdx @@ -0,0 +1,56 @@ +--- +title: "Worktrees" +description: "An isolated checkout on a fresh branch, in one dialog and one tab." +--- + +Running two agents on the same repository at once means they fight over the +working tree. A git worktree is the fix, and tty7 makes it a single dialog. + +## Creating one + +**New Worktree Tab…** — in the command palette, the tab's right-click menu, and +the application menu — asks three things: + +| Field | Default | +|---|---| +| **Worktree Name** | A fresh name that does not collide with an existing branch or directory | +| **New Branch** | The same name, editable | +| **Start From** | The branch you are currently on | + +Each field opens on a suggestion you can accept or type straight over. + + +
+ + +Confirm and tty7 creates the worktree, opens a tab in it, and starts a shell +there. The [sidebar](/window/sidebar) files it under the same repository group as +its parent, on its own branch. + +## Where they go + +Worktrees land inside the repository, under: + +``` +
/.tty7/worktrees/ +``` + +` /.tty7/.gitignore` is created with `*` in it the first time, so the +directory never shows up as an untracked mess in your own repository. + +## Removing one + +Closing a worktree tab offers to remove the worktree with it: + +- **Clean tree** — *Remove Worktree* or *Keep*. +- **Dirty tree** — the dialog says so, and removing requires the explicit + *Discard Changes & Remove*. + +Nothing is removed silently, and *Keep* leaves the worktree on disk for `git +worktree list` to find later. + + + Pair this with [agent sessions](/agents/sessions): a worktree per agent means + two Claude Codes can work on the same repository without stepping on each + other's files. + diff --git a/docs/images/hero.webp b/docs/images/hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..416a5a417d20d47e74b22bc60658c8b374d2f413 GIT binary patch literal 183922 zcmagFb9`jcvNjyswkEcdi8IN>wvCBxbSAd#$;37$wrwX9+fKT_IlA}0=R5eTdev`t z_g?#{s#VWZ-73-&64p}?V47dQC}}A1k{SGY9e)jz15PgjV+$oDNE9tzK>h<=>LHm7 za-gvVFvnQq27-)_%jwPlfj|z?potm7ZQ-j|h~I`EL{l5Mz#66Q?RRNV(jDP~>1t;H zz_XLR`)ptF7WDoh4hX-82Blqf3v~Aay`LC>q#%Gnp5hW__q)gA7A3B5AW-$OW`U*o zeGDWEVlV;-11~^;x0cVHS`!(++ z?-JCyebntHv?1Jh$#`LS@(}>|2?zi!1A|r=?zW5pY9Qq|{%i1qu=kpe?%SgIYdN*YoZTul_X1HVN;790j93mfyGENbiO1yMMh00&U)(-twOE)(tPZ zJGKo#v!E }Fl`g?F8t)#=x+m3{J44&P5>DJrT{g7Lf{Qh z5~TUG{pT9s#h<$h0VaXcUIBlg1M&kmK{mjax9)qxx9*WYp4nIA_vzQT*Xb+LL%=;K z@sDf$47AmKB@Ehr$wLA(34Z{bz%w;NYxE_%sC1S(3oJ!r?%^K35%eK#-;|r;@rxxc zXf1CKWhKqFzSt*4MQiiB1`SnbxyGdq8z}EPZ$b$s{x}#gs|ZGKFB-Ur6E~}TmUuUO zpUnD5sxWyu)F$5J*;xN{P-0m%Ej<@vyw9v(SeKl%W)&KTV1t1PyKR2X=unUjslDh7 zxy$ox-qBQQuBUp* Qh!~q!^zKJwd54B2KAA%y}%3Nu;Wf>+2v*7 #9H~sb^VODCjCd&xT z%cFFM>G3&i!?*8l--NTvl^y2z-p#Ozx%$Q}yLKBJr%AQV`5>S+n@1_&;jWh(XoS^V zdrc|B4U~hY$}T$jmT5Ez>R%vU$=4fUr+(wX<$S6sy83d{PUj__;k=y8qE2QJ{FO(9 zcK1|Dj_rC2f;de?e<~cfF}W_Jwc9 h-&B5#aqr=QJK zNM|z}ej8W84CO|=@FEEguV*V^cQ_A>-tF%kh9B&J>x?!9t?fo1=6)MXZn4r#7e}y> zmAYIIH9hnjUsr*Do5kQy)Y1)I(r4yo09h_U52;0)CjT^g93lwGcv`8Gu~dA(T8$qW zD6{ks{MBE$%+xC__#(bP^i}5z@ZQ&%n;3DjFWw5V`%>iT#chT9_jNQihv!nDn@2T# zW#N8$-$3`mL@ZT{;P(?|IrHNoaq^jfIoxw8>{a;mFDP5GEzSd2QoA}wiiC7`noP!; zf+*fyb_s-;IqD0cm(kVf$NJ*-g=BZwT1;$C=G5Z+$4_%n+u}FK{9^1|Z8H2H+h0-} z{iblqW71u29sJ;~b}!~r2Og(HR$d?7J ;-?#%QWr+APpS$>4)wXwbO~_z5NsX7uWgp*fEU`1KCT|x_xaz+ zlW5Y#bgE>hwE==s2N?R(b=DSnzO9{3SV8quCYc4W=3}Lw^zQmFE^0