PageSourceSearch

https://blanboom.org/2026/ssh-cli-coding-agent/

html blanboom.org collected 2026-09-24 19:26:09 UTC 112,654 bytes, 1,078 lines download raw bytes

1<!doctype html>
2<html lang="zh-Hans">
3<head>
4	
5	<meta charset="UTF-8">
6	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5, viewport-fit=cover">
7	<link rel="profile" href="https://gmpg.org/xfn/11">
8
9	<title>移动端 SSH + CLI Coding Agent 的实践与体验优化 &#8211; Blanboom</title>
10<meta name='robots' content='max-image-preview:large' />
11<meta property="og:type" content="article">
12<meta property="og:title" content="移动端 SSH + CLI Coding Agent 的实践与体验优化">
13<meta property="og:description" content="我的主力电脑是一台 iMac,在固定的房间,这限制了我使用电脑的时间和场景。不过随着 Codex、Claude [&hellip;]">
14<meta property="og:image" content="https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent.png">
15<meta property="og:image:width" content="1536">
16<meta property="og:image:height" content="1024">
17<meta property="og:url" content="https://blanboom.org/2026/ssh-cli-coding-agent/">
18<meta property="og:site_name" content="Blanboom">
19<meta property="article:published_time" content="2026-01-20T22:59:35+08:00">
20<meta property="article:modified_time" content="2026-01-20T23:03:59+08:00">
21<meta property="og:updated_time" content="2026-01-20T23:03:59+08:00">
22<meta property="article:tag" content="AI">
23<meta property="article:tag" content="SSH">
24<meta property="article:section" content="体验与折腾">
25<meta name="twitter:title" content="移动端 SSH + CLI Coding Agent 的实践与体验优化">
26<meta name="twitter:description" content="我的主力电脑是一台 iMac,在固定的房间,这限制了我使用电脑的时间和场景。不过随着 Codex、Claude [&hellip;]">
27<meta name="twitter:card" content="summary_large_image">
28<meta name="twitter:image" content="https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent.png">
29<meta name="twitter:site" content="@Blanboom">
30<meta name="twitter:creator" content="@Blanboom">
31<!-- Jetpack Site Verification Tags -->
32<meta name="google-site-verification" content="jLdMr1XWmHiLVbigajb3c-RD_w95VVog8jmkSw63RKU" />
33<link rel='dns-prefetch' href='//blanboom.org' />
34<link rel='dns-prefetch' href='//www.googletagmanager.com' />
35<link rel='dns-prefetch' href='//stats.wp.com' />
36<link rel="alternate" type="application/rss+xml" title="Blanboom &raquo; Feed" href="https://blanboom.org/feed/" />
37<link rel="alternate" type="application/rss+xml" title="Blanboom &raquo; 评论 Feed" href="https://blanboom.org/comments/feed/" />
38<link rel="alternate" type="application/rss+xml" title="Blanboom &raquo; 移动端 SSH + CLI Coding Agent 的实践与体验优化 评论 Feed" href="https://blanboom.org/2026/ssh-cli-coding-agent/feed/" />
39<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://blanboom.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fblanboom.org%2F2026%2Fssh-cli-coding-agent%2F" />
40<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://blanboom.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fblanboom.org%2F2026%2Fssh-cli-coding-agent%2F&#038;format=xml" />
41<style id="wp-img-auto-sizes-contain-inline-css">
42img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}
43/*# sourceURL=wp-img-auto-sizes-contain-inline-css */
44</style>
45<link rel='stylesheet' id='blocksy-dynamic-global-css' href='https://blanboom.org/wp-content/uploads/blocksy/css/global.css?ver=78854' media='all' />
46<style id="wp-block-library-inline-css">
47:root{--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color);--wp-editor-canvas-background:#ddd;--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,160.5;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}
47:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}:root{--wp--preset--font-size--normal:16px;--wp--preset--font-size--huge:42px}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}:root .has-text-align-center{text-align:center}:root .has-text-align-left{text-align:left}:root .has-text-align-right{text-align:right}.has-fit-text{white-space:nowrap!important}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{word-wrap:normal!important;border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style*=border-color]){border-style:solid}html :where([style*=border-top-color]){border-top-style:solid}html :where([style*=border-right-color]){border-right-style:solid}html :where([style*=border-bottom-color]){border-bottom-style:solid}html :where([style*=border-left-color]){border-left-style:solid}html :where([style*=border-width]){border-style:solid}html :where([style*=border-top-width]){border-top-style:solid}html :where([style*=border-right-width]){border-right-style:solid}html :where([style*=border-bottom-width]){border-bottom-style:solid}html :where([style*=border-left-width]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}}
48
49/*# sourceURL=/wp-includes/css/dist/block-library/common.min.css */
50</style>
51<style id="wp-block-list-inline-css">
52ol,ul{box-sizing:border-box}:root :where(.wp-block-list.has-background){padding:1.25em 2.375em}
53/*# sourceURL=https://blanboom.org/wp-includes/blocks/list/style.min.css */
54</style>
55
56
57<style id="global-styles-inline-css">
58:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--palette-color-1: var(--theme-palette-color-1, #2872fa);--wp--preset--color--palette-color-2: var(--theme-palette-color-2, #1559ed);--wp--preset--color--palette-color-3: var(--theme-palette-color-3, #3A4F66);--wp--preset--color--palette-color-4: var(--theme-palette-color-4, #192a3d);--wp--preset--color--palette-color-5: var(--theme-palette-color-5, #e1e8ed);--wp--preset--color--palette-color-6: var(--theme-palette-color-6, #f2f5f7);--wp--preset--color--palette-color-7: var(--theme-palette-color-7, #FAFBFC);--wp--preset--color--palette-color-8: var(--theme-palette-color-8, #ffffff);--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgb(252,185,
580) 0%,rgb(255,105,0) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--gradient--juicy-peach: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%);--wp--preset--gradient--young-passion: linear-gradient(to right, #ff8177 0%, #ff867a 0%, #ff8c7f 21%, #f99185 52%, #cf556c 78%, #b12a5b 100%);--wp--preset--gradient--true-sunset: linear-gradient(to right, #fa709a 0%, #fee140 100%);--wp--preset--gradient--morpheus-den: linear-gradient(to top, #30cfd0 0%, #330867 100%);--wp--preset--gradient--plum-plate: linear-gradient(135deg, #667eea 0%, #764ba2 100%);--wp--preset--gradient--aqua-splash: linear-gradient(15deg, #13547a 0%, #80d0c7 100%);--wp--preset--gradient--love-kiss: linear-gradient(to top, #ff0844 0%, #ffb199 100%);--wp--preset--gradient--new-retrowave: linear-gradient(to top, #3b41c5 0%, #a981bb 49%, #ffc8a9 100%);--wp--preset--gradient--plum-bath: linear-gradient(to top, #cc208e 0%, #6713d2 100%);--wp--preset--gradient--high-flight: linear-gradient(to right, #0acffe 0%, #495aff 100%);--wp--preset--gradient--teen-party: linear-gradient(135deg, #FF057C 0%, #8D0B93 50%, #321575 100%);--wp--preset--gradient--fabled-sunset: linear-gradient(135deg, #231557 0%, #44107A 29%, #FF1361 67%, #FFF800 100%);--wp--preset--gradient--arielle-smile: radial-gradient(circle 248px at center, #16d9e3 0%, #30c7ec 47%, #46aef7 100%);--wp--preset--gradient--itmeo-branding: linear-gradient(180deg, #2af598 0%, #009efd 100%);--wp--preset--gradient--deep-blue: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);--wp--preset--gradient--strong-bliss: linear-gradient(to right, #f78ca0 0%, #f9748f 19%, #fd868c 60%, #fe9a8b 100%);--wp--preset--gradient--sweet-period: linear-gradient(to top, #3f51b1 0%, #5a55ae 13%, #7b5fac 25%, #8f6aae 38%, #a86aa4 50%, #cc6b8e 62%, #f18271 75%, #f3a469 87%, #f7c978 100%);--wp--preset--gradient--purple-division: linear-gradient(to top, #7028e4 0%, #e5b2ca 100%);--wp--preset--gradient--cold-evening: linear-gradient(to top, #0c3483 0%, #a2b6df 100%, #6b8cce 100%, #a2b6df 100%);--wp--preset--gradient--mountain-rock: linear-gradient(to right, #868f96 0%, #596164 100%);--wp--preset--gradient--desert-hump: linear-gradient(to top, #c79081 0%, #dfa579 100%);--wp--preset--gradient--ethernal-constance: linear-gradient(to top, #09203f 0%, #537895 100%);--wp--preset--gradient--happy-memories: linear-gradient(300deg, #ff5858 0%, #f09819 100%);--wp--preset--gradient--grown-early: linear-gradient(to top, #0ba360 0%, #3cba92 100%);--wp--preset--gradient--morning-salad: linear-gradient(135deg, #B7F8DB 0%, #50A7C2 100%);--wp--preset--gradient--night-call: linear-gradient(135deg, #AC32E4 0%, #7918F2 48%, #4801FF 100%);--wp--preset--gradient--mind-crawl: linear-gradient(135deg, #473B7B 0%, #3584A7 51%, #30D2BE 100%);--wp--preset--gradient--angel-care: linear-gradient(135deg, #FFE29F 0%, #FFA99F 48%, #FF719A 100%);--wp--preset--gradient--juicy-cake: linear-gradient(to top, #e14fad 0%, #f9d423 100%);--wp--preset--gradient--rich-metal: linear-gradient(to right, #d7d2cc 0%, #304352 100%);--wp--preset--gradient--mole-hall: linear-gradient(340deg, #616161 0%, #9bc5c3 100%);--wp--preset--gradient--cloudy-knoxville: linear-gradient(120deg, #fdfbfb 0%, #ebedee 100%);--wp--preset--gradient--soft-grass: linear-gradient(to top, #c1dfc4 0%, #deecdd 100%);--wp--preset--gradient--saint-petersburg: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);--wp--preset--gradient--everlasting-sky: linear-gradient(135deg, #fdfcfb 0%, #e2d1c3 100%);--wp--preset--gradient--kind-steel: linear-gradient(340deg, #e9defa 0%, #fbfcdb 100%);--wp--preset--gradient--over-sun: linear-gradient(60deg, #abecd6 0%, #fbed96 100%);--wp--preset--gradient--premium-white: linear-gradient(to top, #d5d4d0 0%, #d5d4d0 1%, #eeeeec 31%, #efeeec 75%, #e9e9e7 100%);--wp--preset--gradient--clean-mirror: linear-gradient(45deg, #93a5cf 0%, #e4efe9 100%);--wp--preset--gradient--wild-apple: linear-gradient(to top, #d299c2 0%, #fef9d7 100%);--wp--preset--gradient--snow-again: linear-gradient(to top, #e6e9f0 0%, #eef1f5 100%);--wp--preset--gradient--confident-cloud: linear-gradient(to top, #dad4ec 0%, #dad4ec 1%, #f3e7e9 100%);
58--wp--preset--gradient--glass-water: linear-gradient(to top, #dfe9f3 0%, white 100%);--wp--preset--gradient--perfect-white: linear-gradient(135deg, #E3FDF5 0%, #FFE6FA 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: clamp(22px, 1.375rem + ((1vw - 3.2px) * 0.625), 30px);--wp--preset--font-size--x-large: clamp(30px, 1.875rem + ((1vw - 3.2px) * 1.563), 50px);--wp--preset--font-size--xx-large: clamp(45px, 2.813rem + ((1vw - 3.2px) * 2.734), 80px);--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);--wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);}:root { --wp--style--global--content-size: var(--theme-block-max-width);--wp--style--global--wide-size: var(--theme-block-wide-max-width); }:where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: var(--theme-content-spacing); margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: var(--theme-content-spacing); }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: var(--theme-content-spacing);margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: var(--theme-content-spacing);margin-block-end: 0;}:root :where(.is-layout-flex){gap: var(--theme-content-spacing);}:root :where(.is-layout-grid){gap: var(--theme-content-spacing);}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{padding-top: 0px;padding-right: 0px;padding-bottom: 0px;padding-left: 0px;}:root :where(.wp-element-button, .wp-block-button__link){font-style: inherit;font-weight: inherit;letter-spacing: inherit;text-transform: inherit;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-palette-color-1-color{color: var(--wp--preset--color--palette-color-1) !important;}.has-palette-color-2-color{color: var(--wp--preset--color--palette-color-2) !important;}.has-palette-color-3-color{color: var(--wp--preset--color--palette-color-3) !important;}.has-palette-color-4-color{color: var(--wp--preset--color--palette-color-4) !important;}.has-palette-color-5-color{color: var(--wp--preset--color--palette-color-5) !important;}.has-palette-color-6-color{color: var(--wp--preset--color--palette-color-6) !important;}.has-palette-color-7-color{color: var(--wp--preset--color--palette-color-7) !important;}.has-palette-color-8-color{color: var(--wp--preset--color--palette-color-8) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-palette-color-1-background-color{background-color: var(--wp--preset--color--palette-color-1) !important;}.has-palette-color-2-background-color{background-color: var(--wp--preset--color--palette-color-2) !important;}.has-palette-color-3-background-color{background-color: var(--wp--preset--color--palette-color-3) !important;}.has-palette-color-4-background-color{background-color: var(--wp--preset--color--palette-color-4) !important;}.has-palette-color-5-background-color{background-color: var(--wp--preset--color--palette-color-5) !important;}.has-palette-color-6-background-color{background-color: var(--wp--preset--color--palette-color-6) !important;}.has-palette-color-7-background-color{background-color: var(--wp--preset--color--palette-color-7) !important;}.has-palette-color-8-background-color{background-color: var(--wp--preset--color--palette-color-8) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-palette-color-1-border-color{border-color: var(--wp--preset--color--palette-color-1) !important;}.has-palette-color-2-border-color{border-color: var(--wp--preset--color--palette-color-2) !important;}.has-palette-color-3-border-color{border-color: var(--wp--preset--color--palette-color-3) !important;}.has-palette-color-4-border-color{border-color: var(--wp--preset--color--palette-color-4) !important;}.has-palette-color-5-border-color{border-color: var(--wp--preset--color--palette-color-5) !important;}.has-palette-color-6-border-color{border-color: var(--wp--preset--color--palette-color-6) !important;}.has-palette-color-7-border-color{border-color: var(--wp--preset--color--palette-color-7) !important;}.has-palette-color-8-border-color{border-color: var(--wp--preset--color--palette-color-8) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}
58.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-juicy-peach-gradient-background{background: var(--wp--preset--gradient--juicy-peach) !important;}.has-young-passion-gradient-background{background: var(--wp--preset--gradient--young-passion) !important;}.has-true-sunset-gradient-background{background: var(--wp--preset--gradient--true-sunset) !important;}.has-morpheus-den-gradient-background{background: var(--wp--preset--gradient--morpheus-den) !important;}.has-plum-plate-gradient-background{background: var(--wp--preset--gradient--plum-plate) !important;}.has-aqua-splash-gradient-background{background: var(--wp--preset--gradient--aqua-splash) !important;}.has-love-kiss-gradient-background{background: var(--wp--preset--gradient--love-kiss) !important;}.has-new-retrowave-gradient-background{background: var(--wp--preset--gradient--new-retrowave) !important;}.has-plum-bath-gradient-background{background: var(--wp--preset--gradient--plum-bath) !important;}.has-high-flight-gradient-background{background: var(--wp--preset--gradient--high-flight) !important;}
58.has-teen-party-gradient-background{background: var(--wp--preset--gradient--teen-party) !important;}.has-fabled-sunset-gradient-background{background: var(--wp--preset--gradient--fabled-sunset) !important;}.has-arielle-smile-gradient-background{background: var(--wp--preset--gradient--arielle-smile) !important;}.has-itmeo-branding-gradient-background{background: var(--wp--preset--gradient--itmeo-branding) !important;}.has-deep-blue-gradient-background{background: var(--wp--preset--gradient--deep-blue) !important;}.has-strong-bliss-gradient-background{background: var(--wp--preset--gradient--strong-bliss) !important;}.has-sweet-period-gradient-background{background: var(--wp--preset--gradient--sweet-period) !important;}.has-purple-division-gradient-background{background: var(--wp--preset--gradient--purple-division) !important;}.has-cold-evening-gradient-background{background: var(--wp--preset--gradient--cold-evening) !important;}.has-mountain-rock-gradient-background{background: var(--wp--preset--gradient--mountain-rock) !important;}.has-desert-hump-gradient-background{background: var(--wp--preset--gradient--desert-hump) !important;}.has-ethernal-constance-gradient-background{background: var(--wp--preset--gradient--ethernal-constance) !important;}.has-happy-memories-gradient-background{background: var(--wp--preset--gradient--happy-memories) !important;}.has-grown-early-gradient-background{background: var(--wp--preset--gradient--grown-early) !important;}.has-morning-salad-gradient-background{background: var(--wp--preset--gradient--morning-salad) !important;}.has-night-call-gradient-background{background: var(--wp--preset--gradient--night-call) !important;}.has-mind-crawl-gradient-background{background: var(--wp--preset--gradient--mind-crawl) !important;}.has-angel-care-gradient-background{background: var(--wp--preset--gradient--angel-care) !important;}.has-juicy-cake-gradient-background{background: var(--wp--preset--gradient--juicy-cake) !important;}.has-rich-metal-gradient-background{background: var(--wp--preset--gradient--rich-metal) !important;}.has-mole-hall-gradient-background{background: var(--wp--preset--gradient--mole-hall) !important;}.has-cloudy-knoxville-gradient-background{background: var(--wp--preset--gradient--cloudy-knoxville) !important;}.has-soft-grass-gradient-background{background: var(--wp--preset--gradient--soft-grass) !important;}.has-saint-petersburg-gradient-background{background: var(--wp--preset--gradient--saint-petersburg) !important;}.has-everlasting-sky-gradient-background{background: var(--wp--preset--gradient--everlasting-sky) !important;}.has-kind-steel-gradient-background{background: var(--wp--preset--gradient--kind-steel) !important;}.has-over-sun-gradient-background{background: var(--wp--preset--gradient--over-sun) !important;}.has-premium-white-gradient-background{background: var(--wp--preset--gradient--premium-white) !important;}.has-clean-mirror-gradient-background{background: var(--wp--preset--gradient--clean-mirror) !important;}.has-wild-apple-gradient-background{background: var(--wp--preset--gradient--wild-apple) !important;}.has-snow-again-gradient-background{background: var(--wp--preset--gradient--snow-again) !important;}.has-confident-cloud-gradient-background{background: var(--wp--preset--gradient--confident-cloud) !important;}.has-glass-water-gradient-background{background: var(--wp--preset--gradient--glass-water) !important;}.has-perfect-white-gradient-background{background: var(--wp--preset--gradient--perfect-white) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-xx-large-font-size{font-size: var(--wp--preset--font-size--xx-large) !important;}
59/*# sourceURL=global-styles-inline-css */
60</style>
61
62<link rel='stylesheet' id='prismatic-prism-css' href='https://blanboom.org/wp-content/plugins/prismatic/lib/prism/css/theme-default.css?ver=3.7.5' media='all' />
63<link rel='stylesheet' id='ct-main-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/main.min.css?ver=2.1.44' media='all' />
64<link rel='stylesheet' id='ct-page-title-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/p
64age-title.min.css?ver=2.1.44' media='all' />
65<link rel='stylesheet' id='ct-comments-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/comments.min.css?ver=2.1.44' media='all' />
66<link rel='stylesheet' id='ct-posts-nav-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/posts-nav.min.css?ver=2.1.44' media='all' />
67<link rel='stylesheet' id='ct-featured-image-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/featured-image.min.css?ver=2.1.44' media='all' />
68<link rel='stylesheet' id='ct-related-posts-styles-css' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/related-posts.min.css?ver=2.1.44' media='all' />
69<link rel='stylesheet' id='wp-block-paragraph-css' href='https://blanboom.org/wp-includes/blocks/paragraph/style.min.css?ver=7.0' media='all' />
70
71<!-- Google tag (gtag.js) snippet added by Site Kit -->
72<!-- Site Kit 添加的 Google Analytics 代码段 -->
vendor: 80 bytes, lines 72-73
72
73<script id="google_gtagjs-js" src="https://www.googletagmanager.com/gtag/js?id=
73G-8H84YY5TRN
vendor: 18 bytes, line 73
73" async></script>
74<script id="google_gtagjs-js-after">
75window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}
76gtag("set","linker",{"domains":["blanboom.org"]});
77gtag("js", new Date());
78gtag("set", "developer_id.dZTNiMT", true);
79gtag("config", "G-8H84YY5TRN", {"googlesitekit_post_type":"post","googlesitekit_post_categories":"\u4f53\u9a8c\u4e0e\u6298\u817e","googlesitekit_post_date":"20260120"});
80//# sourceURL=google_gtagjs-js-after
81</script>
81
82<link rel="https://api.w.org/" href="https://blanboom.org/wp-json/" /><link rel="alternate" title="JSON" type="application/json" href="https://blanboom.org/wp-json/wp/v2/posts/4298" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://blanboom.org/xmlrpc.php?rsd" />
83<meta name="generator" content="WordPress 7.0" />
84<link rel="canonical" href="https://blanboom.org/2026/ssh-cli-coding-agent/" />
85<link rel='shortlink' href='https://wp.me/p3DFpo-17k' />
86<meta name="generator" content="Site Kit by Google 1.180.0" />	<style>img#wpstats{display:none}</style>
87		<noscript><link rel='stylesheet' href='https://blanboom.org/wp-content/themes/blocksy/static/bundle/no-scripts.min.css' type='text/css'></noscript>
88<meta name="description" content="我的主力电脑是一台 iMac,在固定的房间,这限制了我使用电脑的时间和场景。不过随着 Codex、Claude&hellip;" />
89<link rel="icon" href="https://blanboom.org/wp-content/uploads/2018/03/cropped-favicon.001-32x32.png" sizes="32x32" />
90<link rel="icon" href="https://blanboom.org/wp-content/uploads/2018/03/cropped-favicon.001-192x192.png" sizes="192x192" />
91<link rel="apple-touch-icon" href="https://blanboom.org/wp-content/uploads/2018/03/cropped-favicon.001-180x180.png" />
92<meta name="msapplication-TileImage" content="https://blanboom.org/wp-content/uploads/2018/03/cropped-favicon.001-270x270.png" />
93	<link rel='stylesheet' id='lwptoc-main-css' href='https://blanboom.org/wp-content/plugins/luckywp-table-of-contents/front/assets/main.min.css?ver=2.1.14' media='all' />
94
95</head>
96
97
98<body class="wp-singular post-template-default single single-post postid-4298 single-format-standard wp-embed-responsive wp-theme-blocksy" data-link="type-2" data-prefix="single_blog_post" data-header="type-1" data-footer="type-1" itemscope="itemscope" itemtype="https://schema.org/Blog">
99
100<a class="skip-link screen-reader-text" href="#main">跳至内容</a><div class="ct-drawer-canvas" data-location="start">
101		<div id="search-modal" class="ct-panel" data-behaviour="modal" role="dialog" aria-label="搜索模态窗" inert>
102			<div class="ct-panel-actions">
103				<button class="ct-toggle-close" data-type="type-1" aria-label="关闭搜索模态窗">
104					<svg class="ct-icon" width="12" height="12" viewBox="0 0 15 15"><path d="M1 15a1 1 0 01-.71-.29 1 1 0 010-1.41l5.8-5.8-5.8-5.8A1 1 0 011.7.29l5.8 5.8 5.8-5.8a1 1 0 011.41 1.41l-5.8 5.8 5.8 5.8a1 1 0 01-1.41 1.41l-5.8-5.8-5.8 5.8A1 1 0 011 15z"/></svg>				</button>
105			</div>
106
107			<div class="ct-panel-content">
108				
109
110<form role="search" method="get" class="ct-search-form" data-form-controls="inside" data-taxonomy-filter="false" data-submit-button="icon" action="https://blanboom.org/" aria-haspopup="listbox" data-live-results="thumbs">
111
112	<div class="ct-search-form-inner ct-pseudo-input" >
113		
114			<input
115				type="search" class="modal-field"				placeholder="Start typing to search"
116				value=""
117				name="s"
118				autocomplete="off"
119				title="搜索..."
120				aria-label="搜索..."
121									aria-autocomplete="list"
122					aria-controls="ct-search-results-ec8"
123					aria-describedby="ct-search-status-ec8"
124					aria-expanded="false"
125											>
126
127			
128		
129		<button type="submit" class="wp-element-button" aria-label="搜索按钮">
130			<svg class="ct-icon ct-search-button-content" aria-hidden="true" width="15" height="15" viewBox="0 0 15 15"><path d="M14.8,13.7L12,11c0.9-1.2,1.5-2.6,1.5-4.2c0-3.7-3-6.8-6.8-6.8S0,3,0,6.8s3,6.8,6.8,6.8c1.6,0,3.1-0.6,4.2-1.5l2.8,2.8c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2C15.1,14.5,15.1,14,14.8,13.7z M1.5,6.8c0-2.9,2.4-5.2,5.2-5.2S12,3.9,12,6.8S9.6,12,6.8,12S1.5,9.6,1.5,6.8z"/></svg>
131			<span class="ct-ajax-loader">
132				<svg viewBox="0 0 24 24">
133					<circle cx="12" cy="12" r="10" opacity="0.2" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"/>
134
135					<path d="m12,2c5.52,0,10,4.48,10,10" fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2">
136						<animateTransform
137							attributeName="transform"
138							attributeType="XML"
139							type="rotate"
140							dur="0.6s"
141							from="0 12 12"
142							to="360 12 12"
143							repeatCount="indefinite"
144							begin="indefinite"
145						/>
146					</path>
147				</svg>
148			</span>
149		</button>
150
151		
152					<input type="hidden" name="ct_post_type" value="post:page">
153		
154		
155
156			</div>
157
158			<div
159			class="screen-reader-text"
160			id="ct-search-status-ec8"
161			aria-live="polite"
162			role="status">
163			无结果		</div>
164	
165</form>
166			</div>
167		</div>
168
169		<div id="offcanvas" class="ct-panel ct-header" data-behaviour="right-side" role="dialog" aria-label="侧边栏模态窗" inert=""><div class="ct-panel-inner">
170				<div class="ct-panel-actions">
171					
172					
173				<button class="ct-toggle-close" data-type="type-1" aria-label="关闭抽屉">
174					<svg class="ct-icon" width="12" height="12" viewBox="0 0 15 15"><path d="M1 15a1 1 0 01-.71-.29 1 1 0 010-1.41l5.8-5.8-5.8-5.8A1 1 0 011.7.29l5.8 5.8 5.8-5.8a1 1 0 011.41 1.41l-5.8 5.8 5.8 5.8a1 1 0 01-1.41 1.41l-5.8-5.8-5.8 5.8A1 1 0 011 15z"/></svg>
175				</button>
176			
177				</div>
178			<div class="ct-panel-content" data-device="desktop"><div class="ct-panel-content-inner"></div></div><div class="ct-panel-content" data-device="mobile"><div class="ct-panel-content-inner">
179<nav
180	class="mobile-menu menu-container"
181	data-id="mobile-menu" data-interaction="click" data-toggle-type="type-1" data-submenu-dots="yes"	aria-label="Pages">
182
183	<ul id="menu-pages-1" class=""><li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-602"><a href="https://blanboom.org/" class="ct-menu-link">博客</a></li>
184<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-357"><a href="https://blanboom.org/projects/" class="ct-menu-link">作品</a></li>
185<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-356"><a href="https://blanboom.org/about/" class="ct-menu-link">关于</a></li>
186<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2212"><a href="https://itunes.apple.com/us/app/id1296588408" class="ct-menu-link">AirTerminal | 蓝牙串口终端</a></li>
187<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4189"><a href="https://apps.apple.com/cn/app/heif-hevc-converter/id6744530166" class="ct-menu-link">HEIF &#038; HEVC 转换器</a></li>
188</ul></nav>
189
190</div></div></div></div></div>
191<div id="main-container">
192	<header id="header" class="ct-header" data-id="type-1" itemscope="" itemtype="https://schema.org/WPHeader"><div data-device="desktop"><div data-row="middle" data-column-set="2"><div class="ct-container"><div data-column="start" data-placements="1"><div data-items="primary">
193<div	class="site-branding"
194	data-id="logo"		itemscope="itemscope" itemtype="https://schema.org/Organization">
195
196	
197			<div class="site-title-container">
198			<span class="site-title " itemprop="name"><a href="https://blanboom.org/" rel="home" itemprop="url">Blanboom</a></span>					</div>
199	  </div>
200
201</div></div><div data-column="end" data-placements="1"><div data-items="primary">
202<nav
203	id="header-menu-1"
204	class="header-menu-1 menu-container"
205	data-id="menu" data-interaction="hover"	data-menu="type-1"
206	data-dropdown="type-1:simple"		data-responsive="no"	itemscope="" itemtype="https://schema.org/SiteNavigationElement"	aria-label="Pages">
207
208	<ul id="menu-pages" class="menu"><li id="menu-item-602" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-602"><a href="https://blanboom.org/" class="ct-menu-link">博客</a></li>
209<li id="menu-item-357" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-357"><a href="https://blanboom.org/projects/" class="ct-menu-link">作品</a></li>
210<li id="menu-item-356" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-356"><a href="https://blanboom.org/about/" class="ct-menu-link">关于</a></li>
211<li id="menu-item-2212" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2212"><a href="https://itunes.apple.com/us/app/id1296588408" class="ct-menu-link">AirTerminal | 蓝牙串口终端</a></li>
212<li id="menu-item-4189" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4189"><a href="https://apps.apple.com/cn/app/heif-hevc-converter/id6744530166" class="ct-menu-link">HEIF &#038; HEVC 转换器</a></li>
213</ul></nav>
214
215
216<button
217	class="ct-header-search ct-toggle "
218	data-toggle-panel="#search-modal"
219	aria-controls="search-modal"
220	aria-label="搜索"
221	data-label="left"
222	data-id="search">
223
224	<span class="ct-label ct-hidden-sm ct-hidden-md ct-hidden-lg" aria-hidden="true">搜索</span>
225
226	<svg class="ct-icon" aria-hidden="true" width="15" height="15" viewBox="0 0 15 15"><path d="M14.8,13.7L12,11c0.9-1.2,1.5-2.6,1.5-4.2c0-3.7-3-6.8-6.8-6.8S0,3,0,6.8s3,6.8,6.8,6.8c1.6,0,3.1-0.6,4.2-1.5l2.8,2.8c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2C15.1,14.5,15.1,14,14.8,13.7z M1.5,6.8c0-2.9,2.4-5.2,5.2-5.2S12,3.9,12,6.8S9.6,12,6.8,12S1.5,9.6,1.5,6.8z"/></svg></button>
227</div></div></div></div></div><div data-device="mobile"><div data-row="middle" data-column-set="2"><div class="ct-container"><div data-column="start" data-placements="1"><div data-items="primary">
228<div	class="site-branding"
229	data-id="logo"		>
230
231	
232			<div class="site-title-container">
233			<span class="site-title "><a href="https://blanboom.org/" rel="home" >Blanboom</a></span>					</div>
234	  </div>
235
236</div></div><div data-column="end" data-placements="1"><div data-items="primary">
237<button
238	class="ct-header-search ct-toggle "
239	data-toggle-panel="#search-modal"
240	aria-controls="search-modal"
241	aria-label="搜索"
242	data-label="left"
243	data-id="search">
244
245	<span class="ct-label ct-hidden-sm ct-hidden-md ct-hidden-lg" aria-hidden="true">搜索</span>
246
247	<svg class="ct-icon" aria-hidden="true" width="15" height="15" viewBox="0 0 15 15"><path d="M14.8,13.7L12,11c0.9-1.2,1.5-2.6,1.5-4.2c0-3.7-3-6.8-6.8-6.8S0,3,0,6.8s3,6.8,6.8,6.8c1.6,0,3.1-0.6,4.2-1.5l2.8,2.8c0.1,0.1,0.3,0.2,0.5,0.2s0.4-0.1,0.5-0.2C15.1,14.5,15.1,14,14.8,13.7z M1.5,6.8c0-2.9,2.4-5.2,5.2-5.2S12,3.9,12,6.8S9.6,12,6.8,12S1.5,9.6,1.5,6.8z"/></svg></button>
248
249<button
250	class="ct-header-trigger ct-toggle "
251	data-toggle-panel="#offcanvas"
252	aria-controls="offcanvas"
253	data-design="simple"
254	data-label="right"
255	aria-label="菜单"
256	data-id="trigger">
257
258	<span class="ct-label ct-hidden-sm ct-hidden-md ct-hidden-lg" aria-hidden="true">菜单</span>
259
260	<svg class="ct-icon" width="18" height="14" viewBox="0 0 18 14" data-type="type-1" aria-hidden="true">
261		<rect y="0.00" width="18" height="1.7" rx="1"/>
262		<rect y="6.15" width="18" height="1.7" rx="1"/>
263		<rect y="12.3" width="18" height="1.7" rx="1"/>
264	</svg></button>
265</div></div></div></div></div></header>
266	<main id="main" class="site-main hfeed" itemscope="itemscope" itemtype="https://schema.org/CreativeWork">
267
268		
269	<div
270		class="ct-container-full"
271				data-content="narrow"		data-vertical-spacing="top:bottom">
272
273		
274		
275	<article
276		id="post-4298"
277		class="post-4298 post type-post status-publish format-standard has-post-thumbnail hentry category-experiences tag-ai tag-ssh">
278
279		<figure class="ct-featured-image "><div class="ct-media-container"><img width="1536" height="1024" src="https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent.png" class="attachment-full size-full wp-post-image" alt=""  decoding="async" srcset="https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent.png 1536w, https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent-300x200.png 300w, https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent-1024x683.png 1024w, https://blanboom.org/wp-content/uploads/2026/01/ssh-cli-agent-768x512.png 768w" sizes="auto, (max-width: 1536px) 100vw, 1536px" itemprop="image" style="aspect-ratio: 3/2;" /></div></figure>
280<div class="hero-section is-width-constrained" data-type="type-1">
281			<header class="entry-header">
282			<h1 class="page-title" itemprop="headline">移动端 SSH + CLI Coding Agent 的实践与体验优化</h1><ul class="entry-meta" data-type="icons:circle" ><li class="meta-date" itemprop="datePublished"><svg width="13" height="13" viewBox="0 0 15 15"><path d="M7.5,0C3.4,0,0,3.4,0,7.5S3.4,15,7.5,15S15,11.6,15,7.5S11.6,0,7.5,0z M7.5,13.6c-3.4,0-6.1-2.8-6.1-6.1c0-3.4,2.8-6.1,6.1-6.1c3.4,0,6.1,2.8,6.1,6.1C13.6,10.9,10.9,13.6,7.5,13.6z M10.8,9.2c-0.1,0.2-0.4,0.4-0.6,0.4c-0.1,0-0.2,0-0.3-0.1L7.2,8.1C7,8,6.8,7.8,6.8,7.5V4c0-0.4,0.3-0.7,0.7-0.7S8.2,3.6,8.2,4v3.1l2.4,1.2C10.9,8.4,11,8.8,10.8,9.2z"/></svg><time class="ct-meta-element-date" datetime="2026-01-20T22:59:35+08:00">2026-01-20</time></li><li class="meta-categories" data-type="simple"><svg width="13" height="13" viewBox="0 0 15 15"><path d="M14.4,1.2H0.6C0.3,1.2,0,1.5,0,1.9V5c0,0.3,0.3,0.6,0.6,0.6h0.6v7.5c0,0.3,0.3,0.6,0.6,0.6h11.2c0.3,0,0.6-0.3,0.6-0.6V5.6h0.6C14.7,5.6,15,5.3,15,5V1.9C15,1.5,14.7,1.2,14.4,1.2z M12.5,12.5h-10V5.6h10V12.5z M13.8,4.4H1.2V2.5h12.5V4.4z M5.6,7.5c0-0.3,0.3-0.6,0.6-0.6h2.5c0.3,0,0.6,0.3,0.6,0.6S9.1,8.1,8.8,8.1H6.2C5.9,8.1,5.6,7.8,5.6,7.5z"/></svg><a href="https://blanboom.org/category/experiences/" rel="tag" class="ct-term-120">体验与折腾</a></li></ul>		</header>
283	</div>
284		
285		
286		<div class="entry-content is-layout-constrained">
287			
288<p class="wp-block-paragraph">我的主力电脑是一台 iMac,在固定的房间,这限制了我使用电脑的时间和场景。不过随着 <a href="https://github.com/openai/codex">Codex</a>、<a href="https://github.com/anthropics/claude-code">Claude Code</a> 等 CLI Coding Agent 的出现,我可以在 iPad 或手机上,通过 SSH 远程连接 Mac,在乘坐地铁等碎片时间远程开发,随时随地为「<a href="https://blanboom.org/2025/heif_converter/">HEIF &amp; HEVC 转换器</a>」添加新功能。</p>
289
290
291
292<p class="wp-block-paragraph">在通过 SSH 远程开发的过程中,我对自己的开发环境进行了一系列配置和优化,例如:</p>
293
294
295
296<ul class="wp-block-list">
297<li>通过&nbsp;<a href="https://github.com/Finb/Bark">Bark</a>&nbsp;将 Claude Code/Codex 的通知推送到 iPhone</li>
298
299
300
301<li>解决移动端网络变化/杀后台导致 SSH 断连</li>
302
303
304
305<li>修改 SSH 配置文件让 1Password SSH Agent 与远程连接共存</li>
306</ul>
307
308
309
310<p class="wp-block-paragraph">我将自己进行的配置改动记录到这篇文章中,供自己后续维护和回顾,也方便各位读者参考。</p>
311
312
313
314<span id="more-4298"></span>
315
316
317
318<div class="wp-block-jetpack-markdown"><div class="lwptoc lwptoc-autoWidth lwptoc-baseItems lwptoc-inherit" data-smooth-scroll="0"><div class="lwptoc_i">    <div class="lwptoc_header">
319        <b class="lwptoc_title">目录</b>            </div>
320<div class="lwptoc_items lwptoc_items-visible">
321    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#Coding_Agent">
322                    <span class="lwptoc_item_number">1</span>
323                <span class="lwptoc_item_label">将 Coding Agent 的通知发送到手机上</span>
324    </a>
325    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#Bark_CodexClaude_Code_OpenCode">
326                    <span class="lwptoc_item_number">1.1</span>
327                <span class="lwptoc_item_label">Bark 通知脚本,同时兼容 Codex、Claude Code 和 OpenCode</span>
328    </a>
329    </div><div class="lwptoc_item">    <a href="#Codex">
330                    <span class="lwptoc_item_number">1.2</span>
331                <span class="lwptoc_item_label">Codex 配置文件</span>
332    </a>
333    </div><div class="lwptoc_item">    <a href="#Claude_Code">
334                    <span class="lwptoc_item_number">1.3</span>
335                <span class="lwptoc_item_label">Claude Code 配置文件</span>
336    </a>
337    </div><div class="lwptoc_item">    <a href="#OpenCode">
338                    <span class="lwptoc_item_number">1.4</span>
339                <span class="lwptoc_item_label">OpenCode 配置文件</span>
340    </a>
341    </div><div class="lwptoc_item">    <a href="#lwptoc">
342                    <span class="lwptoc_item_number">1.5</span>
343                <span class="lwptoc_item_label">备选方案</span>
344    </a>
345    </div></div></div><div class="lwptoc_item">    <a href="#SSH">
346                    <span class="lwptoc_item_number">2</span>
347                <span class="lwptoc_item_label">选择合适的 SSH 终端</span>
348    </a>
349    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#Secure_ShellFish">
350                    <span class="lwptoc_item_number">2.1</span>
351                <span class="lwptoc_item_label">选择 Secure ShellFish 的理由</span>
352    </a>
353    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#lwptoc1">
354                    <span class="lwptoc_item_number">2.1.1</span>
355                <span class="lwptoc_item_label">适配移动设备的使用场景</span>
356    </a>
357    </div><div class="lwptoc_item">    <a href="#TUI_Coding_Agent">
358                    <span class="lwptoc_item_number">2.1.2</span>
359                <span class="lwptoc_item_label">支持丰富的终端特性,适配带有复杂 TUI 的 Coding Agent</span>
360    </a>
361    </div><div class="lwptoc_item">    <a href="#Files_App">
362                    <span class="lwptoc_item_number">2.1.3</span>
363                <span class="lwptoc_item_label">Files App 与第三方代码编辑器支持</span>
364    </a>
365    </div></div></div><div class="lwptoc_item">    <a href="#App">
366                    <span class="lwptoc_item_number">2.2</span>
367                <span class="lwptoc_item_label">备选 App</span>
368    </a>
369    </div></div></div><div class="lwptoc_item">    <a href="#Textastic_Vim">
370                    <span class="lwptoc_item_number">3</span>
371                <span class="lwptoc_item_label">移动端使用 Textastic 代替 Vim 等命令行代码编辑器</span>
372    </a>
373    </div><div class="lwptoc_item">    <a href="#1Password_SSH_Agent_SSH">
374                    <span class="lwptoc_item_number">4</span>
375                <span class="lwptoc_item_label">1Password SSH Agent 与远程 SSH 会话共存</span>
376    </a>
377    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#SSH1">
378                    <span class="lwptoc_item_number">4.1</span>
379                <span class="lwptoc_item_label">SSH 配置文件</span>
380    </a>
381    </div><div class="lwptoc_item">    <a href="#lwptoc2">
382                    <span class="lwptoc_item_number">4.2</span>
383                <span class="lwptoc_item_label">备选方案</span>
384    </a>
385    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#SSH_macOS_Keychain">
386                    <span class="lwptoc_item_number">4.2.1</span>
387                <span class="lwptoc_item_label">方案一:将 SSH 私钥密码保存到 macOS Keychain</span>
388    </a>
389    </div><div class="lwptoc_item">    <a href="#zsh">
390                    <span class="lwptoc_item_number">4.2.2</span>
391                <span class="lwptoc_item_label">方案二:zsh 插件</span>
392    </a>
393    </div></div></div></div></div><div class="lwptoc_item">    <a href="#SSH_Agent_Forwarding_tmux">
394                    <span class="lwptoc_item_number">5</span>
395                <span class="lwptoc_item_label">SSH Agent Forwarding 与 tmux 共存</span>
396    </a>
397    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#SSH_tmux">
398                    <span class="lwptoc_item_number">5.1</span>
399                <span class="lwptoc_item_label">SSH 与 tmux 配置文件</span>
400    </a>
401    </div><div class="lwptoc_item">    <a href="#zsh_tmux">
402                    <span class="lwptoc_item_number">5.2</span>
403                <span class="lwptoc_item_label">备选方案:通过 zsh 插件,从 tmux 同步环境变量</span>
404    </a>
405    </div></div></div><div class="lwptoc_item">    <a href="#Git">
406                    <span class="lwptoc_item_number">6</span>
407                <span class="lwptoc_item_label">Git 提交签名</span>
408    </a>
409    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#GPG_pinentry-mac_Git">
410                    <span class="lwptoc_item_number">6.1</span>
411                <span class="lwptoc_item_label">方案一:使用 GPG + pinentry-mac 为 Git 提交签名</span>
412    </a>
413    </div><div class="lwptoc_item">    <a href="#SSH_Coding_Agent">
414                    <span class="lwptoc_item_number">6.2</span>
415                <span class="lwptoc_item_label">方案二:使用 SSH 签名,同时为 Coding Agent 设置权限,提交代码时询问用户</span>
416    </a>
417    </div></div></div><div class="lwptoc_item">    <a href="#Coding_Agent1">
418                    <span class="lwptoc_item_number">7</span>
419                <span class="lwptoc_item_label">为 Coding Agent 设置合适的权限,兼顾安全性和体验</span>
420    </a>
421    <div class="lwptoc_itemWrap"><div class="lwptoc_item">    <a href="#Codex_CLI">
422                    <span class="lwptoc_item_number">7.1</span>
423                <span class="lwptoc_item_label">Codex CLI 配置文件</span>
424    </a>
425    </div><div class="lwptoc_item">    <a href="#OpenCode1">
426                    <span class="lwptoc_item_number">7.2</span>
427                <span class="lwptoc_item_label">OpenCode 配置文件</span>
428    </a>
429    </div></div></div><div class="lwptoc_item">    <a href="#Shift_Tab">
430                    <span class="lwptoc_item_number">8</span>
431                <span class="lwptoc_item_label">Shift + Tab 快捷键</span>
432    </a>
433    </div><div class="lwptoc_item">    <a href="#lwptoc3">
434                    <span class="lwptoc_item_number">9</span>
435                <span class="lwptoc_item_label">补充信息</span>
436    </a>
437    </div><div class="lwptoc_item">    <a href="#AI">
438                    <span class="lwptoc_item_number">10</span>
439                <span class="lwptoc_item_label">AI 创作与利益相关声明</span>
440    </a>
441    </div></div></div>
442</div></div><h2><span id="Coding_Agent">将 Coding Agent 的通知发送到手机上</span></h2>
443<p>利用碎片时间远程开发,无法像使用电脑那样,盯着屏幕随时观察 CLI Coding Agent 的执行结果,所以我使用下面的 Python 脚本,通过 <a href="https://github.com/Finb/Bark">Bark</a> 将执行结果发送到手机上。</p>
444<p>此脚本同时兼容 Claude Code、Codex 和 OpenCode,并对推送内容做了加密处理,Bark 服务器和 Apple 都无法获取推送内容。</p>
445<p>相关代码也已上传到 GitHub:</p>
446<ul>
447<li><a href="https://github.com/blanboom/bark-notification-for-claude-codex-opencode">GitHub – blanboom/bark-notification-for-claude-codex-opencode: Bark push notifications for Claude Code, Codex CLI, and OpenCode with modern AES-256-GCM encryption</a></li>
448</ul>
449<h3><span id="Bark_CodexClaude_Code_OpenCode">Bark 通知脚本,同时兼容 Codex、Claude Code 和 OpenCode</span></h3>
450<p><code class="" data-line="">notify_claude_codex_bark.py</code></p>
451<pre><code class="language-python" data-line="">#!/usr/bin/env python3
452import base64
453import json
454import sys
455import urllib.parse
456import urllib.request
457
458# Dependency: brew install cryptography
459from cryptography.hazmat.primitives.ciphers.aead import AESGCM
460
461BARK_BASE = &quot;https://api.day.app/xxx&quot;
462ENCRYPTION_KEY = &quot;xxx&quot;
463ENCRYPTION_IV = &quot;xxx&quot;
464
465OPENAI_ICON_URL = &quot;https://images.ctfassets.net/j22is2dtoxu1/intercom-img-d177d076c9a5453052925143/49d5d812b0a6fcc20a14faa8c629d9fb/icon-ios-1024_401x.png&quot;
466# Claude symbol (CC0) from Wikimedia, publicly accessible without auth.
467CLAUDE_ICON_URL = &quot;https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Claude_AI_symbol.svg/960px-Claude_AI_symbol.svg.png&quot;
468# OpenCode icon
469OPENCODE_ICON_URL = &quot;https://opencode.ai/apple-touch-icon.png&quot;
470
471def _load_key_iv():
472    key_bytes = ENCRYPTION_KEY.encode(&quot;utf-8&quot;)
473    if len(key_bytes) != 32:
474        return None, None
475
476    iv_bytes = ENCRYPTION_IV.encode(&quot;utf-8&quot;)
477    if len(iv_bytes) != 12:
478        return None, None
479
480    return key_bytes, iv_bytes
481
482
483def _encrypt_aes_gcm(plaintext: bytes, key: bytes, iv: bytes):
484    aesgcm = AESGCM(key)
485    encrypted = aesgcm.encrypt(iv, plaintext, None)
486    return base64.b64encode(encrypted).decode(&quot;ascii&quot;)
487
488
489def _load_payload() -&gt; dict:
490    if len(sys.argv) &gt; 1:
491        try:
492            return json.loads(sys.argv[1])
493        except json.JSONDecodeError:
494            return {}
495    try:
496        if not sys.stdin.isatty():
497            raw = sys.stdin.read().strip()
498            if raw:
499                return json.loads(raw)
500    except Exception:
501        return {}
502    return {}
503
504
505def _detect_source(payload: dict) -&gt; str:
506    &quot;&quot;&quot;Detect the source of the payload: 'claude', 'opencode', or 'codex'.&quot;&quot;&quot;
507    if payload.get(&quot;hook_event_name&quot;):
508        return &quot;claude&quot;
509    if payload.get(&quot;session_id&quot;) or payload.get(&quot;transcript_path&quot;):
510        return &quot;claude&quot;
511    title = payload.get(&quot;title&quot;) or &quot;&quot;
512    if &quot;Claude&quot; in title:
513        return &quot;claude&quot;
514    if &quot;OpenCode&quot; in title or &quot;opencode&quot; in title.lower():
515        return &quot;opencode&quot;
516    event_type = payload.get(&quot;event&quot;) or payload.get(&quot;type&quot;) or &quot;&quot;
517    if event_type.startswith(&quot;session.&quot;) or event_type in (&quot;session_completed&quot;, &quot;file_edited&quot;):
518        return &quot;opencode&quot;
519    return &quot;codex&quot;
520
521
522def main() -&gt; None:
523    payload = _load_payload()
524    source = _detect_source(payload)
525
526    event_type = (
527        payload.get(&quot;hook_event_name&quot;)
528        or payload.get(&quot;type&quot;)
529        or payload.get(&quot;event&quot;)
530    )
531    if source == &quot;claude&quot;:
532        title = payload.get(&quot;title&quot;) or &quot;Claude Code&quot;
533        icon_url = CLAUDE_ICON_URL
534    elif source == &quot;opencode&quot;:
535        title = payload.get(&quot;title&quot;) or &quot;OpenCode&quot;
536        icon_url = OPENCODE_ICON_URL
537    else:
538        title = payload.get(&quot;title&quot;) or &quot;Codex&quot;
539        icon_url = OPENAI_ICON_URL
540    subtitle = event_type
541    message = (
542        payload.get(&quot;last-assistant-message&quot;)
543        or payload.get(&quot;message&quot;)
544        or payload.get(&quot;summary&quot;)
545    )
546    if not message:
547        cwd = payload.get(&quot;cwd&quot;)
548        if cwd and event_type:
549            message = f&quot;{event_type} in {cwd}&quot;
550        elif cwd:
551            message = f&quot;Event in {cwd}&quot;
552        elif event_type:
553            message = f&quot;Event: {event_type}&quot;
554        else:
555            message = &quot;Event&quot;
556    push_payload = {
557        &quot;title&quot;: title,
558        &quot;markdown&quot;: message,
559        &quot;icon&quot;: icon_url,
560        &quot;action&quot;: &quot;none&quot;,
561    }
562    if subtitle:
563        push_payload[&quot;subtitle&quot;] = subtitle
564    key_bytes, iv_bytes = _load_key_iv()
565    if not key_bytes:
566        return
567
568    plaintext = json.dumps(push_payload, ensure_ascii=False, separators=(&quot;,&quot;, &quot;:&quot;)).encode(
569        &quot;utf-8&quot;
570    )
571    try:
572        ciphertext = _encrypt_aes_gcm(plaintext, key_bytes, iv_bytes)
573    except Exception:
574        return
575    if not ciphertext:
576        return
577
578    form = urllib.parse.urlencode({&quot;ciphertext&quot;: ciphertext, &quot;iv&quot;: ENCRYPTION_IV})
579    req = urllib.request.Request(
580        BARK_BASE,
581        data=form.encode(&quot;utf-8&quot;),
582        headers={&quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;},
583        method=&quot;POST&quot;,
584    )
585    try:
586        with urllib.request.urlopen(req, timeout=5) as response:
587            response.read()
588    except Exception:
589        # Do not block Codex runs on notification failures.
590        return
591
592
593if __name__ == &quot;__main__&quot;:
594    main()
595</code></pre>
596<h3><span id="Codex">Codex 配置文件</span></h3>
597<p><code class="" data-line="">.codex/config.toml</code></p>
598<pre><code class="" data-line="">notify = [&quot;python3&quot;, &quot;/path/to/notify_claude_codex_bark.py&quot;]
599</code></pre>
600<h3><span id="Claude_Code">Claude Code 配置文件</span></h3>
601<p><code class="" data-line="">.claude/settings.json</code></p>
602<pre><code class="language-json" data-line="">{
603  &quot;hooks&quot;: {
604    &quot;Notification&quot;: [
605      {
606        &quot;hooks&quot;: [
607          {
608            &quot;command&quot;: &quot;python3 /path/to/notify_claude_codex_bark.py&quot;,
609            &quot;type&quot;: &quot;command&quot;
610          }
611        ],
612        &quot;matcher&quot;: &quot;&quot;
613      }
614    ]
615  }
616}
617</code></pre>
618<h3><span id="OpenCode">OpenCode 配置文件</span></h3>
619<p><code class="" data-line="">~/.config/opencode/plugin/notify.ts</code></p>
620<pre><code class="" data-line="">import type { Plugin } from &quot;@opencode-ai/plugin&quot;;
621
622const NOTIFY_SCRIPT = &quot;/path/to/notify_claude_codex_bark.py&quot;;
623
624const plugin: Plugin = async ({ client, $ }) =&gt; {
625  const notify = (type: string, message: string) =&gt; {
626    const payload = JSON.stringify({ title: &quot;OpenCode&quot;, type, message });
627    $`echo ${payload} | python3 ${NOTIFY_SCRIPT}`.quiet().catch(() =&gt; {});
628  };
629
630  return {
631    event: async ({ event }) =&gt; {
632      if (event.type === &quot;session.idle&quot;) {
633        const { sessionID } = event.properties;
634        const sessions = await client.session.list({ limit: 50 });
635        const session = sessions.data?.find((s: { id: string }) =&gt; s.id === sessionID);
636        if (!session || session.parentID) return;
637
638        notify(&quot;session.idle&quot;, session.title || &quot;Task completed&quot;);
639      }
640
641      if (event.type === &quot;permission.asked&quot;) {
642        const { permission, patterns } = event.properties;
643        const detail = patterns.length ? `: ${patterns.join(&quot;, &quot;)}` : &quot;&quot;;
644        notify(&quot;permission.asked&quot;, `${permission}${detail}`);
645      }
646    },
647  };
648};
649
650export default plugin;
651
652</code></pre>
653<h3><span id="lwptoc">备选方案</span></h3>
654<p>目前我在 iPhone 和 iPad 上使用的 SSH 终端是 <a href="https://secureshellfish.app/">Secure ShellFish</a>(选择这款终端的原因请见下文),这个 App 也支持用类似 Bark 的方式发送推送通知。</p>
655<h2><span id="SSH">选择合适的 SSH 终端</span></h2>
656<p>为了在移动设备上获得更好的终端体验,我选择使用 <a href="https://secureshellfish.app/">Secure ShellFish</a>。</p>
657<h3><span id="Secure_ShellFish">选择 Secure ShellFish 的理由</span></h3>
658<h4><span id="lwptoc1">适配移动设备的使用场景</span></h4>
659<p>使用移动设备时,经常遇到网络环境变化导致 SSH 断连的问题。Secure ShellFish 内置了优秀的 <a href="https://github.com/tmux/tmux">tmux</a> 支持,可通过 tmux 保持和自动恢复 Shell 会话。</p>
660<p>同时,这款 App 还能在图形化界面上创建、删除、重命名 tmux 会话,或者将 tmux 会话绑定到新的标签页上。</p>
661<p>另外,Secure ShellFish 还是实现了可选的后台保活优化,可通过监听地理位置变化、画中画浮窗等,实现 App 长时间在后台运行。</p>
662<h4><span id="TUI_Coding_Agent">支持丰富的终端特性,适配带有复杂 TUI 的 Coding Agent</span></h4>
663<p>Claude Code、OpenCode、<a href="https://github.com/google-gemini/gemini-cli">Gemini CLI</a> 拥有复杂的 TUI,需要在现代的终端模拟器下,才能更好地工作。</p>
664<p>Secure ShellFish 基于 <a href="https://github.com/migueldeicaza/SwiftTerm">SwiftTerm</a>,支持现代终端特性。同时这款 App 一直在积极更新,例如最近的 2026.4 版本更新,就带来更好的 Claude Code 的兼容性。</p>
665<h4><span id="Files_App">Files App 与第三方代码编辑器支持</span></h4>
666<p>
666Secure ShellFish 支持与 iOS 自带的文件应用整合。能够让文件应用,或者任何第三方代码编辑器通过打开 Mac 上的文件。</p>
667<h3><span id="App">备选 App</span></h3>
668<ul>
669<li><a href="https://blink.sh/">Blink Shell</a>:更专业的 SSH 终端,同时支持 <a href="https://mosh.org/">mosh</a></li>
670</ul>
671<h2><span id="Textastic_Vim">移动端使用 Textastic 代替 Vim 等命令行代码编辑器</span></h2>
672<p>虽然有 AI 帮忙编写和修改代码,但是很多时候,我还是需要临时手动修改代码。</p>
673<p>在 iPhone 等小屏幕设备上,通过软键盘在 SSH 客户端中,使用 Vim 等文本编辑器编辑代码,体验不是很好。</p>
674<p>所以在移动设备上,我使用的代码编辑器是 Textastic:</p>
675<ul>
676<li><a href="https://www.textasticapp.com/iphone.html">Textastic – Text, Code, and Markup Editor with Syntax Highlighting – FTP, SFTP, SSH, Dropbox, WebDAV – for iPhone</a></li>
677</ul>
678<p>Secure ShellFish 内置了 Textastic 集成,在终端中输入 <code class="" data-line="">textastic &lt;文件名&gt;</code>,即可跳转到 Textastic 并打开指定的文件。</p>
679<h2><span id="1Password_SSH_Agent_SSH">1Password SSH Agent 与远程 SSH 会话共存</span></h2>
680<p>我在 Mac 本地使用 <a href="https://developer.1password.com/docs/ssh/agent/">1Password SSH Agent</a> 管理 SSH 私钥,平时执行 <code class="" data-line="">git push</code> 等操作时通过 Touch ID 确认,兼顾了体验和安全性。</p>
681<p>但是在 iPhone 和 iPad 上通过 SSH 远程连接 Mac 时,就无法进行 Touch ID 认证了。对于这个问题,我的解决方法是:</p>
682<ul>
683<li><strong>移动端</strong>:使用支持 Agent Forwarding 的 SSH 客户端(例如 <a href="https://secureshellfish.app/">Secure ShellFish</a> 或 <a href="https://blink.sh/">Blink</a>),将 iPad 侧的 SSH agent 转发到 Mac;</li>
684<li><strong>Mac 端</strong>:修改 SSH 配置文件,仅在当前会话没有可用 SSH agent 时,才回退使用 1Password 的 <code class="" data-line="">IdentityAgent</code>。</li>
685</ul>
686<h3><span id="SSH1">SSH 配置文件</span></h3>
687<p>具体的 SSH 配置文件如下:</p>
688<p><code class="" data-line="">.ssh/config</code></p>
689<pre><code class="" data-line="">/# ------------------------------------------------------------------------------
690# SSH agent 回退策略(1Password 作为 fallback)
691#
692# 触发条件(任一满足即启用 1Password SSH agent):
693#
694#   1. SSH_AUTH_SOCK 未设置
695#      - 当前会话没有可用的 SSH agent
696#
697#   2. SSH_AUTH_SOCK 字符串中包含 &quot;com.apple.launchd&quot;
698#      - launchd / launchctl 启动的临时 socket
699#      - 常见路径示例:
700#          /private/tmp/com.apple.launchd.xxxxxx/Listeners
701#      - 不稳定、不可复用,明确排除
702#
703#   3. SSH_AUTH_SOCK 指向的目标不是一个可用的 socket
704#      - 断掉的符号链接
705#      - 普通文件
706#      - agent 已退出
707#      - 注意:test -S 会自动顺着符号链接判断最终目标
708#
709# 不触发条件(保持现有 agent,不覆盖):
710#
711#   - SSH_AUTH_SOCK 已设置
712#   - 路径不包含 com.apple.launchd
713#   - 且最终目标是一个有效的 socket
714#     (例如:agent 转发、tmux 继承、本地 GUI agent 等)
715#
716# 实现要点:
717#   - Match exec 的命令必须是“单行字符串”
718#   - 通过 shell 返回码控制匹配:
719#       * 返回 0  → Match 生效 → 使用 1Password agent
720#       * 返回非 0 → Match 不生效 → 保持原 agent
721#   - 仅使用 POSIX 工具(sh / test / grep)
722# ------------------------------------------------------------------------------
723
724Match host * exec &quot;sh -lc 'test -z \&quot;$SSH_AUTH_SOCK\&quot; || echo \&quot;$SSH_AUTH_SOCK\&quot; | grep -q com.apple.launchd || ! test -S \&quot;$SSH_AUTH_SOCK\&quot;'&quot;
725    IdentityAgent ~/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock
726</code></pre>
727<h3><span id="lwptoc2">备选方案</span></h3>
728<p>如果不使用 1Password,还有如下两种方法将 SSH 私钥加载到 SSH Agent,不过在首次登录时,都需要额外的输入密码等确认操作。</p>
729<h4><span id="SSH_macOS_Keychain">方案一:将 SSH 私钥密码保存到 macOS Keychain</span></h4>
730<p>参考如下链接。但是 macOS Keychain 不会随着 SSH 登录而自动解锁,需要额外敲命令解锁 Keychain:</p>
731<ul>
732<li><a href="https://apple.stackexchange.com/questions/48502/how-can-i-permanently-add-my-ssh-private-key-to-keyc
732hain-so-it-is-automatically">How can I permanently add my SSH private key to Keychain so it is automatically available to ssh? – Ask Different</a></li>
733</ul>
734<h4><span id="zsh">方案二:zsh 插件</span></h4>
735<p>可使用如下 <a href="https://ohmyz.sh/">Oh My Zsh</a> 插件。但是首次登录时,也需要输入 SSH 私钥密码:</p>
736<ul>
737<li><a href="https://github.com/ohmyzsh/ohmyzsh/blob/master/plugins/ssh-agent/README.md">ohmyzsh/plugins/ssh-agent/README.md at master · ohmyzsh/ohmyzsh · GitHub</a></li>
738</ul>
739<h2><span id="SSH_Agent_Forwarding_tmux">SSH Agent Forwarding 与 tmux 共存</span></h2>
740<p>Secure ShellFish 自带完善的 <a href="https://github.com/tmux/tmux/wiki">tmux</a> 支持,能够解决断线重连后 Shell 会话丢失的问题。</p>
741<p>但是 tmux 与 SSH agent forwarding 共存,会出现这样的问题:</p>
742<ul>
743<li>每次 SSH 连接建立时,转发的 <code class="" data-line="">SSH_AUTH_SOCK</code> 路径可能不同;</li>
744<li>tmux 的会话往往长期存在,如果 tmux 内仍指向旧的 socket,就会出现「重连后 tmux 里 <code class="" data-line="">git push</code> 不工作」的现象。</li>
745</ul>
746<p>对于这个问题,我根据 StackOverflow 上讨论,采用了如下解决方法:</p>
747<ul>
748<li>将 <code class="" data-line="">SSH_AUTH_SOCK</code> 固化为稳定路径,并让 tmux 始终使用该路径</li>
749</ul>
750<h3><span id="SSH_tmux">SSH 与 tmux 配置文件</span></h3>
751<p>具体的配置文件如下:</p>
752<p><code class="" data-line="">~/.ssh/rc</code></p>
753<pre><code class="" data-line="">#!/bin/zsh
754
755# Source - https://stackoverflow.com/a
756# Posted by pymkin, modified by community. See post 'Timeline' for change history
757# Retrieved 2025-12-24, License - CC BY-SA 4.0
758# Fix SSH auth socket location so agent forwarding works with tmux.
759if test &quot;$SSH_AUTH_SOCK&quot; ; then
760  ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
761fi
762</code></pre>
763<p><code class="" data-line="">~/.tmux.conf</code></p>
764<pre><code class="" data-line=""># Source - https://stackoverflow.com/a
765# Posted by pymkin, modified by community. See post 'Timeline' for change history
766# Retrieved 2025-12-24, License - CC BY-SA 4.0
767# fix ssh agent when tmux is detached
768setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
769
770
771# 不要让 client attach 覆盖 SSH_AUTH_SOCK
772set -g update-environment &quot;DISPLAY KRB5CCNAME MSYSTEM SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY&quot;
773</code></pre>
774<p>通过这种方式,tmux 内部不再依赖易变的 socket 路径,重连后也能自然继承新的 agent forwarding。</p>
775<h3><span id="zsh_tmux">备选方案:通过 zsh 插件,从 tmux 同步环境变量</span></h3>
776<p><a href="https://ohmyz.sh/">Oh My Zsh</a> 的 tmux 插件支持通过设置 <code class="" data-line="">ZSH_TMUX_AUTOREFRESH</code> 为 <code class="" data-line="">true</code> 来触发环境变量刷新:</p>
777<ul>
778<li><a href="https://github.com/ohmyzsh/ohmyzsh/blob/master/plugins/tmux/README.md">ohmyzsh/plugins/tmux/README.md at master · ohmyzsh/ohmyzsh · GitHub</a></li>
779</ul>
780<p>此方法更加简单,但是必须在当前命令执行完,执行下一条命令时,才能自动刷新 <code class="" data-line="">SSH_AUTH_SOCK</code> 环境变量。</p>
781<h2><span id="Git">Git 提交签名</span></h2>
782<p>我经常让 CLI Coding Agent 在完成一个任务后自动提交代码,所以代码提交流程应该是没有用户交互的,无需输入密码,或者用 Touch ID 等方式二次确认。</p>
783<p>同时,我也想保留对 <a href="https://git-scm.com/book/ms/v2/Git-Tools-Signing-Your-Work">Git 提交的签名</a>,而且不想在 macOS 文件系统中保持明文私钥。</p>
784<h3><span id="GPG_pinentry-mac_Git">方案一:使用 GPG + pinentry-mac 为 Git 提交签名</span></h3>
785<p>因此我最初选择使用 <a href="https://www.gnupg.org/">GPG(GnuPG)</a> 来做 Git 提交签名,而不是 SSH signing。这是因为在 macOS 上,<a href="https://github.com/GPGTools/pinentry-mac">pinentry-mac</a> 可以 GPG key 的 passphrase 缓存到系统钥匙串。</p>
786<p>pinentry-mac 和 macOS 自带的 SSH Agent 工作原理有差异,在 SSH 远程连接的情况下,也能访问 macOS Keychain 获取 passphrase 并解锁私钥。所以,此方法在使用 SSH 远程连接 Mac,并通过 tmux 运行 CLI Coding Agent 时,AI 也能稳定地在后台持续提交代码,并带上签名。</p>
787<h3><span id="SSH_Coding_Agent">方案二:使用 SSH 签名,同时为 Coding Agent 设置权限,提交代码时询问用户</span></h3>
788<p>本来对我来说,方案一就是最好的方案。但是,最近 pinentry-mac 似乎出现了一些 bug,勾选了保存 passphrase 到 macOS Keychain,也无法自动解锁私钥。我还没找到这个 bug 的具体解决或规避方式。</p>
789<p>所以,现在我暂时使用方案二,为 Coding Agent 设置权限,执行 <code class="" data-line="">git commit</code> 命令时询问用户。</p>
790<p>结合上文中描述的 bark 通知,当我收到权限请求通知时,就回到 SSH 终端手动确认,再结合 SSH Agent Forwarding,也能实现免输密码对 Git 提交进行签名。</p>
791<p>具体的权限设置,请见下一章节。</p>
792<h2><span id="Coding_Agent1">为 Coding Agent 设置合适的权限,兼顾安全性和体验</span></h2>
793<p>目前大部分 CLI Coding Agent 都具有一定的安全措施,能够避免 AI 执行危险或恶意命令。但是这些功能或者默认关闭,或者过于严格,需要一定的设置,才能更好地工作。</p>
794<h3><span id="Codex_CLI">Codex CLI 配置文件</span></h3>
795<p>其中 Codex CLI 默认启用的沙盒机制,对我来说体验最好。在沙盒内调用命令行工具,或者运行 Python 脚本,无需向用户请求权限。只有访问沙盒外的内容时,才会向用户请求权限。</p>
796<p>由于我需要让 Codex 修改完代码后,执行 <code class="" data-line="">xcodebuild</code> 命令编译验证,所以我在 Codex 配置文件中,放行了这条命令:</p>
797<p><code class="" data-line="">~/.codex/rules/default.rules</code></p>
798<pre><code class="language-python" data-line="">prefix_rule(
799    pattern = [&quot;xcodebuild&quot;],
800    decision = &quot;allow&quot;
801) 
802# 目前通过 SSH 对 Git 提交进行签名,需要人工确认,暂时注释掉
803#prefix_rule(
804#    pattern = [&quot;git&quot;, [&quot;add&quot;, &quot;commit&quot;]],
805#    decision = &quot;allow&quot;
806#)
807</code></pre>
808<h3><span id="OpenCode1">OpenCode 配置文件</span></h3>
809<p>对于 OpenCode,则需要更复杂的配置,放行大部分危险程度较低的命令。</p>
810<p><code class="" data-line="">~/.config/opencode/opencode.json</code></p>
811<pre><code class="language-json" data-line="">  &quot;permission&quot;: {
812    &quot;bash&quot;: {
813      &quot;*&quot;: &quot;ask&quot;,
814      &quot;git log*&quot;: &quot;allow&quot;,
815      &quot;git add*&quot;: &quot;allow&quot;,
816      &quot;git status*&quot;: &quot;allow&quot;,
817      &quot;git checkout*&quot;: &quot;allow&quot;,
818      &quot;git branch*&quot;: &quot;allow&quot;,
819      &quot;git diff*&quot;: &quot;allow&quot;,
820      &quot;git show*&quot;: &quot;allow&quot;,
821      &quot;git rev-parse*&quot;: &quot;allow&quot;,
822      &quot;gh repo clone*&quot;: &quot;allow&quot;,
823      &quot;xcodebuild*&quot;: &quot;allow&quot;,
824      &quot;ls*&quot;: &quot;allow&quot;,
825      &quot;head*&quot;: &quot;allow&quot;,
826      &quot;tail*&quot;: &quot;allow&quot;,
827      &quot;rg*&quot;: &quot;allow&quot;,
828      &quot;wc*&quot;: &quot;allow&quot;,
829      &quot;sed*&quot;: &quot;allow&quot;,
830      &quot;grep*&quot;: &quot;allow&quot;,
831      &quot;find*&quot;: &quot;allow&quot;,
832      &quot;cat*&quot;: &quot;allow&quot;,
833      &quot;sort*&quot;: &quot;allow&quot;,
834      &quot;yes*&quot;: &quot;allow&quot;,
835      &quot;echo*&quot;: &quot;allow&quot;,
836      &quot;ast-grep*&quot;: &quot;allow&quot;
837    }
838  }
839</code></pre>
840<blockquote>
841<p>⚠️ <strong>注意</strong>:上述配置只是我个人的配置文件。请谨慎参考。
842即使只允许少量命令自动执行,攻击者依旧可以用这些命令进行恶意行为,例如用 <code class="" data-line="">xcodebuild</code>
842 命令在编译过程中执行任意脚本,或编译运行一个恶意软件。</p>
843</blockquote>
844<h2><span id="Shift_Tab">Shift + Tab 快捷键</span></h2>
845<p>由于 iOS 软键盘的限制,无法在手机上方便地敲 Shift + Tab 快捷键。而这个快捷键,是 Claude Code 中,切换为 Plan 模式需要经常使用的。</p>
846<p>大部分 SSH 终端 App 都支持 Snippets 功能,能够快速输入提前定义好的字符串。对于 Shift + Tab 快捷键,也可以用 Snippets 功能解决。参考如下链接:</p>
847<ul>
848<li><a href="https://github.com/blinksh/blink/discussions/1941">How can I bind Ctrl-Tab and Ctrl-Shift-Tab? · blinksh/blink · Discussion #1941 · GitHub</a></li>
849</ul>
850<p>我在 Secure ShellFish 中,创建了这些用于 Coding Agent 的 Snippet。同时绑定在软键盘的快捷键上,实现一键输入:</p>
851<pre><code class="" data-line=""># Claude Code 的 Shift + Tab 快捷键
852␛[Z
853# OpenCode 的 Ctrl + X,右箭头。用于显示 Sub Agent
854^X␛[C
855# OpenCode 的 Ctrl + X,上箭头。用于显示 Parent Agent
856^X␛[A
857</code></pre>
858<h2><span id="lwptoc3">补充信息</span></h2>
859<p>Codex 和 Claude Code 除了命令行版本,还拥有网页版,Codex 甚至还可以使用 ChatGPT App 在手机上操作,直接修改 GitHub 上的代码。</p>
860<p>另外还有一些工具,能够更方便地在移动端使用 Coding Agent:</p>
861<ul>
862<li><a href="https://www.pocket-agent.xyz">Pocket — Mobile OS for AI Agents</a></li>
863<li><a href="https://happy.engineering">Happy – Claude Code Mobile Client</a></li>
864</ul>
865<p>但这些工具暂时还无法满足我的需求,例如带上 GPG/SSH 签名提交代码。建议读者在参考本文中的脚本和配置之前,先体验一下这些工具。在满足自己需求的情况下,这些工具能提供比 SSH 客户端更好的体验。</p>
866<h2><span id="AI">AI 创作与利益相关声明</span></h2>
867<ul>
868<li>题图使用 AI 生成;</li>
869<li>文中的代码与配置文件,除非注明来源,均在 AI 的辅助下生成;但笔者可以保证这些代码和配置实测可用,而且是自己正在使用的;</li>
870<li>文章初稿是笔者将代码和配置贴给 AI,让 AI 整理出来的;但是笔者对生成结果不满意,所以仅保留文章的整体结构,重写了约 70% 的正文;</li>
871<li>文中提到的「<a href="https://blanboom.org/2025/heif_converter/">HEIF &amp; HEVC 转换器</a>」是笔者开发的付费 App。其余工具均为笔者正在使用的工具,与笔者没有利益关联。</li>
872</ul>
873<p>本文首发于少数派,原文链接:</p>
874<ul>
875<li><a href="https://sspai.com/post/105621">https://sspai.com/post/105621</a></li>
876</ul>
877</div>
878
879
880
881<p class="wp-block-paragraph"></p>
882		</div>
883
884		
885					<div class="entry-tags is-width-constrained "><span class="ct-module-title">标签</span><div class="entry-tags-items"><a href="https://blanboom.org/tag/ai/" rel="tag"><span>#</span> AI</a><a href="https://blanboom.org/tag/ssh/" rel="tag"><span>#</span> SSH</a></div></div>		
886		
887		
888		<nav class="post-navigation is-width-constrained " >
889							<a href="https://blanboom.org/2025/heif_converter/" class="nav-item-prev">
890					<figure class="ct-media-container  "><img width="300" height="169" src="https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6-300x169.png" class="attachment-medium size-medium wp-post-image" alt=""  decoding="async" srcset="https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6-300x169.png 300w, https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6-1024x576.png 1024w, https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6-768x432.png 768w, https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6-1536x864.png 1536w, https://blanboom.org/wp-content/uploads/2025/04/heif_converter_title_6.png 1920w" sizes="auto, (max-width: 300px) 100vw, 300px" itemprop="image" style="aspect-ratio: 1/1;" /><svg width="20px" height="15px" viewBox="0 0 20 15" fill="#ffffff"><polygon points="0,7.5 5.5,13 6.4,12.1 2.4,8.1 20,8.1 20,6.9 2.4,6.9 6.4,2.9 5.5,2 "/></svg></figure>
891					<div class="item-content">
892						<span class="item-label">
893							上一篇:<span>文章</span>						</span>
894
895													<span class="item-title ct-hidden-sm">
896								HEIF &amp; HEVC 转换器 1.0 发布:压缩 iOS 照片库,释放存储空间							</span>
897											</div>
898
899				</a>
900			
901							<div class="nav-item-next"></div>
902			
903		</nav>
904
905	
906	</article>
907
908	
909		
910			</div>
911
912
913		<div class="ct-related-posts-container" >
914		<div class="ct-container">
915	
916		<div
917			class="ct-related-posts"
918					>
919			
920											<h3 class="ct-module-title">
921					相关文章				</h3>
922							
923			
924			<div class="ct-related-posts-items" data-layout="grid">
925							
926				<article  itemscope="itemscope" itemtype="https://schema.org/CreativeWork"><div id="post-3883" class="post-3883 post type-post status-publish format-standard has-post-thumbnail hentry category-experiences tag-ai tag-rss tag-readwise"><a class="ct-media-container" href="https://blanboom.org/2024/readwise-auto-chinese-title/" aria-label="通过自定义 Prompts,让 Readwise Reader 为文章优化标题、添加中文摘要"><img width="768" height="580" src="https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-768x580.png" class="attachment-medium_large size-medium_large wp-post-image" alt="Readwise Reader 在文章摘要区域,为 Hacker News 的每篇文章添加了中文标题"  decoding="async" srcset="https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-768x580.png 768w, https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-300x227.png 300w, https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-1024x773.png 1024w, https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-1536x1160.png 1536w, https://blanboom.org/wp-content/uploads/2024/04/readwise-chinese-title-2048x1546.png 2048w" sizes="auto, (max-width: 768px) 100vw, 768px" itemprop="image" style="aspect-ratio: 16/9;" /></a><h4 class="related-entry-title"><a href="https://blanboom.org/2024/readwise-auto-chinese-title/" rel="bookmark">通过自定义 Prompts,让 Readwise Reader 为文章优化标题、添加中文摘要</a></h4><ul class="entry-meta" data-type="simple:slash" data-id="61f741" ><li class="meta-date" itemprop="datePublished"><time class="ct-meta-element-date" datetime="2024-04-08T22:38:01+08:00">2024-04-08</time></li></ul></div></article>
927							
928				<article  itemscope="itemscope" itemtype="https://schema.org/CreativeWork"><div id="post-3870" class="post-3870 post type-post status-publish format-standard has-post-thumbnail hentry category-experiences tag-google-photos tag-nas"><a class="ct-media-container" href="https://blanboom.org/2024/nas-to-google-photos/" aria-label="通过 Waydroid 自动备份 NAS 照片到 Google Photos"><img width="768" height="432" src="https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title-768x432.png" class="attachment-medium_large size-medium_large wp-post-image" alt=""  decoding="async" srcset="https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title-768x432.png 768w, https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title-300x169.png 300w, https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title-1024x576.png 1024w, https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title-1536x864.png 1536w, https://blanboom.org/wp-content/uploads/2024/03/waydroid_0_title.png 1920w" sizes="auto, (max-width: 768px) 100vw, 768px" itemprop="image" style="aspect-ratio: 16/9;" /></a><h4 class="related-entry-title"><a href="https://blanboom.org/2024/nas-to-google-photos/" rel="bookmark">通过 Waydroid 自动备份 NAS 照片到 Google Photos</a></h4><ul class="entry-meta" data-type="simple:slash" data-id="fd3bfa" ><li class="meta-date" itemprop="datePublished"><time class="ct-meta-element-date" datetime="2024-03-22T23:18:16+08:00">2024-03-22</time></li><li class="meta-comments"><a href="https://blanboom.org/2024/nas-to-google-photos/#comments">2 条评论</a></li></ul></div></article>
929							
930				<article  itemscope="itemscope" itemtype="https://schema.org/CreativeWork"><div id="post-3798" class="post-3798 post type-post status-publish format-standard has-post-thumbnail hentry category-experiences tag-455 tag-logseq"><a class="ct-media-container" href="https://blanboom.org/2023/logseq-yesterday-todo-transfer-to-today/" aria-label="将 Logseq 的昨日待办事项自动转移到今天"><img width="768" height="512" src="https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-768x512.jpg" class="attachment-medium_large size-medium_large wp-post-image" alt=""  decoding="async" srcset="https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-768x512.jpg 768w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-300x200.jpg 300w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-1024x683.jpg 1024w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-1536x1024.jpg 1536w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-2048x1365.jpg 2048w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-360x240.jpg 360w, https://blanboom.org/wp-content/uploads/2023/09/jeshoots-com-9n1USijYJZ4-unsplash-600x400.jpg 600w" sizes="auto, (max-width: 768px) 100vw, 768px" itemprop="image" style="aspect-ratio: 16/9;" /></a><h4 class="related-entry-title"><a href="https://blanboom.org/2023/logseq-yesterday-todo-transfer-to-today/" rel="bookmark">将 Logseq 的昨日待办事项自动转移到今天</a></h4><ul class="entry-meta" data-type="simple:slash" data-id="d916ae" ><li class="meta-date" itemprop="datePublished"><time class="ct-meta-element-date" datetime="2023-09-09T23:18:11+08:00">2023-09-09</time></li></ul></div></article>
931						</div>
932
933			
934					</div>
935
936			</div>
937	</div>
938	
939	<div class="ct-comments-container"><div class="ct-container-narrow">
940
941<div class="ct-comments" id="comments">
942	
943	
944	
945	
946		<div id="respond" class="comment-respond">
947		<h2 id="reply-title" class="comment-reply-title">发表回复<span class="ct-cancel-reply"><a rel="nofollow" id="cancel-comment-reply-link" href="/2026/ssh-cli-coding-agent/#respond" style="display:none;">取消回复</a></span></h2><form action="https://blanboom.org/wp-comments-post.php" method="post" id="commentform" class="comment-form has-website-field has-labels-outside"><p class="comment-notes"><span id="email-notes">您的邮箱地址不会被公开。</span> <span class="required-field-message">必填项已用 <span class="required">*</span> 标注</span></p><p class="comment-form-field-input-author">
948			<label for="author">姓名 <b class="required">&nbsp;*</b></label>
949			<input id="author" name="author" type="text" value="" size="30" required='required'>
950			</p>
951<p class="comment-form-field-input-email">
952				<label for="email">邮箱 <b class="required">&nbsp;*</b></label>
953				<input id="email" name="email" type="text" value="" size="30" required='required'>
954			</p>
955<p class="comment-form-field-input-url">
956				<label for="url">网站</label>
957				<input id="url" name="url" type="text" value="" size="30">
958				</p>
959<p class="comment-form-field-textarea">
960			<label for="comment">添加评论<b class="required">&nbsp;*</b></label>
961			<textarea id="comment" name="comment" cols="45" rows="8" required="required"></textarea>
962		</p>
963<p class="comment-subscription-form"><input type="checkbox" name="subscribe_comments" id="subscribe_comments" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;" /> <label class="subscribe-label" id="subscribe-label" for="subscribe_comments">通过邮件通知我后续评论</label></p><p class="comment-subscription-form"><input type="checkbox" name="subscribe_blog" id="subscribe_blog" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;" /> <label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">通过邮件通知我有新文章</label></p><p class="form-submit"><button type="submit" name="submit" id="submit" class="submit" value="发表评论">发表评论</button> <input type='hidden' name='comment_post_ID' value='4298' id='comment_post_ID' />
964<input type='hidden' name='comment_parent' id='comment_parent' value='0' />
965</p></form>	</div><!-- #respond -->
966	
967	
968</div>
969
970</div></div>	</main>
971
972	<footer id="footer" class="ct-footer" data-id="type-1" itemscope="" itemtype="https://schema.org/WPFooter"><div data-row="bottom"><div class="ct-container"><div data-column="copyright">
973<div
974	class="ct-footer-copyright"
975	data-id="copyright">
976
977	<p>© 2026 <a href="https://blanboom.org" target="_blank" rel="noopener">Blanboom</a> | <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank" rel="noopener">CC BY-NC-SA 4.0</a></p>
978<p>本博客基于 <a href="https://wordpress.org" target="_blank" rel="noopener">WordPress</a> 搭建,使用 <a href="https://creativethemes.com/blocksy/" target="_blank" rel="noopener">Blocksy</a> 主题</p></div>
979</div><div data-column="socials">
980<div
981	class="ct-footer-socials"
982	data-id="socials">
983
984	
985		<div class="ct-social-box" data-color="custom" data-icon-size="custom" data-icons-type="simple" >
986			
987			
988							
989				<a href="https://x.com/blanboom" data-network="twitter" aria-label="X (Twitter)" target="_blank" rel="noopener noreferrer">
990					<span class="ct-icon-container">
991					<svg
992					width="20px"
993					height="20px"
994					viewBox="0 0 20 20"
995					aria-hidden="true">
996						<path d="M2.9 0C1.3 0 0 1.3 0 2.9v14.3C0 18.7 1.3 20 2.9 20h14.3c1.6 0 2.9-1.3 2.9-2.9V2.9C20 1.3 18.7 0 17.1 0H2.9zm13.2 3.8L11.5 9l5.5 7.2h-4.3l-3.3-4.4-3.8 4.4H3.4l5-5.7-5.3-6.7h4.4l3 4 3.5-4h2.1zM14.4 15 6.8 5H5.6l7.7 10h1.1z"/>
997					</svg>
998				</span>				</a>
999							
1000				<a href="https://github.com/blanboom" data-network="github" aria-label="GitHub" target="_blank" rel="noopener noreferrer">
1001					<span class="ct-icon-container">
1002					<svg
1003					width="20"
1004					height="20"
1005					viewBox="0 0 20 20"
1006					aria-hidden="true">
1007						<path d="M8.9,0.4C4.3,0.9,0.6,4.6,0.1,9.1c-0.5,4.7,2.2,8.9,6.3,10.5C6.7,19.7,7,19.5,7,19.1v-1.6c0,0-0.4,0.1-0.9,0.1c-1.4,0-2-1.2-2.1-1.9c-0.1-0.4-0.3-0.7-0.6-1C3.1,14.6,3,14.6,3,14.5c0-0.2,0.3-0.2,0.4-0.2c0.6,0,1.1,0.7,1.3,1c0.5,0.8,1.1,1,1.4,1c0.4,0,0.7-0.1,0.9-0.2c0.1-0.7,0.4-1.4,1-1.8c-2.3-0.5-4-1.8-4-4c0-1.1,0.5-2.2,1.2-3C5.1,7.1,5,6.6,5,5.9c0-0.4,0-1,0.3-1.6c0,0,1.4,0,2.8,1.3C8.6,5.4,9.3,5.3,10,5.3s1.4,0.1,2,0.3c1.3-1.3,2.8-1.3,2.8-1.3C15,4.9,15,5.5,15,5.9c0,0.8-0.1,1.2-0.2,1.4c0.7,0.8,1.2,1.8,1.2,3c0,2.2-1.7,3.5-4,4c0.6,0.5,1,1.4,1,2.3v2.6c0,0.3,0.3,0.6,0.7,0.5c3.7-1.5,6.3-5.1,6.3-9.3C20,4.4,14.9-0.3,8.9,0.4z"/>
1008					</svg>
1009				</span>				</a>
1010							
1011				<a href="https://weibo.com/blanboom" data-network="weibo" aria-label="Weibo" target="_blank" rel="noopener noreferrer">
1012					<span class="ct-icon-container">
1013					<svg
1014					width="20"
1015					height="20"
1016					viewBox="0 0 20 20"
1017					aria-hidden="true">
1018						<path d="M15.9,7.6c0.3-0.9-0.5-1.8-1.5-1.6c-0.9,0.2-1.1-1.1-0.3-1.3c2-0.4,3.6,1.4,3,3.3C16.9,8.8,15.6,8.4,15.9,7.6z M8.4,18.1c-4.2,0-8.4-2-8.4-5.3C0,11,1.1,9,3,7.2c3.9-3.9,7.9-3.9,6.8-0.2c-0.2,0.5,0.5,0.2,0.5,0.2c3.1-1.3,5.5-0.7,4.5,2c-0.1,0.4,0,0.4,0.3,0.5C20.3,11.3,16.4,18.1,8.4,18.1L8.4,18.1zM14,12.4c-0.2-2.2-3.1-3.7-6.4-3.3C4.3,9.4,1.8,11.4,2,13.6s3.1,3.7,6.4,3.3C11.7,16.6,14.2,14.6,14,12.4zM13.6,2c-1,0.2-0.7,1.7,0.3,1.5c2.8-0.6,5.3,2.1,4.4,4.8c-0.3,0.9,1.1,1.4,1.5,0.5C21,4.9,17.6,1.2,13.6,2L13.6,2z M10.5,14.2c-0.7,1.5-2.6,2.3-4.3,1.8c-1.6-0.5-2.3-2.1-1.6-3.5c0.7-1.4,2.5-2.2,4-1.8C10.4,11.1,11.2,12.7,10.5,14.2zM7.2,13c-0.5-0.2-1.2,0-1.5,0.5C5.3,14,5.5,14.6,6,14.8
1018c0.5,0.2,1.2,0,1.5-0.5C7.8,13.8,7.7,13.2,7.2,13zM8.4,12.5c-0.2-0.1-0.4,0-0.6,0.2c-0.1,0.2-0.1,0.4,0.1,0.5c0.2,0.1,0.5,0,0.6-0.2C8.7,12.8,8.6,12.6,8.4,12.5z"/>
1019					</svg>
1020				</span>				</a>
1021							
1022				<a href="https://blanboom.org/feed" data-network="rss" aria-label="RSS" target="_blank" rel="noopener noreferrer">
1023					<span class="ct-icon-container">
1024					<svg
1025					width="20"
1026					height="20"
1027					viewBox="0 0 20 20"
1028					aria-hidden="true">
1029						<path d="M17.9,0H2.1C1,0,0,1,0,2.1v15.7C0,19,1,20,2.1,20h15.7c1.2,0,2.1-1,2.1-2.1V2.1C20,1,19,0,17.9,0z M5,17.1c-1.2,0-2.1-1-2.1-2.1s1-2.1,2.1-2.1s2.1,1,2.1,2.1S6.2,17.1,5,17.1z M12,17.1h-1.5c-0.3,0-0.5-0.2-0.5-0.5c-0.2-3.6-3.1-6.4-6.7-6.7c-0.3,0-0.5-0.2-0.5-0.5V8c0-0.3,0.2-0.5,0.5-0.5c4.9,0.3,8.9,4.2,9.2,9.2C12.6,16.9,12.3,17.1,12,17.1L12,17.1z M16.6,17.1h-1.5c-0.3,0-0.5-0.2-0.5-0.5c-0.2-6.1-5.1-11-11.2-11.2c-0.3,0-0.5-0.2-0.5-0.5V3.4c0-0.3,0.2-0.5,0.5-0.5c7.5,0.3,13.5,6.3,13.8,13.8C17.2,16.9,16.9,17.1,16.6,17.1L16.6,17.1z"/>
1030					</svg>
1031				</span>				</a>
1032							
1033				<a href="https://blanboom.org/newsletter/" data-network="email" aria-label="邮箱" target="_blank" rel="noopener noreferrer">
1034					<span class="ct-icon-container">
1035					<svg
1036					width="20"
1037					height="20"
1038					viewBox="0 0 20 20"
1039					aria-hidden="true">
1040						<path d="M10,10.1L0,4.7C0.1,3.2,1.4,2,3,2h14c1.6,0,2.9,1.2,3,2.8L10,10.1z M10,11.8c-0.1,0-0.2,0-0.4-0.1L0,6.4V15c0,1.7,1.3,3,3,3h4.9h4.3H17c1.7,0,3-1.3,3-3V6.4l-9.6,5.2C10.2,11.7,10.1,11.7,10,11.8z"/>
1041					</svg>
1042				</span>				</a>
1043			
1044			
1045					</div>
1046
1047	</div>
1048
1049</div></div></div></footer></div>
1050
1051<script type="speculationrules">
1052{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/blocksy/*","/*\\?(.+)","/*ao_noptirocket*","/*jetpack=comms*","/*kinsta-monitor*","/*ao_speedup_cachebuster*","/*removed_item*","/my-account*","/wc-api/*","/edd-api/*","/wp-json*"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
1053</script>
vendor: 1 bytes, line 1053
1053
1054<script id="prismatic-prism-js" src="https://blanboom.org/wp-content/plugins/prismatic/lib/prism/js/prism-core.js?ver=3.7.5"></script>
vendor: 1 bytes, line 1054
1054
1055<script id="prismatic-prism-json-js" src="https://blanboom.org/wp-content/plugins/prismatic/lib/prism/js/lang-json.js?ver=3.7.5"></script>
vendor: 1 bytes, line 1055
1055
1056<script id="prismatic-prism-python-js" src="https://blanboom.org/wp-content/plugins/prismatic/lib/prism/js/lang-python.js?ver=3.7.5"></script>
vendor: 1 bytes, line 1056
1056
1057<script id="iawm-link-fixer-front-link-checker-js-extra">
1058var iawmlfArchivedLinks = {"links":"[{\"id\":1699,\"href\":\"https:\\/\\/github.com\\/openai\\/codex\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260120041120\\/https:\\/\\/github.com\\/openai\\/codex\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:05\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:23\",\"http_code\":206},{\"date\":\"2026-03-28 05:03:07\",\"http_code\":206},{\"date\":\"2026-04-19 13:02:47\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-04-19 13:02:47\",\"http_code\":206},\"process\":\"done\"},{\"id\":1700,\"href\":\"https:\\/\\/github.com\\/anthropics\\/claude-code\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260117111106\\/https:\\/\\/github.com\\/anthropics\\/claude-code\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:09\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:23\",\"http_code\":206},{\"date\":\"2026-03-28 05:03:07\",\"http_code\":206},{\"date\":\"2026-04-19 13:02:47\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-04-19 13:02:47\",\"http_code\":206},\"process\":\"done\"},{\"id\":1701,\"href\":\"https:\\/\\/github.com\\/Finb\\/Bark\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260101091151\\/https:\\/\\/github.com\\/Finb\\/Bark\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:11\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:24\",\"http_code\":206},{\"date\":\"2026-03-28 05:03:07\",\"http_code\":206},{\"date\":\"2026-04-19 13:02:48\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-04-19 13:02:48\",\"http_code\":206},\"process\":\"done\"},{\"id\":1702,\"href\":\"https:\\/\\/github.com\\/blanboom\\/bark-notification-for-claude-codex-opencode\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260120131911\\/https:\\/\\/github.com\\/blanboom\\/bark-notification-for-claude-codex-opencode\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 14:59:07\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:35\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:29\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:29\",\"http_code\":206},\"process\":\"done\"},{\"id\":107,\"href\":\"https:\\/\\/secureshellfish.app\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20250823172720\\/https:\\/\\/secureshellfish.app\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2025-11-27 02:21:27\",\"http_code\":206},{\"date\":\"2025-12-04 08:43:28\",\"http_code\":206},{\"date\":\"2025-12-10 09:57:16\",\"http_code\":206},{\"date\":\"2025-12-22 01:37:30\",\"http_code\":206},{\"date\":\"2026-01-01 17:03:28\",\"http_code\":206},{\"date\":\"2026-01-14 18:14:31\",\"http_code\":206},{\"date\":\"2026-01-20 15:55:16\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:46\",\"http_code\":206},{\"date\":\"2026-02-05 20:37:46\",\"http_code\":206},{\"date\":\"2026-02-17 15:42:32\",\"http_code\":206},{\"date\":\"2026-03-04 18:50:53\",\"http_code\":206},{\"date\":\"2026-03-16 05:06:38\",\"http_code\":206},{\"date\":\"2026-03-22 09:58:49\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:34\",\"http_code\":503},{\"date\":\"2026-04-17 21:45:16\",\"http_code\":206},{\"date\":\"2026-04-21 08:47:14\",\"http_code\":503}],\"broken\":false,\"last_checked\":{\"date\":\"2026-04-21 08:47:14\",\"http_code\":503},\"process\":\"done\"},{\"id\":1703,\"href\":\"https:\\/\\/github.com\\/tmux\\/tmux\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260110132322\\/https:\\/\\/github.com\\/tmux\\/tmux\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:15\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:48\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:30\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:30\",\"http_code\":206},\"process\":\"done\"},{\"id\":1704,\"href\":\"https:\\/\\/github.com\\/google-gemini\\/gemini-cli\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260120131911\\/https:\\/\\/github.com\\/google-gemini\\/gemini-cli\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 15:55:11\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:48\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:29\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:29\",\"http_code\":206},\"process\":\"done\"},{\"id\":102,\"href\":\"https:\\/\\/github.com\\/migueldeicaza\\/SwiftTerm\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251003035405\\/https:\\/\\/github.com\\/migueldeicaza\\/SwiftTerm\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2025-11-27 02:21:14\",\"http_code\":206},{\"date\":\"2025-12-04 08:43:20\",\"http_code\":206}
1058,{\"date\":\"2025-12-10 09:57:03\",\"http_code\":206},{\"date\":\"2025-12-22 01:37:22\",\"http_code\":206},{\"date\":\"2026-01-01 17:03:21\",\"http_code\":206},{\"date\":\"2026-01-20 15:55:11\",\"http_code\":206},{\"date\":\"2026-01-26 13:50:48\",\"http_code\":206},{\"date\":\"2026-02-05 20:37:42\",\"http_code\":206},{\"date\":\"2026-02-17 15:42:26\",\"http_code\":206},{\"date\":\"2026-02-26 09:33:33\",\"http_code\":206},{\"date\":\"2026-03-04 18:50:43\",\"http_code\":206},{\"date\":\"2026-03-16 05:06:31\",\"http_code\":206},{\"date\":\"2026-03-22 09:58:48\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:29\",\"http_code\":206},{\"date\":\"2026-04-17 21:45:28\",\"http_code\":206},{\"date\":\"2026-04-21 08:47:08\",\"http_code\":206},{\"date\":\"2026-05-07 21:24:41\",\"http_code\":206},{\"date\":\"2026-05-19 10:29:51\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-05-19 10:29:51\",\"http_code\":206},\"process\":\"done\"},{\"id\":1705,\"href\":\"https:\\/\\/blink.sh\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251227091302\\/https:\\/\\/blink.sh\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:22\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:32\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:32\",\"http_code\":206},\"process\":\"done\"},{\"id\":1706,\"href\":\"https:\\/\\/mosh.org\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260120084537\\/https:\\/\\/mosh.org\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:24\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206},\"process\":\"done\"},{\"id\":1707,\"href\":\"https:\\/\\/www.textasticapp.com\\/iphone.html\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251119092235\\/https:\\/\\/www.textasticapp.com\\/iphone.html\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:27\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:33\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:33\",\"http_code\":206},\"process\":\"done\"},{\"id\":1708,\"href\":\"https:\\/\\/developer.1password.com\\/docs\\/ssh\\/agent\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251230071627\\/https:\\/\\/developer.1password.com\\/docs\\/ssh\\/agent\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:35\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:32\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:32\",\"http_code\":206},\"process\":\"done\"},{\"id\":1709,\"href\":\"https:\\/\\/apple.stackexchange.com\\/questions\\/48502\\/how-can-i-permanently-add-my-ssh-private-key-to-keychain-so-it-is-automatically\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260104105639\\/https:\\/\\/apple.stackexchange.com\\/questions\\/48502\\/how-can-i-permanently-add-my-ssh-private-key-to-keychain-so-it-is-automatically\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:37\",\"http_code\":200},{\"date\":\"2026-03-28 15:44:27\",\"http_code\":200}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:27\",\"http_code\":200},\"process\":\"done\"},{\"id\":1184,\"href\":\"https:\\/\\/ohmyz.sh\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251126221419\\/https:\\/\\/ohmyz.sh\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2025-11-27 04:24:55\",\"http_code\":206},{\"date\":\"2025-12-24 00:47:18\",\"http_code\":206},{\"date\":\"2026-01-20 15:56:49\",\"http_code\":206},{\"date\":\"2026-02-12 05:04:58\",\"http_code\":206},{\"date\":\"2026-02-17 13:15:06\",\"http_code\":206},{\"date\":\"2026-02-20 17:17:35\",\"http_code\":206},{\"date\":\"2026-03-20 13:29:27\",\"http_code\":206},{\"date\":\"2026-03-28 09:21:29\",\"http_code\":206},{\"date\":\"2026-04-12 15:44:31\",\"http_code\":206},{\"date\":\"2026-05-09 04:51:18\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-05-09 04:51:18\",\"http_code\":206},\"process\":\"done\"},{\"id\":1710,\"href\":\"https:\\/\\/github.com\\/ohmyzsh\\/ohmyzsh\\/blob\\/master\\/plugins\\/ssh-agent\\/README.md\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20250317131529\\/https:\\/\\/github.com\\/ohmyzsh\\/ohmyzsh\\/blob\\/master\\/plugins\\/ssh-agent\\/README.md\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:39\",\"http_code\":429},{\"date\":\"2026-03-28 15:44:31\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:31\",\"http_code\":206},\"process\":\"done\"},{\"id\":1711,\"href\":\"https:\\/\\/github.com\\/tmux\\/tmux\\/wiki\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260116235017\\/https:\\/\\/github.com\\/tmux\\/tmux\\/wiki\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:41\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206},\"process\":\"done\"},{\"id\":1712,\"href\":\"https:\\/\\/github.com\\/ohmyzsh\\/ohmyzsh\\/blob\\/master\\/plugins\\/tmux\\/README.md\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20250306223506\\/https:\\/\\/github.com\\/ohmyzsh\\/ohmyzsh\\/blob\\/master\\/plugins\\/tmux\\/README.md\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:44\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:31\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:31\",\"http_code\":206},\"process\":\"done\"},{\"id\":1713,\"href\":\"https:\\/\\/git-scm.com\\/book\\/ms\\/v2\\/Git-Tools-Signing-Your-Work\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251220062411\\/https:\\/\\/git-scm.com\\/book\\/ms\\/v2\\/Git-Tools-Signing-Your-Work\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:49\",\"http_code\":206},{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 15:44:28\",\"http_code\":206},\"process\":\"done\"},{\"id\":1714,\"href\":\"https:\\/\\/www.gnupg.org\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260115152245\\/https:\\/\\/www.gnupg.org\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:53\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:36\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:36\",\"http_code\":206},\"process\":\"done\"},{\"id\":1715,\"href\":\"https:\\/\\/github.com\\/GPGTools\\/pinentry-mac\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20250831080905\\/https:\\/\\/github.com\\/GPGTools\\/pinentry-mac\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:17:55\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:33\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:33\",\"http_code\":206},\"process\":\"done\"},{\"id\":1716,\"href\":\"https:\\/\\/github.com\\/blinksh\\/blink\\/discussions\\/1941\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260120131817\\/https:\\/\\/github.com\\/blinksh\\/blink\\/discussions\\/1941\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 15:57:01\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:33\",\"http_code\":206}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:33\",\"http_code\":206},\"process\":\"done\"},{\"id\":1717,\"href\":\"https:\\/\\/www.pocket-agent.xyz\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20251226193718\\/https:\\/\\/www.pocket-agent.xyz\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:18:04\",\"http_code\":200},{\"date\":\"2026-03-28 23:23:29\",\"http_code\":200}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:29\",\"http_code\":200},\"process\":\"done\"},{\"id\":1718,\"href\":\"https:\\/\\/happy.engineering\",\"archived_href\":\"http:\\/\\/web-wp.archive.org\\/web\\/20260118204409\\/https:\\/\\/happy.engineering\\/\",\"redirect_href\":\"\",\"checks\":[{\"date\":\"2026-01-20 13:18:06\",\"http_code\":206},{\"date\":\"2026-03-28 23:23:35\",\"http_code\":503}],\"broken\":false,\"last_checked\":{\"date\":\"2026-03-28 23:23:35\",\"http_code\":503},\"process\":\"done\"}
1058,{\"id\":1719,\"href\":\"https:\\/\\/sspai.com\\/post\\/105621\",\"archived_href\":\"\",\"redirect_href\":\"\",\"checks\":[],\"broken\":false,\"last_checked\":null,\"process\":\"done\"}]","linkCheckNonce":"22742ea40d","linkDelayInDays":"3","fixerOption":"replace_link","restUrl":"https://blanboom.org/wp-json/iawmlf/v1/link-check"};
1059//# sourceURL=iawm-link-fixer-front-link-checker-js-extra
1060</script>
vendor: 1 bytes, line 1060
1060
1061<script id="iawm-link-fixer-front-link-checker-js" src="https://blanboom.org/wp-content/plugins/internet-archive-wayback-machine-link-fixer/assets/js/build/front_link_checker.js?ver=5b09e1bafa6c3abd7894"></script>
vendor: 1 bytes, line 1061
1061
1062<script id="ct-scripts-js-extra">
1063var ct_localizations = {"ajax_url":"https://blanboom.org/wp-admin/admin-ajax.php","public_url":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/","rest_url":"https://blanboom.org/wp-json/","search_url":"https://blanboom.org/search/QUERY_STRING/","show_more_text":"\u663e\u793a\u66f4\u591a","more_text":"\u66f4\u591a","search_live_results":"\u641c\u7d22\u7ed3\u679c","search_live_no_results":"\u65e0\u7ed3\u679c","search_live_results_closed":"Search results closed.","search_live_no_result":"\u65e0\u7ed3\u679c","search_live_one_result":"\u627e\u5230 %s \u4e2a\u7ed3\u679c\uff0c\u8bf7\u6309 Tab \u952e\u9009\u62e9\u3002","search_live_many_results":"\u627e\u5230 %s \u4e2a\u7ed3\u679c\uff0c\u8bf7\u6309 Tab \u952e\u9009\u62e9\u3002","search_live_stock_status_texts":{"instock":"\u6709\u8d27","outofstock":"\u7f3a\u8d27"},"clipboard_copied":"\u5df2\u590d\u5236\uff01","clipboard_failed":"\u590d\u5236\u5931\u8d25","expand_submenu":"\u5c55\u5f00\u4e0b\u62c9\u83dc\u5355","collapse_submenu":"\u6298\u53e0\u4e0b\u62c9\u83dc\u5355","dynamic_js_chunks":[{"id":"blocksy_sticky_header","selector":"header [data-sticky]","url":"https://blanboom.org/wp-content/plugins/blocksy-companion/static/bundle/sticky.js?ver=2.1.44","version":"2.1.44"}],"dynamic_styles":{"lazy_load":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/non-critical-styles.min.css?ver=2.1.44","search_lazy":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/non-critical-search-styles.min.css?ver=2.1.44","back_to_top":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/back-to-top.min.css?ver=2.1.44"},"dynamic_styles_selectors":[{"selector":".ct-header-cart, #woo-cart-panel","url":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/cart-header-element-lazy.min.css?ver=2.1.44"},{"selector":".flexy","url":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/flexy.min.css?ver=2.1.44"},{"selector":".ct-pagination","url":"https://blanboom.org/wp-content/themes/blocksy/static/bundle/pagination.min.css?ver=2.1.44"},{"selector":"#account-modal","url":"https://blanboom.org/wp-content/plugins/blocksy-companion/static/bundle/header-account-modal-lazy.min.css?ver=2.1.44"},{"selector":".ct-header-account","url":"https://blanboom.org/wp-content/plugins/blocksy-companion/static/bundle/header-account-dropdown-lazy.min.css?ver=2.1.44"}],"login_generic_error_msg":"An unexpected error occurred. Please try again later."};
1064//# sourceURL=ct-scripts-js-extra
1065</script>
vendor: 1 bytes, line 1065
1065
1066<script id="ct-scripts-js" src="https://blanboom.org/wp-content/themes/blocksy/static/bundle/main.js?ver=2.1.44"></script>
vendor: 1 bytes, line 1066
1066
1067<script async data-wp-strategy="async" fetchpriority="low" id="comment-reply-js" src="https://blanboom.org/wp-includes/js/comment-reply.min.js?ver=7.0"></script>
vendor: 1 bytes, line 1067
1067
1068<script id="jetpack-stats-js-before">
1069_stq = window._stq || [];
1070_stq.push([ "view", {"v":"ext","blog":"53782978","post":"4298","tz":"8","srv":"blanboom.org","j":"1:15.8"} ]);
1071_stq.push([ "clickTrackerInit", "53782978", "4298" ]);
1072//# sourceURL=jetpack-stats-js-before
1073</script>
vendor: 1 bytes, line 1073
1073
1074<script data-wp-strategy="defer" defer id="jetpack-stats-js" src="https://stats.wp.com/e-202623.js"></script>
vendor: 1 bytes, line 1074
1074
1075<script id="lwptoc-main-js" src="https://blanboom.org/wp-content/plugins/luckywp-table-of-contents/front/assets/main.min.js?ver=2.1.14"></script>
1075
1076
1077</body>
1078</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.