[{"data":1,"prerenderedAt":6368},["ShallowReactive",2],{"published-article-paths":3,"search-navigation":348,"\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them":421,"\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them-surround":856},[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346],{"path":5},"\u002Fde\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":7},"\u002Fde\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":9},"\u002Fde\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":11},"\u002Fde\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":13},"\u002Fde\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":15},"\u002Fde\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":17},"\u002Fde\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":19},"\u002Fde\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":21},"\u002Fde\u002Farticle\u002Fsetup-antigravity-2",{"path":23},"\u002Fde\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":25},"\u002Fde\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":27},"\u002Fde\u002Farticle\u002Fsync-obsidian-across-devices",{"path":29},"\u002Fde\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":31},"\u002Fde\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":33},"\u002Fde\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":35},"\u002Fde\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":37},"\u002Fen\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":39},"\u002Fen\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":41},"\u002Fen\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":43},"\u002Fen\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":45},"\u002Fen\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":47},"\u002Fen\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":49},"\u002Fen\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":51},"\u002Fen\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":53},"\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":55},"\u002Fen\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":57},"\u002Fen\u002Farticle\u002Fsetup-antigravity-2",{"path":59},"\u002Fen\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":61},"\u002Fen\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":63},"\u002Fen\u002Farticle\u002Fsync-obsidian-across-devices",{"path":65},"\u002Fen\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":67},"\u002Fen\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":69},"\u002Fen\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":71},"\u002Fen\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":73},"\u002Fes\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":75},"\u002Fes\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":77},"\u002Fes\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":79},"\u002Fes\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":81},"\u002Fes\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":83},"\u002Fes\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":85},"\u002Fes\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":87},"\u002Fes\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":89},"\u002Fes\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":91},"\u002Fes\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":93},"\u002Fes\u002Farticle\u002Fsetup-antigravity-2",{"path":95},"\u002Fes\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":97},"\u002Fes\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":99},"\u002Fes\u002Farticle\u002Fsync-obsidian-across-devices",{"path":101},"\u002Fes\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":103},"\u002Fes\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":105},"\u002Fes\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":107},"\u002Fes\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":109},"\u002Ffr\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":111},"\u002Ffr\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":113},"\u002Ffr\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":115},"\u002Ffr\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":117},"\u002Ffr\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":119},"\u002Ffr\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":121},"\u002Ffr\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":123},"\u002Ffr\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":125},"\u002Ffr\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":127},"\u002Ffr\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":129},"\u002Ffr\u002Farticle\u002Fsetup-antigravity-2",{"path":131},"\u002Ffr\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":133},"\u002Ffr\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":135},"\u002Ffr\u002Farticle\u002Fsync-obsidian-across-devices",{"path":137},"\u002Ffr\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":139},"\u002Ffr\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":141},"\u002Ffr\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":143},"\u002Ffr\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":145},"\u002Fid\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":147},"\u002Fid\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":149},"\u002Fid\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":151},"\u002Fid\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":153},"\u002Fid\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":155},"\u002Fid\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":157},"\u002Fid\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":159},"\u002Fid\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":161},"\u002Fid\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":163},"\u002Fid\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":165},"\u002Fid\u002Farticle\u002Fsetup-antigravity-2",{"path":167},"\u002Fid\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":169},"\u002Fid\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":171},"\u002Fid\u002Farticle\u002Fsync-obsidian-across-devices",{"path":173},"\u002Fid\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":175},"\u002Fid\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":177},"\u002Fid\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":179},"\u002Fid\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":181},"\u002Fja\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":183},"\u002Fja\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":185},"\u002Fja\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":187},"\u002Fja\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":189},"\u002Fja\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":191},"\u002Fja\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":193},"\u002Fja\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":195},"\u002Fja\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":197},"\u002Fja\u002Farticle\u002Fsetup-antigravity-2",{"path":199},"\u002Fja\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":201},"\u002Fja\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":203},"\u002Fja\u002Farticle\u002Fsync-obsidian-across-devices",{"path":205},"\u002Fja\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":207},"\u002Fja\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":209},"\u002Fja\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":211},"\u002Fja\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":213},"\u002Fpt\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":215},"\u002Fpt\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":217},"\u002Fpt\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":219},"\u002Fpt\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":221},"\u002Fpt\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":223},"\u002Fpt\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":225},"\u002Fpt\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":227},"\u002Fpt\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":229},"\u002Fpt\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":231},"\u002Fpt\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":233},"\u002Fpt\u002Farticle\u002Fsetup-antigravity-2",{"path":235},"\u002Fpt\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":237},"\u002Fpt\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":239},"\u002Fpt\u002Farticle\u002Fsync-obsidian-across-devices",{"path":241},"\u002Fpt\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":243},"\u002Fpt\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":245},"\u002Fpt\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":247},"\u002Fpt\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":249},"\u002Ftw\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":251},"\u002Ftw\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":253},"\u002Ftw\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":255},"\u002Ftw\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":257},"\u002Ftw\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":259},"\u002Ftw\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":261},"\u002Ftw\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":263},"\u002Ftw\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":265},"\u002Ftw\u002Farticle\u002Fsetup-antigravity-2",{"path":267},"\u002Ftw\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":269},"\u002Ftw\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":271},"\u002Ftw\u002Farticle\u002Fsync-obsidian-across-devices",{"path":273},"\u002Ftw\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":275},"\u002Ftw\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":277},"\u002Ftw\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":279},"\u002Ftw\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":281},"\u002Fvi\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":283},"\u002Fvi\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":285},"\u002Fvi\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":287},"\u002Fvi\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":289},"\u002Fvi\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":291},"\u002Fvi\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":293},"\u002Fvi\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":295},"\u002Fvi\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":297},"\u002Fvi\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":299},"\u002Fvi\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":301},"\u002Fvi\u002Farticle\u002Fsetup-antigravity-2",{"path":303},"\u002Fvi\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":305},"\u002Fvi\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":307},"\u002Fvi\u002Farticle\u002Fsync-obsidian-across-devices",{"path":309},"\u002Fvi\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":311},"\u002Fvi\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":313},"\u002Fvi\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":315},"\u002Fvi\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":317},"\u002Fzh\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":319},"\u002Fzh\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":321},"\u002Fzh\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":323},"\u002Fzh\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":325},"\u002Fzh\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":327},"\u002Fzh\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":329},"\u002Fzh\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":331},"\u002Fzh\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":333},"\u002Fzh\u002Farticle\u002Fsetup-antigravity-2",{"path":335},"\u002Fzh\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":337},"\u002Fzh\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":339},"\u002Fzh\u002Farticle\u002Fsync-obsidian-across-devices",{"path":341},"\u002Fzh\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":343},"\u002Fzh\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":345},"\u002Fzh\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":347},"\u002Fzh\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",[349,353,357,361,365,369,373,377,381,385,389,393,397,401,405,409,413,417],{"title":350,"path":351,"stem":352},"AI Agent Skills: What They Are & How to Create Them","\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them","en\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"title":354,"path":355,"stem":356},"Bringing Buzz to DeepSeek Harness: Taught to Speak Nostr","\u002Farticle\u002Fbringing-buzz-to-deepseek-harness","en\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"title":358,"path":359,"stem":360},"Solving AI Agent Skills Fragmentation with npx skills","\u002Farticle\u002Fcentralised-the-skills-for-agents","en\u002Farticle\u002Fcentralised-the-skills-for-agents",{"title":362,"path":363,"stem":364},"How to Expose Hermes Agent Privately with Cloudflare WARP","\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp","en\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"title":366,"path":367,"stem":368},"How AI Agent Skills Replace Nuxt App Scaffolding Scripts","\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts","en\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"title":370,"path":371,"stem":372},"Stop Exposing Your Vault: Secure NodeWarden with Cloudflare","\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare","en\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"title":374,"path":375,"stem":376},"How to Deploy Hermes Agent on a Linux VPS","\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server","en\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"title":378,"path":379,"stem":380},"Self-Host Your Travel Itineraries with TREK and Docker","\u002Farticle\u002Fself-hosted-travel-planner-trek","en\u002Farticle\u002Fself-hosted-travel-planner-trek",{"title":382,"path":383,"stem":384},"Self-Host Block's Buzz: Shared AI Agent Workspace","\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues","en\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"title":386,"path":387,"stem":388},"How to Self-Host a BitWarden Compatible Server Nodewarden","\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare","en\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"title":390,"path":391,"stem":392},"Google Antigravity 2 Hands-On: Setup & First Impressions","\u002Farticle\u002Fsetup-antigravity-2","en\u002Farticle\u002Fsetup-antigravity-2",{"title":394,"path":395,"stem":396},"NetSuite AI Connector Guide: MCP Setup & Use Cases","\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude","en\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"title":398,"path":399,"stem":400},"Switch Between Multiple Cloudflare WARP Orgs on Mac","\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac","en\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"title":402,"path":403,"stem":404},"How to Sync Obsidian Vaults Across Devices Securely","\u002Farticle\u002Fsync-obsidian-across-devices","en\u002Farticle\u002Fsync-obsidian-across-devices",{"title":406,"path":407,"stem":408},"Testing Claude Fable 5: A Financial Analysis Review","\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis","en\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"title":410,"path":411,"stem":412},"Guide to Browser and Scheduler in Antigravity 2","\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2","en\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"title":414,"path":415,"stem":416},"Build a Persistent AI Memory System on Cloudflare","\u002Farticle\u002Fuse-cloudflare-as-ai-memory","en\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"title":418,"path":419,"stem":420},"Antigravity 2 in Action: AI Agents, Skills, and MCP","\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2","en\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"id":422,"title":350,"author":423,"body":424,"category":835,"date":837,"description":838,"extension":839,"image":840,"imageAlt":841,"isPublished":512,"meta":842,"minRead":504,"navigation":512,"path":37,"seo":848,"stem":352,"tags":849,"updatedAt":854,"__hash__":855},"article\u002Fen\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them.md","",{"type":425,"value":426,"toc":825},"minimark",[427,432,446,459,542,548,552,555,564,571,576,634,645,651,654,706,710,713,720,723,735,739,783,786,803,807,818,821],[428,429,431],"h2",{"id":430},"what-is-an-ai-agent-skill","What Is an AI Agent Skill?",[433,434,435,436,440,441,445],"p",{},"An agent skill is a reusable ",[437,438,439],"strong",{},"set of instructions"," — a standardised procedure that tells an agent how to do a particular kind of task well. It consists of a single Markdown file, ",[442,443,444],"code",{},"SKILL.md",", and can bundle any other files the task requires, such as reference documents, templates, or executable scripts.",[433,447,448,449,458],{},"Take the ",[450,451,455],"a",{"href":452,"rel":453},"https:\u002F\u002Fgithub.com\u002Fmattpocock\u002Fskills\u002Fblob\u002F733d312884b3878a9a9cff693c5886943753a741\u002Fskills\u002Fproductivity\u002Fgrill-me\u002FSKILL.md",[454],"nofollow",[442,456,457],{},"grill-me"," skill as an example:",[460,461,465],"pre",{"className":462,"code":463,"language":464,"meta":423,"style":423},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","---\nname: grill-me\ndescription: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions \"grill me\".\n---\n\nInterview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.\n\nAsk the questions one at a time.\n\nIf a question can be answered by exploring the codebase, explore the codebase instead.\n","yaml",[442,466,467,476,491,502,507,514,520,525,531,536],{"__ignoreMap":423},[468,469,472],"span",{"class":470,"line":471},"line",1,[468,473,475],{"class":474},"sBMFI","---\n",[468,477,479,483,487],{"class":470,"line":478},2,[468,480,482],{"class":481},"swJcz","name",[468,484,486],{"class":485},"sMK4o",":",[468,488,490],{"class":489},"sfazB"," grill-me\n",[468,492,494,497,499],{"class":470,"line":493},3,[468,495,496],{"class":481},"description",[468,498,486],{"class":485},[468,500,501],{"class":489}," Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions \"grill me\".\n",[468,503,505],{"class":470,"line":504},4,[468,506,475],{"class":474},[468,508,510],{"class":470,"line":509},5,[468,511,513],{"emptyLinePlaceholder":512},true,"\n",[468,515,517],{"class":470,"line":516},6,[468,518,519],{"class":489},"Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.\n",[468,521,523],{"class":470,"line":522},7,[468,524,513],{"emptyLinePlaceholder":512},[468,526,528],{"class":470,"line":527},8,[468,529,530],{"class":489},"Ask the questions one at a time.\n",[468,532,534],{"class":470,"line":533},9,[468,535,513],{"emptyLinePlaceholder":512},[468,537,539],{"class":470,"line":538},10,[468,540,541],{"class":489},"If a question can be answered by exploring the codebase, explore the codebase instead.\n",[433,543,544,545,547],{},"A ",[442,546,444],{}," file contains a small block of metadata and a body of instructions. The metadata consists of the skill's name and description, which the AI agent loads at startup.",[428,549,551],{"id":550},"how-ai-agent-skills-work-progressive-disclosure","How AI Agent Skills Work: Progressive Disclosure",[433,553,554],{},"Initially, only the name and description are loaded into the context. When a user's request matches a skill's description, the body of instructions is loaded into the same context.",[433,556,557,558,563],{},"Let's look at how the ",[450,559,561],{"href":452,"rel":560},[454],[442,562,457],{}," skill is used.",[433,565,566],{},[567,568],"img",{"alt":569,"src":570},"Sequence diagram illustrating the progressive disclosure mechanism for executing AI agent skills","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FAI%20Agent%20Skills%20What%20They%20Are%20%26%20How%20to%20Create%20Them\u002Fai-agent-skill-progressive-disclosure-sequence-diagram.webp",[572,573,575],"h3",{"id":574},"step-by-step","Step-by-Step",[577,578,579,586,592,598,604,618,628],"ol",{},[580,581,582,585],"li",{},[437,583,584],{},"Request"," — The user asks the agent for something (\"grill me on my workflow design\").",[580,587,588,591],{},[437,589,590],{},"Selection prompt"," — The user's request, along with the descriptions of all available skills, is sent to the LLM.",[580,593,594,597],{},[437,595,596],{},"LLM selects"," — The LLM compares the request to each description and returns the skill(s) that match.",[580,599,600,603],{},[437,601,602],{},"Confirmation"," — The agent surfaces the proposed skill(s) back to the user, who confirms (or rejects\u002Fadjusts) the choice.",[580,605,606,609,610,614,615,617],{},[437,607,608],{},"Instructions loaded"," — The agent fetches the ",[611,612,613],"em",{},"full"," instructions for the confirmed skill: the ",[442,616,444],{}," body.",[580,619,620,623,624,627],{},[437,621,622],{},"Execution prompt"," — The user's request ",[437,625,626],{},"plus the selected skill's instructions"," is sent to the LLM.",[580,629,630,633],{},[437,631,632],{},"Response"," — The LLM produces the output, which is the first grilling question.",[433,635,636,637,644],{},"Now let's use ",[450,638,641],{"href":639,"rel":640},"https:\u002F\u002Fgithub.com\u002Fcoleam00\u002Fexcalidraw-diagram-skill",[454],[442,642,643],{},"excalidraw-diagram-skill"," to illustrate how a skill with a reference document is used:",[433,646,647],{},[567,648],{"alt":649,"src":650},"Sequence diagram showing an AI agent executing a skill loaded with external reference files and templates","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FAI%20Agent%20Skills%20What%20They%20Are%20%26%20How%20to%20Create%20Them\u002Fai-agent-skill-with-reference-files-sequence-diagram.webp",[572,652,575],{"id":653},"step-by-step-1",[577,655,656,661,665,674,678,690,697],{},[580,657,658,660],{},[437,659,584],{}," — The user asks the agent for something (\"draw the workflow of the deployment process\").",[580,662,663,591],{},[437,664,590],{},[580,666,667,669,670,673],{},[437,668,596],{}," — The LLM compares the request to each description and returns the skill(s) that match. Here, \"draw the workflow\" matches the ",[442,671,672],{},"excalidraw-diagram"," description, so it is selected.",[580,675,676,603],{},[437,677,602],{},[580,679,680,609,682,614,684,686,687,689],{},[437,681,608],{},[611,683,613],{},[442,685,444],{}," body and any referenced files (for ",[442,688,672],{},", that includes the colour palette, JSON schema, and element templates).",[580,691,692,623,694,696],{},[437,693,622],{},[437,695,626],{}," is sent to the LLM. The model now has the detailed methodology it needs.",[580,698,699,701,702,705],{},[437,700,632],{}," — The LLM produces the output (an ",[442,703,704],{},".excalidraw"," JSON file), which the agent returns to the user.",[428,707,709],{"id":708},"ai-agent-skills-vs-tools-and-mcp","AI Agent Skills vs. Tools and MCP",[433,711,712],{},"Skills don't replace prompts, tools, or MCP. Tools and MCP integrations extend an agent's reach to external systems — querying a database, calling an API, and so on. Skills deepen the agent's know-how for completing a task.",[433,714,715,716,719],{},"An MCP such as the ",[450,717,718],{"href":395},"NetSuite MCP"," lets an agent answer user questions by accessing live financial and operational data in NetSuite. Then a NetSuite operational-reporting skill, in turn, guides the agent on how to compose that report and present the answer as a report to the user.",[433,721,722],{},"Some scenarios for using skills include:",[724,725,726,729,732],"ul",{},[580,727,728],{},"Multi-step workflows",[580,730,731],{},"Processing documents, such as extracting data from PDFs",[580,733,734],{},"Code-generation standards",[428,736,738],{"id":737},"how-to-create-ai-agent-skills","How to Create AI Agent Skills",[577,740,741,751,765,774],{},[580,742,743,746,747,750],{},[437,744,745],{},"Create a folder"," named for the skill (e.g. ",[442,748,749],{},"netsuite-operation-report\u002F",").",[580,752,753,758,759,761,762,764],{},[437,754,755,756],{},"Write ",[442,757,444],{}," with a ",[442,760,482],{},", a sharp ",[442,763,496],{},", and a concise body of instructions (under 200 words).",[580,766,767,770,771,773],{},[437,768,769],{},"Add resources"," the task needs — reference docs, templates, scripts. Keep ",[442,772,444],{}," short and link out to the details.",[580,775,776,779,780,782],{},[437,777,778],{},"Install it"," where agents will discover it. Refer to ",[450,781,358],{"href":359}," for how to manage skills across multiple agents.",[433,784,785],{},"A few tips for writing good skills:",[724,787,788,791,797,800],{},[580,789,790],{},"Write the description for the trigger, not the human.",[580,792,793,794,796],{},"Keep ",[442,795,444],{}," lean — under 200 words. Put the general case in the body; leave the edge cases to reference documents.",[580,798,799],{},"Use scripts for anything deterministic. Don't ask the LLM to do arithmetic.",[580,801,802],{},"Version it. Check it into git.",[428,804,806],{"id":805},"conclusion","Conclusion",[433,808,809,810,813,814,817],{},"Unlike tools and MCP, which define ",[611,811,812],{},"what to connect to",", agent skills package ",[611,815,816],{},"how to do the work",". They are an essential complement, not a replacement.",[433,819,820],{},"By leveraging progressive disclosure, skills keep your agent's context window clean and efficient — loading detailed instructions, reference documents, and executable scripts only when a user's request triggers them.",[822,823,824],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":478,"depth":493,"links":826},[827,828,832,833,834],{"id":430,"depth":478,"text":431},{"id":550,"depth":478,"text":551,"children":829},[830,831],{"id":574,"depth":493,"text":575},{"id":653,"depth":493,"text":575},{"id":708,"depth":478,"text":709},{"id":737,"depth":478,"text":738},{"id":805,"depth":478,"text":806},[836],"ai-agents","2026-06-26","Discover what AI agent skills are, how progressive disclosure works, and learn to build custom reusable skills.","md","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FAI%20Agent%20Skills%20What%20They%20Are%20%26%20How%20to%20Create%20Them\u002FEN-AI-Agent-Skills-What-They-Are-%26-How-to-Create-Them.webp","AI Agent Skills Guide: How to Build Reusable Workflows",{"schemaOrg":843,"robots":846,"sitemap":847},[844],{"@type":845,"headline":350,"description":838},"HowTo","index, follow",{"lastmod":837},{"title":841,"description":838,"ogTitle":350,"ogDescription":838,"twitterTitle":350,"twitterDescription":838},[850,851,852,853],"AI Agents","Agent Skills","Reusable Workflows","AI Tutorial",null,"KB_UqaFeAxxEkCKJGNsZFWECf41haD9D0uv9jcvrFz8",{"surround":857,"related":2089},[858,1529],{"id":859,"title":374,"author":423,"body":860,"category":1501,"date":1502,"description":1503,"extension":839,"image":1504,"imageAlt":1505,"isPublished":512,"meta":1506,"minRead":509,"navigation":512,"path":375,"seo":1521,"stem":376,"tags":1523,"updatedAt":854,"__hash__":1528},"article\u002Fen\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server.md",{"type":425,"value":861,"toc":1490},[862,866,869,872,876,880,883,898,904,907,937,944,973,980,985,1000,1012,1020,1025,1043,1047,1050,1072,1078,1081,1093,1104,1115,1146,1150,1161,1171,1182,1192,1199,1209,1215,1243,1259,1263,1269,1281,1286,1323,1327,1330,1346,1352,1431,1434,1482,1484,1487],[428,863,865],{"id":864},"why-host-hermes-agent-on-a-remote-vps","Why Host Hermes Agent on a Remote VPS?",[433,867,868],{},"Since the Hermes Agent is capable of running background tasks, scheduling tasks, and responding to webhook calls, we need a machine to be on standby 24\u002F7. Local machines can lose power, get disconnected from Internet or having the resources maxed out. A remote server guarantees 99% uptime and makes it easy to scale computation resources when needed.",[433,870,871],{},"There are several affordable virtual private server(VPS)) providers out there such as Hetzner, Hostinger and Contabo. We have been using Contabo for a while, and so far so good.",[428,873,875],{"id":874},"how-to-set-up-hermes-agent-on-a-linux-vps","How to Set Up Hermes Agent on a Linux VPS",[572,877,879],{"id":878},"step-1-connect-to-your-vps","Step 1: Connect to Your VPS",[433,881,882],{},"Open the terminal and SSH into your remote machine:",[460,884,888],{"className":885,"code":886,"language":887,"meta":423,"style":423},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ssh root@your_server_ip\n","bash",[442,889,890],{"__ignoreMap":423},[468,891,892,895],{"class":470,"line":471},[468,893,894],{"class":474},"ssh",[468,896,897],{"class":489}," root@your_server_ip\n",[433,899,900],{},[567,901],{"alt":902,"src":903},"SSH connection to the Linux VPS server in terminal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fvps-terminal-ssh-connection.webp",[433,905,906],{},"Ensure your server packages are up to date:",[460,908,910],{"className":885,"code":909,"language":887,"meta":423,"style":423},"sudo apt update && sudo apt upgrade -y\n",[442,911,912],{"__ignoreMap":423},[468,913,914,917,920,923,926,929,931,934],{"class":470,"line":471},[468,915,916],{"class":474},"sudo",[468,918,919],{"class":489}," apt",[468,921,922],{"class":489}," update",[468,924,925],{"class":485}," &&",[468,927,928],{"class":474}," sudo",[468,930,919],{"class":489},[468,932,933],{"class":489}," upgrade",[468,935,936],{"class":489}," -y\n",[433,938,939,940,943],{},"Add a new user, ",[442,941,942],{},"hermes",", or your preferred username:",[460,945,947],{"className":885,"code":946,"language":887,"meta":423,"style":423},"sudo adduser hermes \nsudo passwd hermes\n",[442,948,949,963],{"__ignoreMap":423},[468,950,951,953,956,959],{"class":470,"line":471},[468,952,916],{"class":474},[468,954,955],{"class":489}," adduser",[468,957,958],{"class":489}," hermes",[468,960,962],{"class":961},"sTEyZ"," \n",[468,964,965,967,970],{"class":470,"line":478},[468,966,916],{"class":474},[468,968,969],{"class":489}," passwd",[468,971,972],{"class":489}," hermes\n",[433,974,975,976,979],{},"Turn off ",[442,977,978],{},"root"," password login:",[577,981,982],{},[580,983,984],{},"Open the SSH configuration file:",[460,986,988],{"className":885,"code":987,"language":887,"meta":423,"style":423},"sudo nano \u002Fetc\u002Fssh\u002Fsshd_config\n",[442,989,990],{"__ignoreMap":423},[468,991,992,994,997],{"class":470,"line":471},[468,993,916],{"class":474},[468,995,996],{"class":489}," nano",[468,998,999],{"class":489}," \u002Fetc\u002Fssh\u002Fsshd_config\n",[577,1001,1002],{"start":478},[580,1003,1004,1005,1008,1009,486],{},"Locate the ",[442,1006,1007],{},"PermitRootLogin"," line and change its value to ",[442,1010,1011],{},"no",[460,1013,1018],{"className":1014,"code":1016,"language":1017,"meta":423},[1015],"language-text","PermitRootLogin no\n","text",[442,1019,1016],{"__ignoreMap":423},[577,1021,1022],{"start":493},[580,1023,1024],{},"Save the file and restart the SSH service:",[460,1026,1028],{"className":885,"code":1027,"language":887,"meta":423,"style":423},"sudo systemctl restart ssh\n",[442,1029,1030],{"__ignoreMap":423},[468,1031,1032,1034,1037,1040],{"class":470,"line":471},[468,1033,916],{"class":474},[468,1035,1036],{"class":489}," systemctl",[468,1038,1039],{"class":489}," restart",[468,1041,1042],{"class":489}," ssh\n",[572,1044,1046],{"id":1045},"step-2-install-hermes-agent","Step 2: Install Hermes Agent",[433,1048,1049],{},"Run the following command:",[460,1051,1053],{"className":885,"code":1052,"language":887,"meta":423,"style":423},"curl -fsSL https:\u002F\u002Fhermes-agent.nousresearch.com\u002Finstall.sh | bash\n",[442,1054,1055],{"__ignoreMap":423},[468,1056,1057,1060,1063,1066,1069],{"class":470,"line":471},[468,1058,1059],{"class":474},"curl",[468,1061,1062],{"class":489}," -fsSL",[468,1064,1065],{"class":489}," https:\u002F\u002Fhermes-agent.nousresearch.com\u002Finstall.sh",[468,1067,1068],{"class":485}," |",[468,1070,1071],{"class":474}," bash\n",[433,1073,1074],{},[567,1075],{"alt":1076,"src":1077},"Running the Hermes Agent installation script in terminal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-agent-installation-terminal.webp",[433,1079,1080],{},"Once installed, verify the installation by typing:",[460,1082,1084],{"className":885,"code":1083,"language":887,"meta":423,"style":423},"hermes --version\n",[442,1085,1086],{"__ignoreMap":423},[468,1087,1088,1090],{"class":470,"line":471},[468,1089,942],{"class":474},[468,1091,1092],{"class":489}," --version\n",[433,1094,1095,1096,1099,1100],{},"Run ",[442,1097,1098],{},"hermes setup"," to configure the Hermes Agent:\n",[567,1101],{"alt":1102,"src":1103},"Running the hermes setup command in terminal to start configuration","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-agent-setup-wizard.webp",[433,1105,1106,1107,1110,1111],{},"Select an LLM provider, start with ",[442,1108,1109],{},"DeepSeek"," and add others later.\n",[567,1112],{"alt":1113,"src":1114},"Selecting DeepSeek as the LLM provider in Hermes setup","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-llm-provider-selection.webp",[433,1116,1117,1118,1120,1121,1125,1129,1130,1133,1134,1129,1138,1141,1142],{},"Enter ",[442,1119,1109],{},"API key:\n",[567,1122],{"alt":1123,"src":1124},"Entering the DeepSeek API key in the terminal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-enter-api-key.webp",[567,1126],{"alt":1127,"src":1128},"Successful confirmation of the LLM provider API key","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-api-key-success.webp","\nSelect ",[442,1131,1132],{},"local machine"," for running the Hermes Agent:\n",[567,1135],{"alt":1136,"src":1137},"Selecting local machine for Hermes Agent execution environment","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-select-local-machine.webp",[442,1139,1140],{},"Telegram"," in the channels. Other channels can be configured later.\n",[567,1143],{"alt":1144,"src":1145},"Selecting Telegram as the communication channel in Hermes setup","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-select-telegram-channel.webp",[572,1147,1149],{"id":1148},"step-3-integrating-with-telegram","Step 3: Integrating with Telegram",[433,1151,1152,1153,1156,1157],{},"Select ",[442,1154,1155],{},"[2]"," for using Telegram bot.\n",[567,1158],{"alt":1159,"src":1160},"Selecting option to configure Telegram bot integration","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-bot-integration-option.webp",[433,1162,1163,1164,1166,1167],{},"Head to ",[442,1165,1140],{}," and search for 'BotFather'.\n",[567,1168],{"alt":1169,"src":1170},"Searching for BotFather in the Telegram application","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-search-botfather.webp",[433,1172,1173,1174,1177,1178],{},"Click ",[442,1175,1176],{},"Open"," to open 'BotFather'.\n",[567,1179],{"alt":1180,"src":1181},"Opening the chat interface with BotFather on Telegram","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-open-botfather-chat.webp",[433,1183,1173,1184,1187,1188],{},[442,1185,1186],{},"Create a New Bot",".\n",[567,1189],{"alt":1190,"src":1191},"Sending newbot command to BotFather to create a new Telegram bot","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fbotfather-create-new-bot.webp",[433,1193,1194,1195],{},"Fill in the names and create the bot.\n",[567,1196],{"alt":1197,"src":1198},"Configuring the name and username for the new Telegram bot","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fbotfather-bot-details-configured.webp",[433,1200,1173,1201,1204,1205],{},[442,1202,1203],{},"Copy"," to copy the token and paste it back to the terminal.\n",[567,1206],{"alt":1207,"src":1208},"Copying the HTTP API token of the newly created Telegram bot","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fbotfather-copy-http-api-token.webp",[433,1210,1211,1212,1214],{},"Find the ",[442,1213,1140],{}," user account ID and add it to the 'Allowed user list':",[724,1216,1217,1226,1240],{},[580,1218,1219,1220,1222],{},"Search '@raw_data_bot' on ",[442,1221,1140],{},[567,1223],{"alt":1224,"src":1225},"Searching for raw data bot on Telegram to retrieve user ID","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-search-raw-data-bot.webp",[580,1227,1228,1229,1232,1233,1187,1236],{},"Click on ",[442,1230,1231],{},"RawDataBot"," then click Start button. The user ID will be shown behind ",[442,1234,1235],{},"P.S. Your ID:",[567,1237],{"alt":1238,"src":1239},"Starting RawDataBot to view the user account ID","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-raw-data-bot-user-id.webp",[580,1241,1242],{},"Copy the user ID and paste to the terminal.",[433,1244,1245,1246,1250,1251,1255],{},"Since we are running on the cloud, we want the service to be started automatically.\n",[567,1247],{"alt":1248,"src":1249},"Configuring the autostart option for Hermes systemd service","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-autostart-service-option.webp","\nLeave everything as default:\n",[567,1252],{"alt":1253,"src":1254},"Leaving setup configurations as default values in terminal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-leave-defaults-1.webp",[567,1256],{"alt":1257,"src":1258},"Completing the default setup options in Hermes configuration","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Fhermes-setup-leave-defaults-2.webp",[428,1260,1262],{"id":1261},"testing-your-hermes-agent-with-telegram-bot","Testing Your Hermes Agent with Telegram Bot",[433,1264,1265,1266,486],{},"Run the following command to start the ",[442,1267,1268],{},"hermes gateway",[460,1270,1272],{"className":885,"code":1271,"language":887,"meta":423,"style":423},"hermes gateway\n",[442,1273,1274],{"__ignoreMap":423},[468,1275,1276,1278],{"class":470,"line":471},[468,1277,942],{"class":474},[468,1279,1280],{"class":489}," gateway\n",[433,1282,1163,1283,1285],{},[442,1284,1140],{}," and add the created bot, '@tech_cloud_hermes_bot', to our chats.",[724,1287,1288,1302,1313],{},[580,1289,1290,1291,1293,1294,1297,1298],{},"type '\u002Fnew' in ",[442,1292,1140],{}," to start a new ",[442,1295,1296],{},"Hermes Agent"," session.\n",[567,1299],{"alt":1300,"src":1301},"Typing new command in Telegram to start a new Hermes Agent session","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-chat-hermes-new-session.webp",[580,1303,1304,1305,1308,1309],{},"type ",[442,1306,1307],{},"\u002Fcommands"," will list all available commands.\n",[567,1310],{"alt":1311,"src":1312},"Typing commands in Telegram to view available Hermes instructions","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-chat-hermes-commands-list.webp",[580,1314,1304,1315,1318,1319],{},[442,1316,1317],{},"\u002Fmodel"," to see a list of available LLMs.\n",[567,1320],{"alt":1321,"src":1322},"Typing model in Telegram to see the list of active LLMs","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002Ftelegram-chat-hermes-model-selection.webp",[428,1324,1326],{"id":1325},"running-hermes-gateway-as-a-background-service","Running Hermes Gateway as a Background Service",[433,1328,1329],{},"Create service file:",[460,1331,1335],{"className":1332,"code":1333,"language":1334,"meta":423,"style":423},"language-shell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sudo nano \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-gateway.service\n","shell",[442,1336,1337],{"__ignoreMap":423},[468,1338,1339,1341,1343],{"class":470,"line":471},[468,1340,916],{"class":474},[468,1342,996],{"class":489},[468,1344,1345],{"class":489}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-gateway.service\n",[433,1347,1348,1349,1351],{},"Paste the following, replace ",[442,1350,942],{}," in '\u002Fhome\u002Fhermes' with your preferred username:",[460,1353,1357],{"className":1354,"code":1355,"language":1356,"meta":423,"style":423},"language-ini shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[Unit]\nDescription=Hermes Gateway\nAfter=network.target\n\n[Service]\nUser=hermes\nWorkingDirectory=\u002Fhome\u002Fhermes\nExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes gateway\nRestart=always\nRestartSec=10\nEnvironment=PATH=\u002Fhome\u002Fhermes\u002F.local\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin\n\n[Install]\nWantedBy=multi-user.target\n","ini",[442,1358,1359,1364,1369,1374,1378,1383,1388,1393,1398,1403,1408,1414,1419,1425],{"__ignoreMap":423},[468,1360,1361],{"class":470,"line":471},[468,1362,1363],{},"[Unit]\n",[468,1365,1366],{"class":470,"line":478},[468,1367,1368],{},"Description=Hermes Gateway\n",[468,1370,1371],{"class":470,"line":493},[468,1372,1373],{},"After=network.target\n",[468,1375,1376],{"class":470,"line":504},[468,1377,513],{"emptyLinePlaceholder":512},[468,1379,1380],{"class":470,"line":509},[468,1381,1382],{},"[Service]\n",[468,1384,1385],{"class":470,"line":516},[468,1386,1387],{},"User=hermes\n",[468,1389,1390],{"class":470,"line":522},[468,1391,1392],{},"WorkingDirectory=\u002Fhome\u002Fhermes\n",[468,1394,1395],{"class":470,"line":527},[468,1396,1397],{},"ExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes gateway\n",[468,1399,1400],{"class":470,"line":533},[468,1401,1402],{},"Restart=always\n",[468,1404,1405],{"class":470,"line":538},[468,1406,1407],{},"RestartSec=10\n",[468,1409,1411],{"class":470,"line":1410},11,[468,1412,1413],{},"Environment=PATH=\u002Fhome\u002Fhermes\u002F.local\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin\n",[468,1415,1417],{"class":470,"line":1416},12,[468,1418,513],{"emptyLinePlaceholder":512},[468,1420,1422],{"class":470,"line":1421},13,[468,1423,1424],{},"[Install]\n",[468,1426,1428],{"class":470,"line":1427},14,[468,1429,1430],{},"WantedBy=multi-user.target\n",[433,1432,1433],{},"Enable and start the service:",[460,1435,1437],{"className":1332,"code":1436,"language":1334,"meta":423,"style":423},"sudo systemctl daemon-reload\nsudo systemctl enable hermes-gateway\nsudo systemctl start hermes-gateway\nsudo systemctl status hermes-gateway\n",[442,1438,1439,1448,1460,1471],{"__ignoreMap":423},[468,1440,1441,1443,1445],{"class":470,"line":471},[468,1442,916],{"class":474},[468,1444,1036],{"class":489},[468,1446,1447],{"class":489}," daemon-reload\n",[468,1449,1450,1452,1454,1457],{"class":470,"line":478},[468,1451,916],{"class":474},[468,1453,1036],{"class":489},[468,1455,1456],{"class":489}," enable",[468,1458,1459],{"class":489}," hermes-gateway\n",[468,1461,1462,1464,1466,1469],{"class":470,"line":493},[468,1463,916],{"class":474},[468,1465,1036],{"class":489},[468,1467,1468],{"class":489}," start",[468,1470,1459],{"class":489},[468,1472,1473,1475,1477,1480],{"class":470,"line":504},[468,1474,916],{"class":474},[468,1476,1036],{"class":489},[468,1478,1479],{"class":489}," status",[468,1481,1459],{"class":489},[428,1483,806],{"id":805},[433,1485,1486],{},"In this article, we focused on how to set up the Hermes Agent and use Telegram to communicate with it. Having the Hermes Agent running on a remote server provides a true digital assistant that runs 24\u002F7.",[822,1488,1489],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":423,"searchDepth":478,"depth":493,"links":1491},[1492,1493,1498,1499,1500],{"id":864,"depth":478,"text":865},{"id":874,"depth":478,"text":875,"children":1494},[1495,1496,1497],{"id":878,"depth":493,"text":879},{"id":1045,"depth":493,"text":1046},{"id":1148,"depth":493,"text":1149},{"id":1261,"depth":478,"text":1262},{"id":1325,"depth":478,"text":1326},{"id":805,"depth":478,"text":806},[836],"2026-06-19","Deploy the Hermes Agent on a remote VPS for 24\u002F7 uptime. Follow our step-by-step guide to integrate it with a custom Telegram bot.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server\u002FHow%20to%20Setup%20Hermes%20on%20Remote%20Server.webp","A step-by-step guide to deploying Hermes Agent on a remote Linux VPS and integrating it with a custom Telegram bot for 24\u002F7 uptime.",{"schemaOrg":1507,"robots":846,"sitemap":1520},[1508],{"@type":845,"name":374,"description":1503,"image":1504,"step":1509},[1510,1514,1517],{"@type":1511,"name":879,"text":1512,"image":903,"url":1513},"HowToStep","Open the terminal and SSH into your remote machine: Ensure your server packages are up to date: Add a new user, `hermes`, or your preferred usernam...","#step-1-connect-to-your-vps",{"@type":1511,"name":1046,"text":1515,"image":1077,"url":1516},"Run the following command: Once installed, verify the installation by typing: Run `hermes setup` to configure the Hermes Agent: Select an LLM provi...","#step-2-install-hermes-agent",{"@type":1511,"name":1149,"text":1518,"image":1160,"url":1519},"Select `[2]` for using Telegram bot. Head to `Telegram` and search for 'BotFather'. Click `Open` to open 'BotFather'. Click `Create a New Bot`. Fil...","#step-3-integrating-with-telegram",{"lastmod":1502},{"title":1522,"description":1503,"ogTitle":374,"ogDescription":1503,"twitterTitle":374,"twitterDescription":1503},"Hermes Agent VPS Setup: Telegram Bot Integration Guide",[1296,1524,1525,1526,1527],"VPS Setup","Telegram Bot","Linux VPS","AI Agent","gfsduy5l7mhQlgk1B5l15odagbzetTgFxjC5hIpUmKg",{"id":1530,"title":398,"author":423,"body":1531,"category":2072,"date":2075,"description":2076,"extension":839,"image":2077,"imageAlt":2078,"isPublished":512,"meta":2079,"minRead":504,"navigation":512,"path":399,"seo":2083,"stem":400,"tags":2084,"updatedAt":854,"__hash__":2088},"article\u002Fen\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac.md",{"type":425,"value":1532,"toc":2065},[1533,1537,1540,1547,1551,1558,1561,1564,1568,1571,1578,1594,1907,2023,2025,2028,2032,2062],[428,1534,1536],{"id":1535},"what-is-cloudflare-warp","What Is Cloudflare WARP?",[433,1538,1539],{},"Cloudflare WARP is a client-side application that routes specified device traffic through Cloudflare's global network instead of directly out to the public internet.",[433,1541,1542,1543,1546],{},"It creates an encrypted tunnel built on the ",[437,1544,1545],{},"WireGuard"," protocol, securing traffic from the device to the nearest Cloudflare data center. Policies can then be created in your Cloudflare dashboard to filter, log, inspect, or route this incoming traffic.",[428,1548,1550],{"id":1549},"why-do-we-need-cloudflare-warp","Why Do We Need Cloudflare WARP?",[433,1552,1553,1554,1557],{},"To securely expose internal resources—such as private web services or SaaS applications—to employees, contractors, and other stakeholders, the Cloudflare WARP client is the as the client-side enforcement point for ",[437,1555,1556],{},"Zero Trust Network Access (ZTNA)",".",[433,1559,1560],{},"The Cloudflare WARP client is installed on a user’s laptop or phone. It requires users to authenticate and meet specific security posture checks (such as coming from an approved IP range, using a registered email domain, or running an active firewall) before granting access.",[433,1562,1563],{},"By tunneling device traffic directly to Cloudflare, the user's identity, device, and policies are verified before requests ever reach internal resources. As a result, internal resources are never exposed to the public internet, and every single request is fully logged and audited.",[428,1565,1567],{"id":1566},"supporting-multiple-warp-profiles-on-one-device","Supporting Multiple WARP Profiles on One Device",[433,1569,1570],{},"When users need to switch between personal and corporate Cloudflare accounts, or when system administrators manage multiple tenants, supporting multiple WARP profiles on a single device becomes crucial.",[433,1572,1573,1574,1577],{},"To achieve this on macOS, we can use a ",[442,1575,1576],{},".mobileconfig"," MDM profile file to define and register the different WARP environments.",[724,1579,1580,1591],{},[580,1581,1582,1590],{},[450,1583,1586,1587,1589],{"href":1584,"rel":1585},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fstatic\u002Fmdm\u002Fmultiple-orgs\u002FCloudflareWARP.mobileconfig",[454],"Download a sample ",[442,1588,1576],{}," file"," directly from Cloudflare.",[580,1592,1593],{},"Below is an example of what this configuration looks like:",[460,1595,1599],{"className":1596,"code":1597,"language":1598,"meta":423,"style":423},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n\u003Cplist version=\"1.0\">\n\u003Cdict>\n  \u003Ckey>PayloadContent\u003C\u002Fkey>\n  \u003Carray>\n    \u003Cdict>\n      \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n      \u003Cstring>Warp Configuration\u003C\u002Fstring>\n      \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n      \u003Cstring>com.cloudflare.warp.CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n      \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n      \u003Cstring>Cloudflare Ltd.\u003C\u002Fstring>\n      \u003Ckey>PayloadType\u003C\u002Fkey>\n      \u003Cstring>com.cloudflare.warp\u003C\u002Fstring>\n      \u003Ckey>PayloadUUID\u003C\u002Fkey>\n      \u003Cstring>CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n      \u003Ckey>PayloadVersion\u003C\u002Fkey>\n      \u003Cinteger>1\u003C\u002Finteger>\n      \u003Ckey>configs\u003C\u002Fkey>\n      \u003Carray>\n        \u003Cdict>\n          \u003Ckey>organization\u003C\u002Fkey>\n          \u003Cstring>your-team-name-1\u003C\u002Fstring>\n          \u003Ckey>display_name\u003C\u002Fkey>\n          \u003Cstring>Team 1\u003C\u002Fstring>\n        \u003C\u002Fdict>\n        \u003Cdict>\n          \u003Ckey>organization\u003C\u002Fkey>\n          \u003Cstring>your-team-name-2\u003C\u002Fstring>\n          \u003Ckey>display_name\u003C\u002Fkey>\n          \u003Cstring>Team 2\u003C\u002Fstring>\n        \u003C\u002Fdict>\n      \u003C\u002Farray>\n    \u003C\u002Fdict>\n  \u003C\u002Farray>\n  \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n  \u003Cstring>Cloudflare WARP\u003C\u002Fstring>\n  \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n  \u003Cstring>cloudflare_warp\u003C\u002Fstring>\n  \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n  \u003Cstring>Cloudflare, Ltd.\u003C\u002Fstring>\n  \u003Ckey>PayloadRemovalDisallowed\u003C\u002Fkey>\n  \u003Cfalse\u002F>\n  \u003Ckey>PayloadScope\u003C\u002Fkey>\n  \u003Cstring>System\u003C\u002Fstring>\n  \u003Ckey>PayloadType\u003C\u002Fkey>\n  \u003Cstring>Configuration\u003C\u002Fstring>\n  \u003Ckey>PayloadUUID\u003C\u002Fkey>\n  \u003Cstring>2B7763B8-64F6-41EB-AA5E-7761651B8131\u003C\u002Fstring>\n  \u003Ckey>PayloadVersion\u003C\u002Fkey>\n  \u003Cinteger>1\u003C\u002Finteger>\n\u003C\u002Fdict>\n\u003C\u002Fplist>\n","xml",[442,1600,1601,1606,1611,1616,1621,1626,1631,1636,1641,1646,1651,1656,1661,1666,1671,1677,1683,1689,1695,1701,1707,1713,1719,1725,1731,1737,1743,1749,1754,1759,1765,1770,1776,1781,1787,1793,1799,1805,1811,1817,1823,1829,1835,1841,1847,1853,1859,1865,1871,1877,1883,1889,1895,1901],{"__ignoreMap":423},[468,1602,1603],{"class":470,"line":471},[468,1604,1605],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",[468,1607,1608],{"class":470,"line":478},[468,1609,1610],{},"\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n",[468,1612,1613],{"class":470,"line":493},[468,1614,1615],{},"\u003Cplist version=\"1.0\">\n",[468,1617,1618],{"class":470,"line":504},[468,1619,1620],{},"\u003Cdict>\n",[468,1622,1623],{"class":470,"line":509},[468,1624,1625],{},"  \u003Ckey>PayloadContent\u003C\u002Fkey>\n",[468,1627,1628],{"class":470,"line":516},[468,1629,1630],{},"  \u003Carray>\n",[468,1632,1633],{"class":470,"line":522},[468,1634,1635],{},"    \u003Cdict>\n",[468,1637,1638],{"class":470,"line":527},[468,1639,1640],{},"      \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n",[468,1642,1643],{"class":470,"line":533},[468,1644,1645],{},"      \u003Cstring>Warp Configuration\u003C\u002Fstring>\n",[468,1647,1648],{"class":470,"line":538},[468,1649,1650],{},"      \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n",[468,1652,1653],{"class":470,"line":1410},[468,1654,1655],{},"      \u003Cstring>com.cloudflare.warp.CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n",[468,1657,1658],{"class":470,"line":1416},[468,1659,1660],{},"      \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n",[468,1662,1663],{"class":470,"line":1421},[468,1664,1665],{},"      \u003Cstring>Cloudflare Ltd.\u003C\u002Fstring>\n",[468,1667,1668],{"class":470,"line":1427},[468,1669,1670],{},"      \u003Ckey>PayloadType\u003C\u002Fkey>\n",[468,1672,1674],{"class":470,"line":1673},15,[468,1675,1676],{},"      \u003Cstring>com.cloudflare.warp\u003C\u002Fstring>\n",[468,1678,1680],{"class":470,"line":1679},16,[468,1681,1682],{},"      \u003Ckey>PayloadUUID\u003C\u002Fkey>\n",[468,1684,1686],{"class":470,"line":1685},17,[468,1687,1688],{},"      \u003Cstring>CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n",[468,1690,1692],{"class":470,"line":1691},18,[468,1693,1694],{},"      \u003Ckey>PayloadVersion\u003C\u002Fkey>\n",[468,1696,1698],{"class":470,"line":1697},19,[468,1699,1700],{},"      \u003Cinteger>1\u003C\u002Finteger>\n",[468,1702,1704],{"class":470,"line":1703},20,[468,1705,1706],{},"      \u003Ckey>configs\u003C\u002Fkey>\n",[468,1708,1710],{"class":470,"line":1709},21,[468,1711,1712],{},"      \u003Carray>\n",[468,1714,1716],{"class":470,"line":1715},22,[468,1717,1718],{},"        \u003Cdict>\n",[468,1720,1722],{"class":470,"line":1721},23,[468,1723,1724],{},"          \u003Ckey>organization\u003C\u002Fkey>\n",[468,1726,1728],{"class":470,"line":1727},24,[468,1729,1730],{},"          \u003Cstring>your-team-name-1\u003C\u002Fstring>\n",[468,1732,1734],{"class":470,"line":1733},25,[468,1735,1736],{},"          \u003Ckey>display_name\u003C\u002Fkey>\n",[468,1738,1740],{"class":470,"line":1739},26,[468,1741,1742],{},"          \u003Cstring>Team 1\u003C\u002Fstring>\n",[468,1744,1746],{"class":470,"line":1745},27,[468,1747,1748],{},"        \u003C\u002Fdict>\n",[468,1750,1752],{"class":470,"line":1751},28,[468,1753,1718],{},[468,1755,1757],{"class":470,"line":1756},29,[468,1758,1724],{},[468,1760,1762],{"class":470,"line":1761},30,[468,1763,1764],{},"          \u003Cstring>your-team-name-2\u003C\u002Fstring>\n",[468,1766,1768],{"class":470,"line":1767},31,[468,1769,1736],{},[468,1771,1773],{"class":470,"line":1772},32,[468,1774,1775],{},"          \u003Cstring>Team 2\u003C\u002Fstring>\n",[468,1777,1779],{"class":470,"line":1778},33,[468,1780,1748],{},[468,1782,1784],{"class":470,"line":1783},34,[468,1785,1786],{},"      \u003C\u002Farray>\n",[468,1788,1790],{"class":470,"line":1789},35,[468,1791,1792],{},"    \u003C\u002Fdict>\n",[468,1794,1796],{"class":470,"line":1795},36,[468,1797,1798],{},"  \u003C\u002Farray>\n",[468,1800,1802],{"class":470,"line":1801},37,[468,1803,1804],{},"  \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n",[468,1806,1808],{"class":470,"line":1807},38,[468,1809,1810],{},"  \u003Cstring>Cloudflare WARP\u003C\u002Fstring>\n",[468,1812,1814],{"class":470,"line":1813},39,[468,1815,1816],{},"  \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n",[468,1818,1820],{"class":470,"line":1819},40,[468,1821,1822],{},"  \u003Cstring>cloudflare_warp\u003C\u002Fstring>\n",[468,1824,1826],{"class":470,"line":1825},41,[468,1827,1828],{},"  \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n",[468,1830,1832],{"class":470,"line":1831},42,[468,1833,1834],{},"  \u003Cstring>Cloudflare, Ltd.\u003C\u002Fstring>\n",[468,1836,1838],{"class":470,"line":1837},43,[468,1839,1840],{},"  \u003Ckey>PayloadRemovalDisallowed\u003C\u002Fkey>\n",[468,1842,1844],{"class":470,"line":1843},44,[468,1845,1846],{},"  \u003Cfalse\u002F>\n",[468,1848,1850],{"class":470,"line":1849},45,[468,1851,1852],{},"  \u003Ckey>PayloadScope\u003C\u002Fkey>\n",[468,1854,1856],{"class":470,"line":1855},46,[468,1857,1858],{},"  \u003Cstring>System\u003C\u002Fstring>\n",[468,1860,1862],{"class":470,"line":1861},47,[468,1863,1864],{},"  \u003Ckey>PayloadType\u003C\u002Fkey>\n",[468,1866,1868],{"class":470,"line":1867},48,[468,1869,1870],{},"  \u003Cstring>Configuration\u003C\u002Fstring>\n",[468,1872,1874],{"class":470,"line":1873},49,[468,1875,1876],{},"  \u003Ckey>PayloadUUID\u003C\u002Fkey>\n",[468,1878,1880],{"class":470,"line":1879},50,[468,1881,1882],{},"  \u003Cstring>2B7763B8-64F6-41EB-AA5E-7761651B8131\u003C\u002Fstring>\n",[468,1884,1886],{"class":470,"line":1885},51,[468,1887,1888],{},"  \u003Ckey>PayloadVersion\u003C\u002Fkey>\n",[468,1890,1892],{"class":470,"line":1891},52,[468,1893,1894],{},"  \u003Cinteger>1\u003C\u002Finteger>\n",[468,1896,1898],{"class":470,"line":1897},53,[468,1899,1900],{},"\u003C\u002Fdict>\n",[468,1902,1904],{"class":470,"line":1903},54,[468,1905,1906],{},"\u003C\u002Fplist>\n",[724,1908,1909,1920,1934,1944,1949,1967,1979,1998,2014],{},[580,1910,1911,1912,1915,1916,1919],{},"Replace ",[442,1913,1914],{},"your-team-name-1"," and ",[442,1917,1918],{},"your-team-name-2"," with your respective Cloudflare Zero Trust team names.",[580,1921,1922,1923,1926,1927,1930,1931,1933],{},"Run the command ",[442,1924,1925],{},"uuidgen"," in your Terminal to generate unique UUIDs, and use them to replace the placeholder ",[442,1928,1929],{},"PayloadUUID"," values in the ",[442,1932,1576],{}," file.",[580,1935,1936,1937,1940,1941,1943],{},"Make sure that the ",[442,1938,1939],{},"PayloadIdentifier"," string also contains the updated ",[442,1942,1929],{}," to keep the profile distinct.",[580,1945,1946,1947,1933],{},"Save your edited ",[442,1948,1576],{},[580,1950,1951,1952,1955,1956,1959,1960,1963],{},"Open ",[437,1953,1954],{},"System Settings"," on your Mac, search for ",[437,1957,1958],{},"Profiles",", and select it.",[1961,1962],"br",{},[567,1964],{"alt":1965,"src":1966},"macOS System Settings Profiles pane","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-system-settings-profiles.webp",[580,1968,1228,1969,1972,1973,1975],{},[437,1970,1971],{},"Install, view or remove..."," to begin adding your new configuration profile.",[1961,1974],{},[567,1976],{"alt":1977,"src":1978},"macOS Profiles install view or remove button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-profiles-view-remove.webp",[580,1980,1981,1982,1985,1986,1933,1988,1990,1994],{},"Click the ",[437,1983,1984],{},"+"," (plus) icon in the bottom-left corner and select your saved ",[442,1987,1576],{},[1961,1989],{},[567,1991],{"alt":1992,"src":1993},"macOS Profiles plus button to add a new profile","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-profiles-add-profile.webp",[567,1995],{"alt":1996,"src":1997},"Selecting the mobileconfig file on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-select-mobileconfig-file.webp",[580,1999,1152,2000,2003,2004,2007,2008,2010],{},[437,2001,2002],{},"Cloudflare WARP"," and click ",[437,2005,2006],{},"Install"," to apply the configuration.",[1961,2009],{},[567,2011],{"alt":2012,"src":2013},"Confirming Cloudflare WARP profile installation on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-install-cloudflare-warp-profile.webp",[580,2015,2016,2017,2019],{},"Restart your Cloudflare WARP client. You should now see the multi-profile switcher in the user interface:",[1961,2018],{},[567,2020],{"alt":2021,"src":2022},"Cloudflare WARP client with multi-profile switcher on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fcloudflare-warp-multi-profile-switcher.webp",[428,2024,806],{"id":805},[433,2026,2027],{},"The Cloudflare WARP client acts as a critical security point on user devices, making Zero Trust Network Access both robust and highly practical. Keeping internal resources isolated from the public internet ensures that every connection attempt is securely authenticated, evaluated, and audited.",[428,2029,2031],{"id":2030},"references","References",[724,2033,2034,2041,2048,2055],{},[580,2035,2036],{},[450,2037,2040],{"href":2038,"rel":2039},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002Fdeployment\u002Fmdm-deployment\u002F#prepare-file-for-mdm-deployment",[454],"Managed Deployment Preparation",[580,2042,2043],{},[450,2044,2047],{"href":2045,"rel":2046},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002Fdeployment\u002Fmdm-deployment\u002Fswitch-organizations\u002F",[454],"Switch Between Zero Trust Organizations",[580,2049,2050],{},[450,2051,2054],{"href":2052,"rel":2053},"https:\u002F\u002Fblog.cloudflare.com\u002Fintroducing-warp-connector-paving-the-path-to-any-to-any-connectivity-2\u002F",[454],"Introducing WARP Connector: Paving the Path to Any-to-Any Connectivity",[580,2056,2057],{},[450,2058,2061],{"href":2059,"rel":2060},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002F",[454],"Cloudflare One Client Documentation",[822,2063,2064],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":478,"depth":493,"links":2066},[2067,2068,2069,2070,2071],{"id":1535,"depth":478,"text":1536},{"id":1549,"depth":478,"text":1550},{"id":1566,"depth":478,"text":1567},{"id":805,"depth":478,"text":806},{"id":2030,"depth":478,"text":2031},[2073,2074],"security","cloudflare","2026-07-04","Configure and switch multiple Cloudflare WARP organisations on macOS using a .mobileconfig file. A complete MDM guide for IT admins.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002FEN-Switch-Between-Multiple-Cloudflare-WARP-Orgs-on-Mac.webp","Configure Multiple Cloudflare WARP Profiles on macOS",{"schemaOrg":2080,"robots":846,"sitemap":2082},[2081],{"@type":845,"headline":398,"description":2076},{"lastmod":2075},{"title":2078,"description":2076,"ogTitle":398,"ogDescription":2076,"twitterTitle":398,"twitterDescription":2076},[2085,2002,2086,2087],"macOS","MDM","Zero Trust","1b-JmgD0tsBcQooHgG1MNPYYvTAdh8f83JMRp2OWhJ8",[2090,3297,4193],{"id":2091,"title":354,"author":423,"body":2092,"category":3260,"date":3263,"description":3264,"extension":839,"image":3265,"imageAlt":3266,"isPublished":512,"meta":3267,"minRead":533,"navigation":512,"path":355,"seo":3292,"stem":356,"tags":3294,"updatedAt":854,"__hash__":3296},"article\u002Fen\u002Farticle\u002Fbringing-buzz-to-deepseek-harness.md",{"type":425,"value":2093,"toc":3244},[2094,2100,2121,2129,2132,2136,2142,2184,2187,2245,2249,2256,2519,2522,2526,2530,2537,2541,2554,2558,2569,2616,2623,2627,2630,2661,2665,2670,2712,2717,2723,2728,2734,2749,2762,2766,2775,2806,2828,2876,2884,2889,2895,2902,2908,2913,2920,2934,2940,2949,2988,2991,2997,3004,3010,3014,3017,3165,3169,3202,3206,3212,3215,3241],[433,2095,2096],{},[567,2097],{"alt":2098,"src":2099},"DeepSeek Harness message gateway connected to Block Buzz channel overview","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-nostr-gateway-overview.webp",[433,2101,2102,2103,2110,2111,2116,2117,1557],{},"The DeepSeek Harness (DSH) plugin, ",[437,2104,2105],{},[450,2106,2109],{"href":2107,"rel":2108},"https:\u002F\u002Fgithub.com\u002Fa792883583\u002Fdsh-message-gateway",[454],"dsh-message-gateway",", extends the DeepSeek Harness assistant across messaging platforms such as Discord, Telegram, and WeChat. The plugin repository was forked and extended to add the ",[437,2112,2113],{},[450,2114,2115],{"href":383},"Buzz"," platform to the list. The forked repository is available on GitHub at ",[450,2118,2119],{"href":2119,"rel":2120},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fdsh-message-gateway",[454],[2122,2123],"article-card",{"description":2124,"image":2125,"image-alt":2126,"label":2127,"min-read":2128,"title":382,"to":383},"Learn how to self-host Block's Buzz on a Linux VPS behind Cloudflare DNS. Run a secure, Nostr-powered workspace where humans and AI agents collaborate.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002FEN-Self-Hosting-Buzz-As-The-Workspace-Where-AI-Agents-Become-Colleagues.webp","A premium 16:9 technology card with deep blue and orange accents illustrating how to self-host Block's Buzz relay on an Ubuntu VPS, featuring a clean glassmorphic panel with centered typography.","Prerequisite guide","12",[433,2130,2131],{},"The DSH assistant joins a Buzz relay as a member, receives direct messages (DMs) and channel messages where it is @mentioned, and responds through the same per-chat agent pipeline used by the Web UI.",[428,2133,2135],{"id":2134},"architecture-of-the-dsh-message-gateway-plugin","Architecture of the dsh-message-gateway Plugin",[433,2137,2138,2139,2141],{},"The architecture of the ",[437,2140,2109],{}," plugin splits into two parts:",[724,2143,2144,2174],{},[580,2145,2146,2149,2150,2153,2154,2157,2158,2161,2162,2165,2166,2169,2170,2173],{},[437,2147,2148],{},"Host"," (Node): ",[442,2151,2152],{},"gateway-store"," (credentials, ",[442,2155,2156],{},"~\u002F.dsh\u002Fgateway.json","), ",[442,2159,2160],{},"platforms.ts"," (platform definitions + connection tests), ",[442,2163,2164],{},"routes.ts"," (",[442,2167,2168],{},"\u002Fgateway\u002F*"," endpoints), and ",[442,2171,2172],{},"bridge-manager.ts"," (the resident bridges: per-chat independent agent sessions + streamed replies).",[580,2175,2176,2179,2180,2183],{},[437,2177,2178],{},"Client"," (browser): the sidebar \"",[437,2181,2182],{},"Message platforms","\" page where you save credentials, test connections, and monitor status.",[433,2185,2186],{},"Adding a new platform involves the following steps:",[577,2188,2189,2206,2220],{},[580,2190,2191,2194,2195,2198,2199,2202,2203,1557],{},[437,2192,2193],{},"A bridge class"," — ",[442,2196,2197],{},"start\u002Fstop\u002Fstatus"," plus an ",[442,2200,2201],{},"onText(text, frame)"," callback, mirroring ",[442,2204,2205],{},"wecom-bridge.ts",[580,2207,2208,2211,2212,2215,2216,2219],{},[437,2209,2210],{},"Bridge-manager wiring"," — reuse the existing per-chat pipeline (",[442,2213,2214],{},"ensureAgentForKey"," + ",[442,2217,2218],{},"pendingMap",") and swap in the platform's reply sink.",[580,2221,2222,2225,2226,1915,2229,2232,2233,2236,2237,2240,2241,2244],{},[437,2223,2224],{},"Storage\u002Froute wiring"," — in ",[442,2227,2228],{},"\u002Fgateway\u002Fsave",[442,2230,2231],{},"\u002Fgateway\u002Fdelete",": ",[437,2234,2235],{},"saving credentials starts the bridge, deleting stops it"," — plus an ",[442,2238,2239],{},"autoStartXxx"," flag so ",[442,2242,2243],{},"dsh web"," reconnects on boot.",[428,2246,2248],{"id":2247},"building-the-buzz-bridge-nostr-protocol-event-lifecycle","Building the Buzz Bridge: Nostr Protocol & Event Lifecycle",[433,2250,2251,2252,2255],{},"The ",[437,2253,2254],{},"DeepSeek Harness"," was used to implement the Buzz bridge. The implementation conforms to the following Nostr protocol specifications:",[2257,2258,2259,2285],"table",{},[2260,2261,2262],"thead",{},[2263,2264,2265,2271],"tr",{},[2266,2267,2268],"th",{},[437,2269,2270],{},"Transport",[2266,2272,2273,2274,2277,2278,2281,2282],{},"One NIP-42-authenticated WebSocket; default ",[442,2275,2276],{},"ws:\u002F\u002Flocalhost:3000","; ",[442,2279,2280],{},"http(s):\u002F\u002F"," is normalised to ",[442,2283,2284],{},"ws(s):\u002F\u002F",[2286,2287,2288,2307,2335,2353,2376,2400,2422,2436,2449,2465,2482,2496],"tbody",{},[2263,2289,2290,2296],{},[2291,2292,2293],"td",{},[437,2294,2295],{},"Auth",[2291,2297,2298,2299,2302,2303,2306],{},"AUTH event ",[442,2300,2301],{},"kind 22242",", tags ",[442,2304,2305],{},"[[\"relay\", url], [\"challenge\", challenge]]",", empty content, signed with the agent key",[2263,2308,2309,2314],{},[2291,2310,2311],{},[437,2312,2313],{},"Subscriptions",[2291,2315,2316,2232,2319,2322,2323,2326,2327,2330,2331,2334],{},[437,2317,2318],{},"Channel-scoped",[442,2320,2321],{},"REQ {\"kinds\":[9], \"#h\":[\u003Cuuid>]}"," — one REQ per channel. A global ",[442,2324,2325],{},"kinds:[9]"," REQ gets EOSE but never fans out; multi-value ",[442,2328,2329],{},"#h"," does ",[437,2332,2333],{},"not"," work",[2263,2336,2337,2342],{},[2291,2338,2339],{},[437,2340,2341],{},"Discovery",[2291,2343,2344,2345,2348,2349,2352],{},"Historical ",[442,2346,2347],{},"REQ {kinds:[39000]}"," for channel metadata (",[442,2350,2351],{},"type == \"dm\""," marks a DM channel)",[2263,2354,2355,2360],{},[2291,2356,2357],{},[437,2358,2359],{},"Membership",[2291,2361,2362,2363,2366,2367,1984,2369,2372,2373],{},"Live ",[442,2364,2365],{},"REQ {kinds:[44100,44101], \"#p\":[our pubkey], since: now-60s}"," — 44100 = added, 44101 = removed, each carrying ",[442,2368,433],{},[442,2370,2371],{},"h","; membership changes update subscriptions ",[437,2374,2375],{},"without reconnect",[2263,2377,2378,2383],{},[2291,2379,2380],{},[437,2381,2382],{},"Chat events",[2291,2384,2385,2388,2389,2392,2393,2396,2397],{},[442,2386,2387],{},"kind 9"," with tags ",[442,2390,2391],{},"[\"h\", channel]",", optional ",[442,2394,2395],{},"[\"e\", replyTo]",", ",[442,2398,2399],{},"[\"p\", mention]",[2263,2401,2402,2407],{},[2291,2403,2404],{},[437,2405,2406],{},"In-place edits",[2291,2408,2409,2412,2413,2215,2415,2418,2419,2421],{},[442,2410,2411],{},"kind 40003"," with ",[442,2414,2371],{},[442,2416,2417],{},"e","→target; content replaces; 64 KB relay cap → keep payloads ≤ 60,000 B; oversized replies chunk — chunk 0 rides the edit, overflow chunks are appended as threaded kind-9 messages (",[442,2420,2417],{},"→thread root)",[2263,2423,2424,2429],{},[2291,2425,2426],{},[437,2427,2428],{},"CLOSED frames",[2291,2430,2431,2432,2435],{},"Pre-AUTH ",[442,2433,2434],{},"auth-required"," is normal bootstrap (finish AUTH, reopen subs); post-AUTH → bounded resubscribe (3 attempts, 0\u002F1\u002F2 s backoff); reconnect rebuilds everything",[2263,2437,2438,2443],{},[2291,2439,2440],{},[437,2441,2442],{},"Relay caps",[2291,2444,2445,2446],{},"≤ 2000 historical events per subscription, newest-first even with ",[442,2447,2448],{},"since",[2263,2450,2451,2456],{},[2291,2452,2453],{},[437,2454,2455],{},"Mention gating",[2291,2457,2458,2459,2461,2462,2464],{},"Act on inbound kind-9 only when (a) ",[442,2460,433],{},"-tag includes our pubkey, (b) channel is a DM, or (c) the ",[442,2463,2417],{}," root is our own event (thread follow). Ignore our own pubkey — loop prevention",[2263,2466,2467,2472],{},[2291,2468,2469],{},[437,2470,2471],{},"Outbound mentions",[2291,2473,2474,2475,2478,2479,2481],{},"Outbound text is published verbatim — the relay does not pre-check ",[442,2476,2477],{},"@"," tokens; ",[442,2480,433],{}," tags carry the inbound author + up to 7 other mentioned pubkeys (max 8)",[2263,2483,2484,2489],{},[2291,2485,2486],{},[437,2487,2488],{},"DMs",[2291,2490,2491,2492,2495],{},"Relay-scoped plaintext channels (",[442,2493,2494],{},"type: \"dm\""," metadata) — no NIP-04\u002F44 encryption in this bridge",[2263,2497,2498,2503],{},[2291,2499,2500],{},[437,2501,2502],{},"Attachments (inbound)",[2291,2504,2505,2506,2165,2509,2396,2512,2396,2515,2518],{},"NIP-92 ",[442,2507,2508],{},"imeta",[442,2510,2511],{},"url",[442,2513,2514],{},"sha256",[442,2516,2517],{},"m",") → plain http(s) download, verify SHA-256, 20 MB cap, max 4 per message; outbound images have no documented publish path → explicitly unsupported",[433,2520,2521],{},"The diagram below illustrates how the Buzz bridge bootstraps:",[567,2523],{"src":2524,"alt":2525},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-bootstrap.webp","Sequence diagram illustrating the Buzz bridge bootstrap and NIP-42 authentication process",[572,2527,2529],{"id":2528},"real-time-streaming-via-nostr-in-place-edits-kind-40003","Real-Time Streaming via Nostr In-Place Edits (Kind 40003)",[433,2531,2532,2533,2536],{},"Nostr has no native typing indicator, and events are append-only. To make replies feel responsive and alive, the Buzz bridge ",[437,2534,2535],{},"simulates streaming using in-place edits"," as shown below:",[567,2538],{"src":2539,"alt":2540},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-reply.webp","Diagram of in-place editing flow simulating live streaming responses with kind 40003 events",[724,2542,2543],{},[580,2544,2545],{},[611,2546,2547,2548,2550,2551,2553],{},"The Buzz bridge publishes a placeholder ",[442,2549,2387],{}," event, then progressively rewrites it with rate-limited ",[442,2552,2411],{}," in-place edits, before writing the final edit when the agent completes its run. This mirrors the \"send then edit\" pattern used by Telegram and Discord bridges.",[572,2555,2557],{"id":2556},"bridging-deepseek-harness-workspaces-via-chat-commands","Bridging DeepSeek Harness Workspaces via Chat Commands",[433,2559,2560,2561,2564,2565,2568],{},"The DSH \"Workspaces\" feature in the Web UI is backed by the ",[442,2562,2563],{},"workspaceRegistry"," service (",[442,2566,2567],{},"@deepseek-ai\u002Fdsh-workspace","):",[460,2570,2574],{"className":2571,"code":2572,"language":2573,"meta":423,"style":423},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const existing = await ctx.workspaceRegistry.resolveByPath(request.path);\n","typescript",[442,2575,2576],{"__ignoreMap":423},[468,2577,2578,2582,2585,2588,2592,2595,2597,2599,2601,2605,2608,2610,2613],{"class":470,"line":471},[468,2579,2581],{"class":2580},"spNyl","const",[468,2583,2584],{"class":961}," existing ",[468,2586,2587],{"class":485},"=",[468,2589,2591],{"class":2590},"s7zQu"," await",[468,2593,2594],{"class":961}," ctx",[468,2596,1557],{"class":485},[468,2598,2563],{"class":961},[468,2600,1557],{"class":485},[468,2602,2604],{"class":2603},"s2Zo4","resolveByPath",[468,2606,2607],{"class":961},"(request",[468,2609,1557],{"class":485},[468,2611,2612],{"class":961},"path)",[468,2614,2615],{"class":485},";\n",[433,2617,2618,2619,2622],{},"The Buzz bridge exposes a chat command, ",[442,2620,2621],{},"\u002Fworkspace \u003Cfolder>",", which registers an existing folder in DSH. Any new session through the gateway attaches to it and appears in the Web UI.",[567,2624],{"src":2625,"alt":2626},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-workspace.webp","Architecture of DeepSeek Harness workspace registration from chat commands via gateway",[433,2628,2629],{},"Three design considerations to note:",[724,2631,2632,2642,2651],{},[580,2633,2634,2637,2638,2641],{},[437,2635,2636],{},"Switching folder = new session."," ",[442,2639,2640],{},"cwd"," is written into the session header at creation and cannot be mutated afterwards.",[580,2643,2644,2637,2647,2650],{},[437,2645,2646],{},"Folder must already exist.",[442,2648,2649],{},"create"," rejects non-existent paths.",[580,2652,2653,2656,2657,2660],{},[437,2654,2655],{},"Security-sensitive command."," Every session operates under an ",[437,2658,2659],{},"auto-approve"," policy, granting file access to the target folder.",[428,2662,2664],{"id":2663},"step-by-step-installation-configuration-guide","Step-by-Step Installation & Configuration Guide",[577,2666,2667],{},[580,2668,2669],{},"Run the following commands:",[460,2671,2673],{"className":885,"code":2672,"language":887,"meta":423,"style":423},"dsh plugin --profile web add https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fdsh-message-gateway.git\n\n# Start DSH web\ndsh web\n",[442,2674,2675,2695,2699,2705],{"__ignoreMap":423},[468,2676,2677,2680,2683,2686,2689,2692],{"class":470,"line":471},[468,2678,2679],{"class":474},"dsh",[468,2681,2682],{"class":489}," plugin",[468,2684,2685],{"class":489}," --profile",[468,2687,2688],{"class":489}," web",[468,2690,2691],{"class":489}," add",[468,2693,2694],{"class":489}," https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fdsh-message-gateway.git\n",[468,2696,2697],{"class":470,"line":478},[468,2698,513],{"emptyLinePlaceholder":512},[468,2700,2701],{"class":470,"line":493},[468,2702,2704],{"class":2703},"sHwdD","# Start DSH web\n",[468,2706,2707,2709],{"class":470,"line":504},[468,2708,2679],{"class":474},[468,2710,2711],{"class":489}," web\n",[577,2713,2714],{"start":478},[580,2715,2716],{},"Once the DSH Web UI is opened in a web browser, click on the 'Message platforms' icon:",[433,2718,2719],{},[567,2720],{"alt":2721,"src":2722},"DeepSeek Harness Web UI sidebar highlighting the Message platforms configuration menu","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-web-ui-message-platforms-sidebar-icon.webp",[577,2724,2725],{"start":493},[580,2726,2727],{},"Click on 'Buzz' on the left panel:",[433,2729,2730],{},[567,2731],{"alt":2732,"src":2733},"Buzz bridge configuration settings panel in DeepSeek Harness message gateway","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-message-gateway-buzz-config-panel.webp",[577,2735,2736,2743,2746],{"start":504},[580,2737,2738,2739,2742],{},"Click 'Generate keypair' to generate a Nostr key pair. Copy the ",[442,2740,2741],{},"npub"," public key somewhere safe, as you will need it later.",[580,2744,2745],{},"Enter the 'Relay URL' and 'Channels' (the allowlist of channel UUIDs to subscribe to).",[580,2747,2748],{},"Click the 'Save' button.",[433,2750,2751,2752,2755,2756,2759,2760,1557],{},"Saving the form stores the credentials and ",[437,2753,2754],{},"starts the bridge",". The ",[442,2757,2758],{},"nsec"," private key is treated as a secret and stored exclusively in ",[442,2761,2156],{},[572,2763,2765],{"id":2764},"registering-the-dsh-assistant-keypair-on-the-buzz-nostr-relay","Registering the DSH Assistant Keypair on the Buzz Nostr Relay",[433,2767,2768,2771,2772,2774],{},[437,2769,2770],{},"Add the DSH assistant to the relay as a member."," The pubkey will be the ",[442,2773,2741],{}," generated above:",[460,2776,2778],{"className":885,"code":2777,"language":887,"meta":423,"style":423},"docker compose exec relay buzz-admin add-member --pubkey npub123123123\n",[442,2779,2780],{"__ignoreMap":423},[468,2781,2782,2785,2788,2791,2794,2797,2800,2803],{"class":470,"line":471},[468,2783,2784],{"class":474},"docker",[468,2786,2787],{"class":489}," compose",[468,2789,2790],{"class":489}," exec",[468,2792,2793],{"class":489}," relay",[468,2795,2796],{"class":489}," buzz-admin",[468,2798,2799],{"class":489}," add-member",[468,2801,2802],{"class":489}," --pubkey",[468,2804,2805],{"class":489}," npub123123123\n",[433,2807,2808,2811,2812,2815,2816,2819,2820,2823,2824,2827],{},[437,2809,2810],{},"Add the DSH assistant to a channel."," Adding a member registers it on the relay, but the member will not yet appear or be searchable within channels. To add the agent to a specific channel using ",[442,2813,2814],{},"buzz-cli",", note that the ",[442,2817,2818],{},"--pubkey"," parameter must be in ",[437,2821,2822],{},"HEX"," format, not npub (the ",[442,2825,2826],{},"buzz-admin add-member"," command prints the member's HEX pubkey).",[460,2829,2831],{"className":885,"code":2830,"language":887,"meta":423,"style":423},"buzz channels add-member --channel \u003CCHANNEL_UUID> --pubkey \u003CAGENT_HEX> --role member\n",[442,2832,2833],{"__ignoreMap":423},[468,2834,2835,2838,2841,2843,2846,2849,2852,2855,2858,2860,2862,2865,2868,2870,2873],{"class":470,"line":471},[468,2836,2837],{"class":474},"buzz",[468,2839,2840],{"class":489}," channels",[468,2842,2799],{"class":489},[468,2844,2845],{"class":489}," --channel",[468,2847,2848],{"class":485}," \u003C",[468,2850,2851],{"class":489},"CHANNEL_UUI",[468,2853,2854],{"class":961},"D",[468,2856,2857],{"class":485},">",[468,2859,2802],{"class":489},[468,2861,2848],{"class":485},[468,2863,2864],{"class":489},"AGENT_HE",[468,2866,2867],{"class":961},"X",[468,2869,2857],{"class":485},[468,2871,2872],{"class":489}," --role",[468,2874,2875],{"class":489}," member\n",[2122,2877],{"description":2878,"image":2125,"image-alt":2879,"label":2880,"min-read":2881,"title":2882,"to":2883},"Step-by-step instructions to install and configure buzz-cli for managing Nostr channels, member keys, and AI agent permissions.","Configuring buzz-cli commands to manage Nostr channel members and agent roles","CLI guide","5","How to Install and Use buzz-cli","\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues#install-buzz-cli",[433,2885,2886,2887,486],{},"Update the DSH assistant's profile on the Nostr relay to a more meaningful display name using ",[442,2888,2814],{},[433,2890,2891],{},[567,2892],{"alt":2893,"src":2894},"Updating the DeepSeek Harness assistant display name on Nostr relay using buzz-cli","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-assistant-buzz-cli-profile-update.webp",[433,2896,2897,2898,2901],{},"Send a ",[437,2899,2900],{},"Wave"," (Buzz's DM greeting) to the DSH assistant. The wave comes back:",[433,2903,2904],{},[567,2905],{"alt":2906,"src":2907},"Testing connection by sending a Wave DM to DeepSeek Harness assistant in Buzz","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-dm-wave-greeting-reply.webp",[433,2909,2910],{},[611,2911,2912],{},"Sending a Wave as a DM to the DSH assistant — the bridge is alive.",[572,2914,2916,2917],{"id":2915},"enabling-workspace","Enabling ",[442,2918,2919],{},"\u002Fworkspace",[433,2921,2922,2923,2926,2927,2930,2931,2933],{},"Because the ",[442,2924,2925],{},"allowWorkspace"," setting defaults to ",[442,2928,2929],{},"false",", issuing the ",[442,2932,2919],{}," command is initially rejected:",[433,2935,2936],{},[567,2937],{"alt":2938,"src":2939},"Error notification showing workspace command rejected when allowWorkspace is disabled","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-workspace-command-rejected-error.webp",[433,2941,2942,2943,2946,2947,486],{},"Enable it in ",[442,2944,2945],{},"~\u002F.dsh\u002Fprofiles\u002Fweb\u002Fcordis.patch.yml",", then restart ",[442,2948,2243],{},[460,2950,2954],{"className":2951,"code":2952,"language":2953,"meta":423,"style":423},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","- id: ui-message-gateway\n  config:\n    allowWorkspace: true\n","yml",[442,2955,2956,2969,2977],{"__ignoreMap":423},[468,2957,2958,2961,2964,2966],{"class":470,"line":471},[468,2959,2960],{"class":485},"-",[468,2962,2963],{"class":481}," id",[468,2965,486],{"class":485},[468,2967,2968],{"class":489}," ui-message-gateway\n",[468,2970,2971,2974],{"class":470,"line":478},[468,2972,2973],{"class":481},"  config",[468,2975,2976],{"class":485},":\n",[468,2978,2979,2982,2984],{"class":470,"line":493},[468,2980,2981],{"class":481},"    allowWorkspace",[468,2983,486],{"class":485},[468,2985,2987],{"class":2986},"sfNiH"," true\n",[433,2989,2990],{},"After the restart:",[433,2992,2993],{},[567,2994],{"alt":2995,"src":2996},"Successful confirmation message after executing workspace registration command in Buzz","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-buzz-workspace-command-success-confirmation.webp",[433,2998,2999,3000,3003],{},"One gotcha: this assumes the workspace folder (",[442,3001,3002],{},"TechVoyage"," in the screenshots) lives in the default user directory. Specify a full path otherwise. Any new session registered under this workspace via Buzz also appears in the DeepSeek Harness Web UI.",[433,3005,3006],{},[567,3007],{"alt":3008,"src":3009},"DeepSeek Harness Web UI displaying the active workspace session synchronized from Buzz","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002Fdsh-web-ui-synced-workspace-session.webp",[572,3011,3013],{"id":3012},"available-commands","Available Commands",[433,3015,3016],{},"Everything that other supported platforms offer works seamlessly on Buzz:",[2257,3018,3019,3029],{},[2260,3020,3021],{},[2263,3022,3023,3026],{},[2266,3024,3025],{},"Command",[2266,3027,3028],{},"What it does",[2286,3030,3031,3040,3050,3060,3070,3080,3090,3100,3109,3129,3148],{},[2263,3032,3033,3037],{},[2291,3034,3035],{},[442,3036,2621],{},[2291,3038,3039],{},"Register an existing folder as the chat's workspace (config-gated)",[2263,3041,3042,3047],{},[2291,3043,3044],{},[442,3045,3046],{},"\u002Fhelp",[2291,3048,3049],{},"List available commands",[2263,3051,3052,3057],{},[2291,3053,3054],{},[442,3055,3056],{},"\u002Ftime",[2291,3058,3059],{},"Current time",[2263,3061,3062,3067],{},[2291,3063,3064],{},[442,3065,3066],{},"\u002Fnew",[2291,3068,3069],{},"Start a fresh session",[2263,3071,3072,3077],{},[2291,3073,3074],{},[442,3075,3076],{},"\u002Fclear",[2291,3078,3079],{},"Clear the conversation",[2263,3081,3082,3087],{},[2291,3083,3084],{},[442,3085,3086],{},"\u002Fstatus",[2291,3088,3089],{},"Bridge status",[2263,3091,3092,3097],{},[2291,3093,3094],{},[442,3095,3096],{},"\u002Fstats",[2291,3098,3099],{},"Chat count + per-bridge status lines (all platforms, incl. Buzz)",[2263,3101,3102,3106],{},[2291,3103,3104],{},[442,3105,1307],{},[2291,3107,3108],{},"Every command descriptor",[2263,3110,3111,3116],{},[2291,3112,3113],{},[442,3114,3115],{},"@path\u002Fto\u002Ffile",[2291,3117,3118,3119,2396,3121,3124,3125,3128],{},"Works exactly like Web @ mentions — the model reads the file relative to the chat's workspace; a bare ",[442,3120,2477],{},[442,3122,3123],{},"@prefix",", or ",[442,3126,3127],{},"\u002Ffiles \u003Cprefix>"," replies with matching files\u002Ffolders from the same discovery source",[2263,3130,3131,3135],{},[2291,3132,3133],{},[442,3134,1317],{},[2291,3136,3137,3140,3141,3143,3144,3147],{},[442,3138,3139],{},"[provider model effort]"," — validated against the live LLM catalog, switches that chat's model + effort; ",[442,3142,1317],{}," alone lists options, ",[442,3145,3146],{},"\u002Fmodel reset"," restores defaults",[2263,3149,3150,3155],{},[2291,3151,3152],{},[442,3153,3154],{},"\u002Feffort",[2291,3156,3157,3160,3161,3164],{},[442,3158,3159],{},"\u003Cid>"," adjusts reasoning effort only; ",[442,3162,3163],{},"\u002Feffort reset"," restores the default",[572,3166,3168],{"id":3167},"security-in-snapshot","Security in Snapshot",[724,3170,3171,3183,3193],{},[580,3172,2251,3173,3175,3176,3178,3179,3182],{},[437,3174,2758],{}," lives only in ",[442,3177,2156],{}," (0600, atomic write) — never in ",[442,3180,3181],{},"\u002Fgateway\u002Flist",", never in logs.",[580,3184,3185,3186,2165,3189,3192],{},"Every inbound event is ",[437,3187,3188],{},"signature-verified",[442,3190,3191],{},"verifyEvent","), deduplicated, self-filtered, and mention-gated before it reaches the agent.",[580,3194,3195,2165,3198,3201],{},[437,3196,3197],{},"Workspace registration is config-gated",[442,3199,3200],{},"allowWorkspace: false"," by default) since gateway sessions auto-approve.",[428,3203,3205],{"id":3204},"key-takeaways","Key Takeaways",[433,3207,3208,3209,3211],{},"The harder part of adding Buzz to ",[442,3210,2109],{}," was fulfilling the Nostr protocol contract. The existing plugin already provided a architectural foundation for per-chat sessions and command routing, making the bridge integration straightforward.",[428,3213,3214],{"id":2030},"References:",[724,3216,3217,3225,3233],{},[580,3218,3219,3224],{},[450,3220,3223],{"href":3221,"rel":3222},"https:\u002F\u002Fgithub.com\u002Fa792883583\u002Fdsh-message-gateway\u002Fblob\u002Fmain\u002Fdocs\u002Farchitecture.md",[454],"dsh-message-gateway architecture guide"," — extension recipe, module map, security notes (bridges default to hidden)",[580,3226,3227,3232],{},[450,3228,3231],{"href":3229,"rel":3230},"https:\u002F\u002Fgithub.com\u002Fnbd-wtf\u002Fnostr-tools",[454],"nostr-tools"," — the Nostr library used under the hood",[580,3234,3235,3240],{},[450,3236,3239],{"href":3237,"rel":3238},"https:\u002F\u002Fgithub.com\u002Fbytedance\u002Fdeer-flow\u002Fblob\u002Fmain\u002Fbackend\u002Fdocs\u002FIM_CHANNEL_CONNECTIONS.md",[454],"deer-flow IM channel connections"," — reference for IM channel connection patterns",[822,3242,3243],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":423,"searchDepth":478,"depth":493,"links":3245},[3246,3247,3251,3258,3259],{"id":2134,"depth":478,"text":2135},{"id":2247,"depth":478,"text":2248,"children":3248},[3249,3250],{"id":2528,"depth":493,"text":2529},{"id":2556,"depth":493,"text":2557},{"id":2663,"depth":478,"text":2664,"children":3252},[3253,3254,3256,3257],{"id":2764,"depth":493,"text":2765},{"id":2915,"depth":493,"text":3255},"Enabling \u002Fworkspace",{"id":3012,"depth":493,"text":3013},{"id":3167,"depth":493,"text":3168},{"id":3204,"depth":478,"text":3205},{"id":2030,"depth":478,"text":3214},[836,3261,2837,3262],"collaboration","deepseek-harness","2026-09-30","Integrate DeepSeek Harness with Block Buzz using a Nostr bridge. Configure NIP-42 auth, in-place message streaming, and per-channel agent workspaces.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FBringing%20Buzz%20to%20DeepSeek%20Harness\u002FEN-Bringing-Buzz-to-DeepSeek-Harness.webp","A premium 16:9 technology card with deep indigo and amber accents illustrating how to connect DeepSeek Harness to Block Buzz via a Nostr gateway, featuring a clean glassmorphic panel with centered typography.",{"schemaOrg":3268,"robots":846,"sitemap":3291},[3269,3271],{"@type":3270,"headline":354,"description":3264,"image":3265},"TechArticle",{"@type":845,"name":354,"description":3264,"image":3265,"step":3272},[3273,3276,3279,3282,3285,3288],{"@type":1511,"name":3274,"text":3275},"Phase 1: Install Gateway Plugin","Install the dsh-message-gateway plugin and start the DSH web service.",{"@type":1511,"name":3277,"text":3278},"Phase 2: Access Message Platforms","Open the DSH Web UI and navigate to Message platforms settings.",{"@type":1511,"name":3280,"text":3281},"Phase 3: Configure Buzz Bridge","Generate a Nostr keypair, enter the Relay URL, and set channel subscriptions.",{"@type":1511,"name":3283,"text":3284},"Phase 4: Register Agent on Relay","Add the DSH assistant to the Buzz Nostr relay using buzz-admin.",{"@type":1511,"name":3286,"text":3287},"Phase 5: Assign Agent to Channel","Add the assistant HEX pubkey to designated channels using buzz-cli.",{"@type":1511,"name":3289,"text":3290},"Phase 6: Enable Workspace Access","Configure allowWorkspace in cordis.patch.yml to enable local folder commands.",{"lastmod":3263},{"title":3293,"description":3264,"ogTitle":354,"ogDescription":3264,"twitterTitle":354,"twitterDescription":3264},"DeepSeek Harness Buzz Plugin: Build a Nostr Bridge",[2254,2115,3295,850,2109],"Nostr","3ILGY8-EUYBkB7RoFM4yH49qiefLt3OYDlH5S748n_g",{"id":3298,"title":362,"author":423,"body":3299,"category":4148,"date":4149,"description":4150,"extension":839,"image":4151,"imageAlt":4152,"isPublished":512,"meta":4153,"minRead":527,"navigation":512,"path":363,"seo":4187,"stem":364,"tags":4189,"updatedAt":4186,"__hash__":4192},"article\u002Fen\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp.md",{"type":425,"value":3300,"toc":4130},[3301,3313,3322,3326,3329,3341,3345,3353,3357,3361,3410,3414,3542,3546,3579,3583,3586,3650,3653,3689,3692,3719,3723,3733,3738,3776,3861,3865,3870,3884,3893,3956,3960,4004,4008,4053,4067,4071,4115,4117,4127],[433,3302,3303,3304,3306,3307,2412,3309,3312],{},"A common challenge arises when you want to access your ",[437,3305,1296],{}," from other devices such as laptops, tablets, or phones without exposing it to the public internet. Utilizing ",[437,3308,2002],{},[437,3310,3311],{},"Cloudflare Zero Trust"," allows you to expose the Hermes Agent globally without opening a single inbound port on your firewall.",[433,3314,3315,3316,3318,3319,3321],{},"If you followed our previous guide, '",[450,3317,374],{"href":375},"', a Hermes Agent is already up and running 24\u002F7. Instead of dealing with the overhead of traditional VPNs, we will use the ",[437,3320,2002],{}," client to expose the Hermes Agent to a private network over the internet.",[428,3323,3325],{"id":3324},"understanding-the-architecture","Understanding the Architecture",[433,3327,3328],{},"The components at play:",[577,3330,3331,3336],{},[580,3332,3333,3335],{},[437,3334,3311],{},": The dashboard at Cloudflare where you define routing rules and access policies.",[580,3337,3338,3340],{},[437,3339,2002],{},": The client application installed on your devices (VPS, laptops, phones). It intercepts traffic destined for your private network and routes it securely.",[572,3342,3344],{"id":3343},"prerequisites","Prerequisites",[724,3346,3347,3350],{},[580,3348,3349],{},"A running Hermes Agent on your VPS.",[580,3351,3352],{},"A free Cloudflare account.",[428,3354,3356],{"id":3355},"step-by-step-guide","Step-by-Step Guide",[572,3358,3360],{"id":3359},"step-1-set-up-cloudflare-zero-trust","Step 1: Set Up Cloudflare Zero Trust",[577,3362,3363,3371,3378,3389,3396,3403],{},[580,3364,3365,3366,1557],{},"Log in to your ",[450,3367,3370],{"href":3368,"rel":3369},"https:\u002F\u002Fdash.cloudflare.com\u002F",[454],"Cloudflare Dashboard",[580,3372,3373,3374],{},"Click on 'Zero Trust' from the left menu.\n",[567,3375],{"alt":3376,"src":3377},"Cloudflare dashboard left sidebar navigation menu with Zero Trust option","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-left-menu.webp",[580,3379,3380,3381,3384,3385],{},"If this is your first time, you will be prompted to choose a plan (the Free tier is perfectly fine for this setup) and name your team (e.g., ",[442,3382,3383],{},"ai-team",").\n",[567,3386],{"alt":3387,"src":3388},"Setting up first-time Cloudflare Zero Trust account and naming the team","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-team-setup.webp",[580,3390,3391,3392],{},"Click on 'Access' then 'Policies' to create an access policy defining who has access to the network.\n",[567,3393],{"alt":3394,"src":3395},"Cloudflare Zero Trust Access Policies page showing newly configured access rules","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-access-policies-page.webp",[580,3397,3398,3399],{},"Click on 'Create new policy'.\n",[567,3400],{"alt":3401,"src":3402},"Cloudflare Access policies page showing no policies added and a button to create a new policy.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20secure%20NodeWarden%20at%20Cloudflare\u002Fcloudflare-access-no-policies-create-button.png",[580,3404,3405,3406],{},"Select 'Emails' and enter your email under 'Policy rules'.\n",[567,3407],{"alt":3408,"src":3409},"Cloudflare Access policy rule configuration screen with an email address specified as the inclusion criteria.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20secure%20NodeWarden%20at%20Cloudflare\u002Fcloudflare-access-policy-rule-email.png",[572,3411,3413],{"id":3412},"step-2-set-up-cloudflare-warp-client-on-vps","Step 2: Set Up Cloudflare WARP Client on VPS",[577,3415,3416,3425,3431,3438,3441,3456,3459,3535],{},[580,3417,1095,3418,1915,3421,3424],{},[442,3419,3420],{},"sudo apt update",[442,3422,3423],{},"sudo apt install cloudflare-warp"," in the terminal on your VPS.",[580,3426,1095,3427,3430],{},[442,3428,3429],{},"warp-cli registration new \u003CTEAM-NAME>"," in the terminal on your VPS, which will print out a URL.",[580,3432,3433,3434,3437],{},"Copy the printed URL, which will look like ",[442,3435,3436],{},"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fwarp",", and paste it in your browser for authentication.",[580,3439,3440],{},"Since email authentication is used in the policy rule setup above, enter your email to authenticate.",[580,3442,3443,3444,3447,3448,3451,3452,3455],{},"On the '",[437,3445,3446],{},"Success","' page in the browser, right-click and select '",[437,3449,3450],{},"Inspect","' on the blue '",[437,3453,3454],{},"Open Cloudflare WARP","' button.",[580,3457,3458],{},"Copy the long token that is shown in the button's link.",[580,3460,1095,3461,3464,3465,3467,3468],{},[442,3462,3463],{},"warp-cli --accept-tos registration token \"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>\""," in the terminal on your VPS to connect it to Cloudflare Zero Trust.",[1961,3466],{},"If the 'Error: Failed to communicate with the WARP API' is encounter on Ubuntu 26, run the following commands:",[460,3469,3471],{"className":885,"code":3470,"language":887,"meta":423,"style":423},"sudo systemctl restart warp-svc.service\n\n# Check status\nsudo systemctl status warp-svc.service\n\n# Run the warp-cli registration token again\nwarp-cli --accept-tos registration token   \"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>\"\n",[442,3472,3473,3484,3488,3493,3503,3507,3512],{"__ignoreMap":423},[468,3474,3475,3477,3479,3481],{"class":470,"line":471},[468,3476,916],{"class":474},[468,3478,1036],{"class":489},[468,3480,1039],{"class":489},[468,3482,3483],{"class":489}," warp-svc.service\n",[468,3485,3486],{"class":470,"line":478},[468,3487,513],{"emptyLinePlaceholder":512},[468,3489,3490],{"class":470,"line":493},[468,3491,3492],{"class":2703},"# Check status\n",[468,3494,3495,3497,3499,3501],{"class":470,"line":504},[468,3496,916],{"class":474},[468,3498,1036],{"class":489},[468,3500,1479],{"class":489},[468,3502,3483],{"class":489},[468,3504,3505],{"class":470,"line":509},[468,3506,513],{"emptyLinePlaceholder":512},[468,3508,3509],{"class":470,"line":516},[468,3510,3511],{"class":2703},"# Run the warp-cli registration token again\n",[468,3513,3514,3517,3520,3523,3526,3529,3532],{"class":470,"line":522},[468,3515,3516],{"class":474},"warp-cli",[468,3518,3519],{"class":489}," --accept-tos",[468,3521,3522],{"class":489}," registration",[468,3524,3525],{"class":489}," token",[468,3527,3528],{"class":485},"   \"",[468,3530,3531],{"class":489},"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>",[468,3533,3534],{"class":485},"\"\n",[580,3536,3537,3538],{},"Head back to the Cloudflare Zero Trust dashboard, and click on 'Devices'. Your VPS device should now be displayed.\n",[567,3539],{"alt":3540,"src":3541},"Zero Trust Devices dashboard confirming the Linux VPS is connected","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-devices-vps-connected.webp",[572,3543,3545],{"id":3544},"step-3-set-up-traffic-routing","Step 3: Set Up Traffic Routing",[577,3547,3548,3555,3562,3569],{},[580,3549,3550,3551],{},"Click the profile for your VPS on the Devices dashboard.\n",[567,3552],{"alt":3553,"src":3554},"Accessing details and split tunnel settings for the registered VPS device","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-device-profile.webp",[580,3556,3557,3558],{},"Scroll down to the 'Split Tunnels' section.\n",[567,3559],{"alt":3560,"src":3561},"Split Tunnels section under VPS profile settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-split-tunnels-section.webp",[580,3563,3564,3565],{},"Click the 'Manage' button and configure the settings as shown below. Replace the IP address if necessary.\n",[567,3566],{"alt":3567,"src":3568},"Managing Split Tunnels IP and hostname exclusions in Cloudflare settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-manage-split-tunnels.webp",[580,3570,3571,3572,1915,3575,3578],{},"Exposing the ",[442,3573,3574],{},"address",[442,3576,3577],{},"host"," will route traffic to your services over the same private network.",[572,3580,3582],{"id":3581},"step-4-configure-firewall-on-the-vps","Step 4: Configure Firewall on the VPS",[433,3584,3585],{},"Enable the firewall to allow the '100.96.0.0\u002F12' subnet only, blocking all other public incoming access.",[460,3587,3589],{"className":885,"code":3588,"language":887,"meta":423,"style":423},"sudo ufw enable \nsudo ufw default allow outgoing \nsudo ufw default deny incoming\nsudo ufw allow in from 100.96.0.0\u002F12\n",[442,3590,3591,3602,3619,3633],{"__ignoreMap":423},[468,3592,3593,3595,3598,3600],{"class":470,"line":471},[468,3594,916],{"class":474},[468,3596,3597],{"class":489}," ufw",[468,3599,1456],{"class":489},[468,3601,962],{"class":961},[468,3603,3604,3606,3608,3611,3614,3617],{"class":470,"line":478},[468,3605,916],{"class":474},[468,3607,3597],{"class":489},[468,3609,3610],{"class":489}," default",[468,3612,3613],{"class":489}," allow",[468,3615,3616],{"class":489}," outgoing",[468,3618,962],{"class":961},[468,3620,3621,3623,3625,3627,3630],{"class":470,"line":493},[468,3622,916],{"class":474},[468,3624,3597],{"class":489},[468,3626,3610],{"class":489},[468,3628,3629],{"class":489}," deny",[468,3631,3632],{"class":489}," incoming\n",[468,3634,3635,3637,3639,3641,3644,3647],{"class":470,"line":504},[468,3636,916],{"class":474},[468,3638,3597],{"class":489},[468,3640,3613],{"class":489},[468,3642,3643],{"class":489}," in",[468,3645,3646],{"class":489}," from",[468,3648,3649],{"class":489}," 100.96.0.0\u002F12\n",[433,3651,3652],{},"Allow loopback traffic to avoid breaking local services:",[460,3654,3656],{"className":885,"code":3655,"language":887,"meta":423,"style":423},"sudo ufw allow in on lo\nsudo ufw allow out on lo\n",[442,3657,3658,3674],{"__ignoreMap":423},[468,3659,3660,3662,3664,3666,3668,3671],{"class":470,"line":471},[468,3661,916],{"class":474},[468,3663,3597],{"class":489},[468,3665,3613],{"class":489},[468,3667,3643],{"class":489},[468,3669,3670],{"class":489}," on",[468,3672,3673],{"class":489}," lo\n",[468,3675,3676,3678,3680,3682,3685,3687],{"class":470,"line":478},[468,3677,916],{"class":474},[468,3679,3597],{"class":489},[468,3681,3613],{"class":489},[468,3683,3684],{"class":489}," out",[468,3686,3670],{"class":489},[468,3688,3673],{"class":489},[433,3690,3691],{},"Reload the firewall and verify status:",[460,3693,3695],{"className":885,"code":3694,"language":887,"meta":423,"style":423},"sudo ufw reload \nsudo ufw status verbose\n",[442,3696,3697,3708],{"__ignoreMap":423},[468,3698,3699,3701,3703,3706],{"class":470,"line":471},[468,3700,916],{"class":474},[468,3702,3597],{"class":489},[468,3704,3705],{"class":489}," reload",[468,3707,962],{"class":961},[468,3709,3710,3712,3714,3716],{"class":470,"line":478},[468,3711,916],{"class":474},[468,3713,3597],{"class":489},[468,3715,1479],{"class":489},[468,3717,3718],{"class":489}," verbose\n",[572,3720,3722],{"id":3721},"step-5-expose-hermes-agent-to-the-private-network","Step 5: Expose Hermes Agent to the Private Network",[433,3724,3725,3726,3729,3730,1557],{},"We will expose the ",[437,3727,3728],{},"Hermes Agent Web Dashboard"," to our private network and use the default authentication provider, ",[437,3731,3732],{},"Nous Research",[3734,3735,3737],"h4",{"id":3736},"set-up-the-auth-provider","Set Up the Auth Provider",[577,3739,3740,3748,3755,3762,3769],{},[580,3741,1163,3742,3747],{},[450,3743,3746],{"href":3744,"rel":3745},"https:\u002F\u002Fportal.nousresearch.com",[454],"portal.nousresearch.com"," to register an account.",[580,3749,3750,3751],{},"Select 'Local Dashboards'.\n",[567,3752],{"alt":3753,"src":3754},"Selecting Local Dashboards option in the Nous Research portal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-local-dashboards-selection.webp",[580,3756,3757,3758],{},"Click 'Register Dashboard'.\n",[567,3759],{"alt":3760,"src":3761},"Clicking Register Dashboard button to create a new dashboard entry","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-register-dashboard.webp",[580,3763,3764,3765],{},"Enter the private network IP address of your VPS as the 'Dashboard redirect URI' and click 'Save'.\n",[567,3766],{"alt":3767,"src":3768},"Registering the private network VPS IP address as redirect URI in Nous Research portal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-register-redirect-uri.webp",[580,3770,3771,3772,3775],{},"Copy the 'OAuth client ID' and paste it in your ",[442,3773,3774],{},"config.yaml"," file:",[460,3777,3779],{"className":462,"code":3778,"language":464,"meta":423,"style":423},"dashboard:\n  theme: default\n  show_token_analytics: false\n  oauth:\n    client_id: agent:cmq02x7ha0002jk0ba3kfnb\n    portal_url: https:\u002F\u002Fportal.nousresearch.com\n  basic_auth:\n    username: ''\n    password_hash: ''\n",[442,3780,3781,3788,3798,3808,3815,3825,3835,3842,3852],{"__ignoreMap":423},[468,3782,3783,3786],{"class":470,"line":471},[468,3784,3785],{"class":481},"dashboard",[468,3787,2976],{"class":485},[468,3789,3790,3793,3795],{"class":470,"line":478},[468,3791,3792],{"class":481},"  theme",[468,3794,486],{"class":485},[468,3796,3797],{"class":489}," default\n",[468,3799,3800,3803,3805],{"class":470,"line":493},[468,3801,3802],{"class":481},"  show_token_analytics",[468,3804,486],{"class":485},[468,3806,3807],{"class":2986}," false\n",[468,3809,3810,3813],{"class":470,"line":504},[468,3811,3812],{"class":481},"  oauth",[468,3814,2976],{"class":485},[468,3816,3817,3820,3822],{"class":470,"line":509},[468,3818,3819],{"class":481},"    client_id",[468,3821,486],{"class":485},[468,3823,3824],{"class":489}," agent:cmq02x7ha0002jk0ba3kfnb\n",[468,3826,3827,3830,3832],{"class":470,"line":516},[468,3828,3829],{"class":481},"    portal_url",[468,3831,486],{"class":485},[468,3833,3834],{"class":489}," https:\u002F\u002Fportal.nousresearch.com\n",[468,3836,3837,3840],{"class":470,"line":522},[468,3838,3839],{"class":481},"  basic_auth",[468,3841,2976],{"class":485},[468,3843,3844,3847,3849],{"class":470,"line":527},[468,3845,3846],{"class":481},"    username",[468,3848,486],{"class":485},[468,3850,3851],{"class":485}," ''\n",[468,3853,3854,3857,3859],{"class":470,"line":533},[468,3855,3856],{"class":481},"    password_hash",[468,3858,486],{"class":485},[468,3860,3851],{"class":485},[3734,3862,3864],{"id":3863},"set-up-systemd-to-autostart-the-hermes-dashboard","Set Up Systemd to Autostart the Hermes Dashboard",[577,3866,3867],{},[580,3868,3869],{},"Create a service file:",[460,3871,3873],{"className":1332,"code":3872,"language":1334,"meta":423,"style":423},"sudo nano \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-dashboard.service\n",[442,3874,3875],{"__ignoreMap":423},[468,3876,3877,3879,3881],{"class":470,"line":471},[468,3878,916],{"class":474},[468,3880,996],{"class":489},[468,3882,3883],{"class":489}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-dashboard.service\n",[577,3885,3886],{"start":478},[580,3887,3888,3889,3892],{},"Paste the following configuration, ensuring ",[442,3890,3891],{},"--host 0.0.0.0"," is part of the command:",[460,3894,3896],{"className":1354,"code":3895,"language":1356,"meta":423,"style":423},"[Unit]\nDescription=Hermes Dashboard\nAfter=network.target\n\n[Service]\nUser=hermes\nWorkingDirectory=\u002Fhome\u002Fhermes\nExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes dashboard --host 0.0.0.0\nRestart=always\nRestartSec=10\nEnvironment=PATH=\u002Fhome\u002Fhermes\u002F.local\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin\n\n[Install]\nWantedBy=multi-user.target\n",[442,3897,3898,3902,3907,3911,3915,3919,3923,3927,3932,3936,3940,3944,3948,3952],{"__ignoreMap":423},[468,3899,3900],{"class":470,"line":471},[468,3901,1363],{},[468,3903,3904],{"class":470,"line":478},[468,3905,3906],{},"Description=Hermes Dashboard\n",[468,3908,3909],{"class":470,"line":493},[468,3910,1373],{},[468,3912,3913],{"class":470,"line":504},[468,3914,513],{"emptyLinePlaceholder":512},[468,3916,3917],{"class":470,"line":509},[468,3918,1382],{},[468,3920,3921],{"class":470,"line":516},[468,3922,1387],{},[468,3924,3925],{"class":470,"line":522},[468,3926,1392],{},[468,3928,3929],{"class":470,"line":527},[468,3930,3931],{},"ExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes dashboard --host 0.0.0.0\n",[468,3933,3934],{"class":470,"line":533},[468,3935,1402],{},[468,3937,3938],{"class":470,"line":538},[468,3939,1407],{},[468,3941,3942],{"class":470,"line":1410},[468,3943,1413],{},[468,3945,3946],{"class":470,"line":1416},[468,3947,513],{"emptyLinePlaceholder":512},[468,3949,3950],{"class":470,"line":1421},[468,3951,1424],{},[468,3953,3954],{"class":470,"line":1427},[468,3955,1430],{},[577,3957,3958],{"start":493},[580,3959,1433],{},[460,3961,3963],{"className":1332,"code":3962,"language":1334,"meta":423,"style":423},"sudo systemctl daemon-reload\nsudo systemctl enable hermes-dashboard\nsudo systemctl start hermes-dashboard\nsudo systemctl status hermes-dashboard\n",[442,3964,3965,3973,3984,3994],{"__ignoreMap":423},[468,3966,3967,3969,3971],{"class":470,"line":471},[468,3968,916],{"class":474},[468,3970,1036],{"class":489},[468,3972,1447],{"class":489},[468,3974,3975,3977,3979,3981],{"class":470,"line":478},[468,3976,916],{"class":474},[468,3978,1036],{"class":489},[468,3980,1456],{"class":489},[468,3982,3983],{"class":489}," hermes-dashboard\n",[468,3985,3986,3988,3990,3992],{"class":470,"line":493},[468,3987,916],{"class":474},[468,3989,1036],{"class":489},[468,3991,1468],{"class":489},[468,3993,3983],{"class":489},[468,3995,3996,3998,4000,4002],{"class":470,"line":504},[468,3997,916],{"class":474},[468,3999,1036],{"class":489},[468,4001,1479],{"class":489},[468,4003,3983],{"class":489},[572,4005,4007],{"id":4006},"step-6-install-cloudflare-warp-client-on-desktop","Step 6: Install Cloudflare WARP Client on Desktop",[577,4009,4010,4018,4021,4028,4035,4042],{},[580,4011,4012,4013,1557],{},"Download the Cloudflare WARP client from ",[450,4014,4017],{"href":4015,"rel":4016},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fwarp-client\u002Fget-started\u002F",[454],"Cloudflare's portal",[580,4019,4020],{},"Open and launch the Cloudflare WARP client after installation.",[580,4022,4023,4024],{},"Log in when prompted.\n",[567,4025],{"alt":4026,"src":4027},"Cloudflare WARP client login prompt on desktop machine","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-login-prompt.webp",[580,4029,4030,4031],{},"A 'Success' page will be displayed after a successful login.\n",[567,4032],{"alt":4033,"src":4034},"Authentication success webpage after logging in to Cloudflare Zero Trust on desktop","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-login-success.webp",[580,4036,4037,4038],{},"The WARP client should now show it is connected to your Zero Trust team.\n",[567,4039],{"alt":4040,"src":4041},"Desktop Cloudflare WARP client confirming active connection to Zero Trust private network","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-client-connected.webp",[580,4043,4044,4045,4048,4049],{},"Navigate to your web browser and enter your private IP (e.g., ",[442,4046,4047],{},"100.96.0.3","). The Hermes Web Dashboard should load successfully.\n",[567,4050],{"alt":4051,"src":4052},"Accessing the private Hermes Agent Web Dashboard in browser on desktop","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fhermes-agent-dashboard-desktop-view.webp",[4054,4055,4056],"blockquote",{},[433,4057,4058,4061,4062,4066],{},[437,4059,4060],{},"Pro Tip for macOS Users:"," If you are using the WARP client to access multiple Cloudflare accounts, check out our quick guide on ",[437,4063,4064],{},[450,4065,398],{"href":399}," to make switching between accounts seamless.",[572,4068,4070],{"id":4069},"step-7-install-cloudflare-warp-client-on-ios-devices","Step 7: Install Cloudflare WARP Client on iOS Devices",[577,4072,4073,4080,4088,4096,4104],{},[580,4074,4075,4076,4079],{},"Install ",[437,4077,4078],{},"Cloudflare One"," from the App Store.",[580,4081,4082,4083],{},"Open the Cloudflare One app and enter your team name when prompted.\n",[567,4084],{"alt":4085,"src":4086,"width":4087},"Entering Cloudflare Zero Trust team name in Cloudflare One app on iOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-team-name-prompt.webp",239,[580,4089,4090,4091],{},"Log in using the same email address that was configured in the policy rule above.\n",[567,4092],{"alt":4093,"src":4094,"width":4095},"Email authentication prompt for Cloudflare Zero Trust on iOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-email-login.webp",229,[580,4097,4098,4099],{},"Once it is connected, it should look like the following:\n",[567,4100],{"alt":4101,"src":4102,"width":4103},"Cloudflare One app showing connected status on iOS mobile device","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-client-connected.webp",322,[580,4105,4106,4107,4109,4110],{},"Navigate to your web browser and enter the private IP ",[442,4108,4047],{}," to access the Hermes Web Dashboard on your mobile device.\n",[567,4111],{"alt":4112,"src":4113,"width":4114},"Accessing Hermes Agent Web Dashboard interface on mobile phone browser","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fhermes-agent-dashboard-mobile-view.webp",345,[428,4116,806],{"id":805},[433,4118,4119,4120,4122,4123,4126],{},"With ",[437,4121,3311],{}," handling identity policies and the ",[437,4124,4125],{},"WARP"," client routing traffic over an encrypted tunnel, your Hermes Agent is securely reachable from your devices globally. This setup lays a secure, robust foundation for building and accessing a fully remote, private AI infrastructure.",[822,4128,4129],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":423,"searchDepth":478,"depth":493,"links":4131},[4132,4135,4147],{"id":3324,"depth":478,"text":3325,"children":4133},[4134],{"id":3343,"depth":493,"text":3344},{"id":3355,"depth":478,"text":3356,"children":4136},[4137,4138,4139,4140,4141,4145,4146],{"id":3359,"depth":493,"text":3360},{"id":3412,"depth":493,"text":3413},{"id":3544,"depth":493,"text":3545},{"id":3581,"depth":493,"text":3582},{"id":3721,"depth":493,"text":3722,"children":4142},[4143,4144],{"id":3736,"depth":504,"text":3737},{"id":3863,"depth":504,"text":3864},{"id":4006,"depth":493,"text":4007},{"id":4069,"depth":493,"text":4070},{"id":805,"depth":478,"text":806},[836,2073],"2026-07-09","Learn how to securely expose and access your Hermes Agent globally using Cloudflare WARP and Zero Trust without opening inbound firewall ports.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002FEN-Exposing-Hermes-Agent-to-Private-Network-Using-Cloudflare-WARP.webp","Securely exposing Hermes Agent to a private network using Cloudflare Zero Trust and WARP tunnel",{"schemaOrg":4154,"robots":846,"sitemap":4185},[4155],{"@type":845,"headline":362,"description":4150,"name":362,"image":4151,"step":4156},[4157,4161,4165,4169,4173,4177,4181],{"@type":1511,"name":4158,"text":4159,"url":4160,"image":3377},"Set Up Cloudflare Zero Trust","Log in to your Cloudflare Dashboard. Click on 'Zero Trust' from the left menu. If this is your first time, you will be prompted to choose a plan (the Free tier is perfectly fine for this setup) and name your team (e.g., ai-team). Click on 'Access' th","#step-1",{"@type":1511,"name":4162,"text":4163,"url":4164,"image":3541},"Set Up Cloudflare WARP Client on VPS","Run sudo apt update and sudo apt install cloudflare-warp in the terminal on your VPS. Run warp-cli registration new \u003CTEAM-NAME> in the terminal on your VPS, which will print out a URL. Copy the printed URL, which will look like https:\u002F\u002F\u003Cteam>.cloudfl","#step-2",{"@type":1511,"name":4166,"text":4167,"url":4168,"image":3554},"Set Up Traffic Routing","Click the profile for your VPS on the Devices dashboard. Scroll down to the 'Split Tunnels' section. Click the 'Manage' button and configure the settings as shown below. Replace the IP address if necessary. Exposing the address and host will route tr","#step-3",{"@type":1511,"name":4170,"text":4171,"url":4172},"Configure Firewall on the VPS","Enable the firewall to allow the '100.96.0.0\u002F12' subnet only, blocking all other public incoming access. bash Allow loopback traffic to avoid breaking local services: bash Reload the firewall and verify status: bash","#step-4",{"@type":1511,"name":4174,"text":4175,"url":4176},"Expose Hermes Agent to the Private Network","We will expose the Hermes Agent Web Dashboard to our private network and use the default authentication provider, Nous Research.","#step-5",{"@type":1511,"name":4178,"text":4179,"url":4180,"image":4027},"Install Cloudflare WARP Client on Desktop","Download the Cloudflare WARP client from Cloudflare's portal. Open and launch the Cloudflare WARP client after installation. Log in when prompted. A 'Success' page will be displayed after a successful login. The WARP client should now show it is conn","#step-6",{"@type":1511,"name":4182,"text":4183,"url":4184,"image":4086},"Install Cloudflare WARP Client on iOS Devices","Install Cloudflare One from the App Store. Open the Cloudflare One app and enter your team name when prompted. Log in using the same email address that was configured in the policy rule above. Once it is connected, it should look like the following:","#step-7",{"lastmod":4186},"2026-09-28",{"title":4188,"description":4150,"ogTitle":362,"ogDescription":4150,"twitterTitle":362,"twitterDescription":4150},"Secure Hermes Agent Access with Cloudflare Zero Trust",[2002,2087,1296,4190,4191],"VPN","Tutorial","7w7yHDwhXSX7-e5xSvZ3rQ_6OcpB47010zvSqV1GJ9M",{"id":4194,"title":382,"author":423,"body":4195,"category":6337,"date":6338,"description":2124,"extension":839,"image":2125,"imageAlt":2126,"isPublished":512,"meta":6339,"minRead":1679,"navigation":512,"path":383,"seo":6361,"stem":384,"tags":6363,"updatedAt":854,"__hash__":6367},"article\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues.md",{"type":425,"value":4196,"toc":6307},[4197,4200,4206,4211,4215,4218,4256,4260,4266,4304,4308,4312,4326,4332,4336,4340,4344,4358,4364,4413,4441,4445,4453,4459,4463,4466,4671,4675,4721,4728,4735,4741,4791,4797,4825,4829,4833,4860,4888,4893,4935,4944,5214,5218,5264,5269,5276,5281,5285,5309,5312,5318,5321,5325,5333,5339,5342,5348,5355,5379,5385,5391,5394,5400,5404,5407,5410,5413,5419,5422,5428,5434,5440,5445,5449,5460,5467,5473,5476,5482,5486,5493,5499,5505,5509,5517,5580,5593,5648,5651,5721,5727,5741,5747,5751,5796,5802,5805,5811,5814,5820,5824,5839,5855,5861,5958,5961,5967,5978,6024,6030,6036,6048,6064,6067,6073,6077,6086,6108,6118,6216,6226,6232,6239,6245,6248,6254,6257,6263,6267,6270,6274,6304],[433,4198,4199],{},"Context fragmentation is a frustrating hurdle when working with multiple AI agents. With conversations scattered across different tools, you end up acting as a human router by copying conversations from Claude Code to paste into Gemini CLI, then copying from Gemini CLI to paste into Hermes Agent. This friction increases when human colleagues are on the same team.",[433,4201,4202],{},[567,4203],{"alt":4204,"src":4205},"The user interface of the Buzz collaborative workspace showing chat channels and active AI agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-workspace-interface.webp",[433,4207,4208,4210],{},[437,4209,2115],{},", an open-source collaboration workspace, brings human teams and AI agents together into a single, unified environment. Here, human colleagues and AI agents share the same task and project history, seamlessly handing work off to one another.",[428,4212,4214],{"id":4213},"what-is-blocks-buzz-the-collaborative-ai-agent-workspace","What is Block's Buzz? The Collaborative AI Agent Workspace",[433,4216,4217],{},"Buzz is an open-source collaboration workspace from Block (Jack Dorsey's company) where humans and AI agents share the same channels and projects. It offers the following key features:",[724,4219,4220,4226,4232,4238,4244,4250],{},[580,4221,4222,4225],{},[437,4223,4224],{},"Shared context:"," Channels are where humans and agents collaborate with one another. All conversational and project history is contained within the channel.",[580,4227,4228,4231],{},[437,4229,4230],{},"Agent-to-agent communication:"," Agents can communicate with each other, even across different machines. An agent can @-mention another agent to hand off work or cross-check code.",[580,4233,4234,4237],{},[437,4235,4236],{},"Mention-driven activation:"," Agents only act when @-mentioned, otherwise staying quiet. When mentioned, an agent reads the relevant context in the channel and start working.",[580,4239,4240,4243],{},[437,4241,4242],{},"Unified identity system:"," Humans and agents use the same identity system, authenticated via cryptographic keys.",[580,4245,4246,4249],{},[437,4247,4248],{},"Delegated commands:"," You can grant human colleagues permission to command your agents, allowing the entire team to brief and leverage each other's digital helpers.",[580,4251,4252,4255],{},[437,4253,4254],{},"Self-hosted servers:"," Because you host the server, your data remains fully under your control. You choose who joins and define your own operational rules.",[428,4257,4259],{"id":4258},"the-cryptographic-nostr-powered-architecture-of-buzz","The Cryptographic, Nostr-Powered Architecture of Buzz",[433,4261,4262],{},[567,4263],{"alt":4264,"src":4265},"Cryptographic, Nostr-powered architectural diagram of the Buzz collaboration workspace","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-nostr-cryptographic-architecture.webp",[724,4267,4268,4274,4280,4286,4292,4298],{},[580,4269,4270,4273],{},[437,4271,4272],{},"The Nostr relay acts as the server:"," Messages, workflows, repositories, and other events are cryptographically signed, verified, and stored on a Nostr relay server. The Nostr protocol natively supports communication over WebSockets and REST APIs.",[580,4275,4276,4279],{},[437,4277,4278],{},"Unified cryptographic identity:"," Both humans and agents authenticate using their own cryptographic keys. This identity remains client-side and is never stored on the server.",[580,4281,4282,4285],{},[437,4283,4284],{},"First-class agent membership:"," Every agent possesses its own identity, channel memberships, and audit trail. Agents connect to the workspace using the Agent Communication Protocol (ACP).",[580,4287,4288,4291],{},[437,4289,4290],{},"Decentralised Git repositories:"," Code repositories are stored on S3 compatible object storage, while tasks, pull requests, and code reviews are tracked within the Nostr event log. Consequently, a Buzz Git repository is hosted on the Nostr relay rather than GitHub.",[580,4293,4294,4297],{},[437,4295,4296],{},"The Buzz app is a Nostr client:"," Buzz is separate from the Nostr relay; it is a desktop\u002Fmobile client application that connects to the relay's URL.",[580,4299,4300,4303],{},[437,4301,4302],{},"Infrastructure stack:"," A PostgreSQL database handles event storage and full-text search, Redis manages pub\u002Fsub messaging, and S3 compatible MinIO is used for media storage.",[428,4305,4307],{"id":4306},"how-to-self-host-blocks-buzz-relay-on-a-linux-vps","How to Self-Host Block's Buzz Relay on a Linux VPS",[572,4309,4311],{"id":4310},"_0-prerequisites","0. Prerequisites",[724,4313,4314,4317,4320,4323],{},[580,4315,4316],{},"A Linux VPS",[580,4318,4319],{},"A domain pointing at your server",[580,4321,4322],{},"Docker and the Docker Compose plugin",[580,4324,4325],{},"Cloudflare account (free tier)",[433,4327,4328,4329,4331],{},"In this guide, we will run the Nostr relay on an Ubuntu VPS behind a ",[450,4330,3311],{"href":363}," private network. The stack is four services in Docker Compose, relay, PostgreSQL, Redis and MinIO.",[2122,4333],{"description":4150,"image":4151,"image-alt":4152,"label":4334,"min-read":4335,"title":362,"to":363},"Related guide","8",[572,4337,4339],{"id":4338},"_1-cloudflare-dns-and-api-token","1. Cloudflare DNS and API Token",[3734,4341,4343],{"id":4342},"create-a-cloudflare-api-token","Create a Cloudflare API Token",[577,4345,4346,4353],{},[580,4347,4348,4349,4352],{},"Click on the top right ",[437,4350,4351],{},"Profile"," from the user icon dropdown menu.",[580,4354,1228,4355,1557],{},[437,4356,4357],{},"API Tokens",[433,4359,4360],{},[567,4361],{"alt":4362,"src":4363},"Cloudflare user profile page showing the API Tokens creation menu","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-profile-api-tokens.webp",[577,4365,4366,4371,4378,4398,4403,4407,4410],{"start":493},[580,4367,1173,4368,1557],{},[437,4369,4370],{},"Create Token",[580,4372,4373,4374,4377],{},"Use the ",[437,4375,4376],{},"Edit zone DNS"," template.",[580,4379,4380,4381],{},"Configure the template as follows:\n",[724,4382,4383,4389],{},[580,4384,4385,4388],{},[437,4386,4387],{},"Permissions",": Zone — DNS — Edit",[580,4390,4391,4394,4395],{},[437,4392,4393],{},"Zone Resources",": Include — Specific zone — ",[442,4396,4397],{},"example.com",[580,4399,1173,4400,1557],{},[437,4401,4402],{},"Continue to summary",[580,4404,1173,4405,1557],{},[437,4406,4370],{},[580,4408,4409],{},"Copy the generated token as it won't be shown when the page is closed.",[580,4411,4412],{},"Test the generated token in your terminal to ensure it works:",[460,4414,4416],{"className":885,"code":4415,"language":887,"meta":423,"style":423},"curl \"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify\" -H \"Authorization: Bearer YOUR_TOKEN_HERE\"\n",[442,4417,4418],{"__ignoreMap":423},[468,4419,4420,4422,4425,4428,4431,4434,4436,4439],{"class":470,"line":471},[468,4421,1059],{"class":474},[468,4423,4424],{"class":485}," \"",[468,4426,4427],{"class":489},"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify",[468,4429,4430],{"class":485},"\"",[468,4432,4433],{"class":489}," -H",[468,4435,4424],{"class":485},[468,4437,4438],{"class":489},"Authorization: Bearer YOUR_TOKEN_HERE",[468,4440,3534],{"class":485},[3734,4442,4444],{"id":4443},"dns-records","DNS Records",[724,4446,4447],{},[580,4448,4449,4450,1557],{},"Create an A record and set it to ",[437,4451,4452],{},"DNS only",[433,4454,4455],{},[567,4456],{"alt":4457,"src":4458},"Configuring a DNS A record for the Buzz domain in Cloudflare dashboard with proxy status set to DNS only","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-dns-a-record-configuration.webp",[572,4460,4462],{"id":4461},"_2-install-docker-on-ubuntu","2. Install Docker on Ubuntu",[433,4464,4465],{},"Run the following commands to install Docker on Ubuntu:",[460,4467,4469],{"className":885,"code":4468,"language":887,"meta":423,"style":423},"# Add Docker's official GPG key and set up the Docker repository\ncurl -fsSL https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg | sudo gpg --dearmor -o \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n\n# Add the official Docker repository\necho \"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu $(lsb_release -cs) stable\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list > \u002Fdev\u002Fnull\n\n# Update package list\nsudo apt update\n\n# Install Docker Engine, Docker Community Edition, and containerd runtime\nsudo apt install docker-ce docker-ce-cli containerd.io -y\n\n# Start automatically when the system boots\nsudo systemctl enable docker\n\n# Verify docker is installed\ndocker --version\n\nsudo apt install -y docker-compose-plugin\n\n# Verify the compose plugin is installed\ndocker compose version\n\n",[442,4470,4471,4476,4501,4505,4510,4553,4557,4562,4571,4575,4580,4600,4604,4609,4620,4624,4629,4635,4639,4653,4657,4662],{"__ignoreMap":423},[468,4472,4473],{"class":470,"line":471},[468,4474,4475],{"class":2703},"# Add Docker's official GPG key and set up the Docker repository\n",[468,4477,4478,4480,4482,4485,4487,4489,4492,4495,4498],{"class":470,"line":478},[468,4479,1059],{"class":474},[468,4481,1062],{"class":489},[468,4483,4484],{"class":489}," https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg",[468,4486,1068],{"class":485},[468,4488,928],{"class":474},[468,4490,4491],{"class":489}," gpg",[468,4493,4494],{"class":489}," --dearmor",[468,4496,4497],{"class":489}," -o",[468,4499,4500],{"class":489}," \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n",[468,4502,4503],{"class":470,"line":493},[468,4504,513],{"emptyLinePlaceholder":512},[468,4506,4507],{"class":470,"line":504},[468,4508,4509],{"class":2703},"# Add the official Docker repository\n",[468,4511,4512,4515,4517,4520,4523,4526,4529,4532,4535,4537,4539,4541,4544,4547,4550],{"class":470,"line":509},[468,4513,4514],{"class":2603},"echo",[468,4516,4424],{"class":485},[468,4518,4519],{"class":489},"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu ",[468,4521,4522],{"class":485},"$(",[468,4524,4525],{"class":474},"lsb_release",[468,4527,4528],{"class":489}," -cs",[468,4530,4531],{"class":485},")",[468,4533,4534],{"class":489}," stable",[468,4536,4430],{"class":485},[468,4538,1068],{"class":485},[468,4540,928],{"class":474},[468,4542,4543],{"class":489}," tee",[468,4545,4546],{"class":489}," \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list",[468,4548,4549],{"class":485}," >",[468,4551,4552],{"class":489}," \u002Fdev\u002Fnull\n",[468,4554,4555],{"class":470,"line":516},[468,4556,513],{"emptyLinePlaceholder":512},[468,4558,4559],{"class":470,"line":522},[468,4560,4561],{"class":2703},"# Update package list\n",[468,4563,4564,4566,4568],{"class":470,"line":527},[468,4565,916],{"class":474},[468,4567,919],{"class":489},[468,4569,4570],{"class":489}," update\n",[468,4572,4573],{"class":470,"line":533},[468,4574,513],{"emptyLinePlaceholder":512},[468,4576,4577],{"class":470,"line":538},[468,4578,4579],{"class":2703},"# Install Docker Engine, Docker Community Edition, and containerd runtime\n",[468,4581,4582,4584,4586,4589,4592,4595,4598],{"class":470,"line":1410},[468,4583,916],{"class":474},[468,4585,919],{"class":489},[468,4587,4588],{"class":489}," install",[468,4590,4591],{"class":489}," docker-ce",[468,4593,4594],{"class":489}," docker-ce-cli",[468,4596,4597],{"class":489}," containerd.io",[468,4599,936],{"class":489},[468,4601,4602],{"class":470,"line":1416},[468,4603,513],{"emptyLinePlaceholder":512},[468,4605,4606],{"class":470,"line":1421},[468,4607,4608],{"class":2703},"# Start automatically when the system boots\n",[468,4610,4611,4613,4615,4617],{"class":470,"line":1427},[468,4612,916],{"class":474},[468,4614,1036],{"class":489},[468,4616,1456],{"class":489},[468,4618,4619],{"class":489}," docker\n",[468,4621,4622],{"class":470,"line":1673},[468,4623,513],{"emptyLinePlaceholder":512},[468,4625,4626],{"class":470,"line":1679},[468,4627,4628],{"class":2703},"# Verify docker is installed\n",[468,4630,4631,4633],{"class":470,"line":1685},[468,4632,2784],{"class":474},[468,4634,1092],{"class":489},[468,4636,4637],{"class":470,"line":1691},[468,4638,513],{"emptyLinePlaceholder":512},[468,4640,4641,4643,4645,4647,4650],{"class":470,"line":1697},[468,4642,916],{"class":474},[468,4644,919],{"class":489},[468,4646,4588],{"class":489},[468,4648,4649],{"class":489}," -y",[468,4651,4652],{"class":489}," docker-compose-plugin\n",[468,4654,4655],{"class":470,"line":1703},[468,4656,513],{"emptyLinePlaceholder":512},[468,4658,4659],{"class":470,"line":1709},[468,4660,4661],{"class":2703},"# Verify the compose plugin is installed\n",[468,4663,4664,4666,4668],{"class":470,"line":1715},[468,4665,2784],{"class":474},[468,4667,2787],{"class":489},[468,4669,4670],{"class":489}," version\n",[572,4672,4674],{"id":4673},"_3-clone-and-configure","3. Clone and configure",[460,4676,4678],{"className":885,"code":4677,"language":887,"meta":423,"style":423},"git clone https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n\ncd buzz\u002Fdeploy\u002Fcompose\ncp .env.example .env\nnano .env\n",[442,4679,4680,4691,4695,4703,4714],{"__ignoreMap":423},[468,4681,4682,4685,4688],{"class":470,"line":471},[468,4683,4684],{"class":474},"git",[468,4686,4687],{"class":489}," clone",[468,4689,4690],{"class":489}," https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n",[468,4692,4693],{"class":470,"line":478},[468,4694,513],{"emptyLinePlaceholder":512},[468,4696,4697,4700],{"class":470,"line":493},[468,4698,4699],{"class":2603},"cd",[468,4701,4702],{"class":489}," buzz\u002Fdeploy\u002Fcompose\n",[468,4704,4705,4708,4711],{"class":470,"line":504},[468,4706,4707],{"class":474},"cp",[468,4709,4710],{"class":489}," .env.example",[468,4712,4713],{"class":489}," .env\n",[468,4715,4716,4719],{"class":470,"line":509},[468,4717,4718],{"class":474},"nano",[468,4720,4713],{"class":489},[433,4722,4723,4724,4727],{},"Edit ",[442,4725,4726],{},".env"," in groups:",[724,4729,4730],{},[580,4731,4732],{},[437,4733,4734],{},"Domain:",[460,4736,4739],{"className":4737,"code":4738,"language":1017},[1015],"BUZZ_DOMAIN=buzz.pafor.me\nRELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\nBUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_MEDIA_BASE_URL=https:\u002F\u002Fbuzz.pafor.me\u002Fmedia\nBUZZ_MEDIA_SERVER_DOMAIN=buzz.pafor.me\nBUZZ_CORS_ORIGINS=https:\u002F\u002Fbuzz.pafor.me\n",[442,4740,4738],{"__ignoreMap":423},[724,4742,4743,4752],{},[580,4744,4745,2637,4748,4751],{},[437,4746,4747],{},"Owner key:",[442,4749,4750],{},"RELAY_OWNER_PUBKEY"," requires your 64-character hex public key. Generate an identity in the desktop app first ('Create a new identity key' → copy your public ID, which is in npub format), then convert it to hex.",[580,4753,4754,4757],{},[437,4755,4756],{},"Secrets:",[724,4758,4759,4771,4785],{},[580,4760,4761,4762,4766,4767,4770],{},"Generate secrets using this ",[450,4763,4765],{"href":4764},"\u002Ftools\u002Fsecret-key-hex","online tool"," or with ",[442,4768,4769],{},"openssl rand -hex 32"," (run it seven times)",[580,4772,4773,4774,4777,4778,2396,4781,4784],{},"Replace every ",[442,4775,4776],{},"CHANGE_ME"," placeholder: ",[442,4779,4780],{},"BUZZ_RELAY_PRIVATE_KEY",[442,4782,4783],{},"BUZZ_GIT_HOOK_HMAC_SECRET",", the Postgres\u002FRedis\u002FTypesense passwords, and the S3 access\u002Fsecret keys.",[580,4786,4787,4788,1557],{},"Leftover placeholders are the most common cause of container restart loops; verify yours with ",[442,4789,4790],{},"grep CHANGE_ME .env",[460,4792,4795],{"className":4793,"code":4794,"language":1017},[1015],"    BUZZ_RELAY_PRIVATE_KEY=CHANGE_ME_64_HEX_PRIVATE_KEY\n    BUZZ_GIT_HOOK_HMAC_SECRET=CHANGE_ME_RANDOM_64_HEX\n    POSTGRES_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    REDIS_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    TYPESENSE_API_KEY=CHANGE_ME_RANDOM_API_KEY\n    BUZZ_S3_ACCESS_KEY=CHANGE_ME_RANDOM_ACCESS_KEY\n    BUZZ_S3_SECRET_KEY=CHANGE_ME_RANDOM_SECRET_KEY\n",[442,4796,4794],{"__ignoreMap":423},[724,4798,4799],{},[580,4800,4801,4804],{},[437,4802,4803],{},"Others:",[724,4805,4806,4813],{},[580,4807,4808,4809,4812],{},"Add ",[442,4810,4811],{},"CLOUDFLARE_API_TOKEN"," as an environment variable and assign the API token generated earlier. This is required for Caddy.",[580,4814,4815,4816,2396,4818,4821,4822,1557],{},"Buzz ships with open defaults — anyone who knows your relay URL can authenticate and join. Set ",[442,4817,4750],{},[442,4819,4820],{},"BUZZ_REQUIRE_RELAY_MEMBERSHIP=true",", and ",[442,4823,4824],{},"BUZZ_REQUIRE_AUTH_TOKEN=true",[572,4826,4828],{"id":4827},"_4-enable-https-with-caddy","4. Enable HTTPS with Caddy",[3734,4830,4832],{"id":4831},"build-a-custom-caddy-image-with-the-cloudflare-dns-module","Build a Custom Caddy Image with the Cloudflare DNS Module",[724,4834,4835,4846,4857],{},[580,4836,4837,4838,4841,4842,4845],{},"We set up DNS-01 with Cloudflare for Caddy. DNS-01 works by having the plugin write a TXT record ",[442,4839,4840],{},"_acme-challenge.buzz.pafor.me"," to the ",[437,4843,4844],{},"public DNS",";",[580,4847,4848,4849,4852,4853,4856],{},"Let's Encrypt then looks the record up from the public internet to verify domain control. This means ",[442,4850,4851],{},"pafor.me"," must be a public zone in your Cloudflare account — not just a private hostname that only exists in Zero Trust \u002F WARP private DNS. If ",[442,4854,4855],{},"buzz.pafor.me"," is only resolved privately and there is no public zone, DNS-01 will fail, requiring a different approach.",[580,4858,4859],{},"Add the following to the Caddyfile:",[460,4861,4863],{"className":2951,"code":4862,"language":2953,"meta":423,"style":423},"{\n  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}\n}\n",[442,4864,4865,4870,4884],{"__ignoreMap":423},[468,4866,4867],{"class":470,"line":471},[468,4868,4869],{"class":485},"{\n",[468,4871,4872,4875,4878,4881],{"class":470,"line":478},[468,4873,4874],{"class":489},"  acme_dns cloudflare",[468,4876,4877],{"class":485}," {",[468,4879,4880],{"class":489},"env.CLOUDFLARE_API_TOKEN",[468,4882,4883],{"class":485},"}\n",[468,4885,4886],{"class":470,"line":493},[468,4887,4883],{"class":485},[724,4889,4890],{},[580,4891,4892],{},"Create a Dockerfile.caddy with the following content, which is required by compose.caddy.yml:",[460,4894,4896],{"className":2951,"code":4895,"language":2953,"meta":423,"style":423},"FROM caddy:2-builder AS builder\n\nRUN xcaddy build \\\n    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n\nFROM caddy:2-alpine\n\nCOPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[442,4897,4898,4903,4907,4912,4917,4921,4926,4930],{"__ignoreMap":423},[468,4899,4900],{"class":470,"line":471},[468,4901,4902],{"class":489},"FROM caddy:2-builder AS builder\n",[468,4904,4905],{"class":470,"line":478},[468,4906,513],{"emptyLinePlaceholder":512},[468,4908,4909],{"class":470,"line":493},[468,4910,4911],{"class":489},"RUN xcaddy build \\\n",[468,4913,4914],{"class":470,"line":504},[468,4915,4916],{"class":489},"    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n",[468,4918,4919],{"class":470,"line":509},[468,4920,513],{"emptyLinePlaceholder":512},[468,4922,4923],{"class":470,"line":516},[468,4924,4925],{"class":489},"FROM caddy:2-alpine\n",[468,4927,4928],{"class":470,"line":522},[468,4929,513],{"emptyLinePlaceholder":512},[468,4931,4932],{"class":470,"line":527},[468,4933,4934],{"class":489},"COPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[724,4936,4937],{},[580,4938,4939,4940,4943],{},"Modify ",[442,4941,4942],{},"compose.caddy.yml"," to use the image with the Cloudflare module and pass the Cloudflare API token:",[460,4945,4947],{"className":2951,"code":4946,"language":2953,"meta":423,"style":423},"services:\n  relay:\n    ports: !reset []\n\n  caddy:\n    build:\n      context: .\n      dockerfile: Dockerfile.caddy\n    image: buzz-caddy:cloudflare\n    depends_on:\n      relay:\n        condition: service_healthy\n    environment:\n      BUZZ_DOMAIN: ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n      CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n    ports:\n      - \"${CADDY_HTTP_PORT:-80}:80\"\n      - \"${CADDY_HTTPS_PORT:-443}:443\"\n    volumes:\n      - .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n      - buzz-caddy-data:\u002Fdata\n      - buzz-caddy-config:\u002Fconfig\n    restart: unless-stopped\n    networks:\n      - buzz-net\n\nvolumes:\n  buzz-caddy-data:\n    labels:\n      com.buzz.volume: caddy-data\n  buzz-caddy-config:\n    labels:\n      com.buzz.volume: caddy-config\n",[442,4948,4949,4956,4963,4976,4980,4987,4994,5005,5015,5025,5032,5039,5049,5056,5066,5076,5082,5094,5105,5112,5119,5126,5133,5143,5150,5157,5161,5168,5175,5182,5192,5199,5205],{"__ignoreMap":423},[468,4950,4951,4954],{"class":470,"line":471},[468,4952,4953],{"class":481},"services",[468,4955,2976],{"class":485},[468,4957,4958,4961],{"class":470,"line":478},[468,4959,4960],{"class":481},"  relay",[468,4962,2976],{"class":485},[468,4964,4965,4968,4970,4973],{"class":470,"line":493},[468,4966,4967],{"class":481},"    ports",[468,4969,486],{"class":485},[468,4971,4972],{"class":2580}," !reset",[468,4974,4975],{"class":485}," []\n",[468,4977,4978],{"class":470,"line":504},[468,4979,513],{"emptyLinePlaceholder":512},[468,4981,4982,4985],{"class":470,"line":509},[468,4983,4984],{"class":481},"  caddy",[468,4986,2976],{"class":485},[468,4988,4989,4992],{"class":470,"line":516},[468,4990,4991],{"class":481},"    build",[468,4993,2976],{"class":485},[468,4995,4996,4999,5001],{"class":470,"line":522},[468,4997,4998],{"class":481},"      context",[468,5000,486],{"class":485},[468,5002,5004],{"class":5003},"sbssI"," .\n",[468,5006,5007,5010,5012],{"class":470,"line":527},[468,5008,5009],{"class":481},"      dockerfile",[468,5011,486],{"class":485},[468,5013,5014],{"class":489}," Dockerfile.caddy\n",[468,5016,5017,5020,5022],{"class":470,"line":533},[468,5018,5019],{"class":481},"    image",[468,5021,486],{"class":485},[468,5023,5024],{"class":489}," buzz-caddy:cloudflare\n",[468,5026,5027,5030],{"class":470,"line":538},[468,5028,5029],{"class":481},"    depends_on",[468,5031,2976],{"class":485},[468,5033,5034,5037],{"class":470,"line":1410},[468,5035,5036],{"class":481},"      relay",[468,5038,2976],{"class":485},[468,5040,5041,5044,5046],{"class":470,"line":1416},[468,5042,5043],{"class":481},"        condition",[468,5045,486],{"class":485},[468,5047,5048],{"class":489}," service_healthy\n",[468,5050,5051,5054],{"class":470,"line":1421},[468,5052,5053],{"class":481},"    environment",[468,5055,2976],{"class":485},[468,5057,5058,5061,5063],{"class":470,"line":1427},[468,5059,5060],{"class":481},"      BUZZ_DOMAIN",[468,5062,486],{"class":485},[468,5064,5065],{"class":489}," ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n",[468,5067,5068,5071,5073],{"class":470,"line":1673},[468,5069,5070],{"class":481},"      CLOUDFLARE_API_TOKEN",[468,5072,486],{"class":485},[468,5074,5075],{"class":489}," ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n",[468,5077,5078,5080],{"class":470,"line":1679},[468,5079,4967],{"class":481},[468,5081,2976],{"class":485},[468,5083,5084,5087,5089,5092],{"class":470,"line":1685},[468,5085,5086],{"class":485},"      -",[468,5088,4424],{"class":485},[468,5090,5091],{"class":489},"${CADDY_HTTP_PORT:-80}:80",[468,5093,3534],{"class":485},[468,5095,5096,5098,5100,5103],{"class":470,"line":1691},[468,5097,5086],{"class":485},[468,5099,4424],{"class":485},[468,5101,5102],{"class":489},"${CADDY_HTTPS_PORT:-443}:443",[468,5104,3534],{"class":485},[468,5106,5107,5110],{"class":470,"line":1697},[468,5108,5109],{"class":481},"    volumes",[468,5111,2976],{"class":485},[468,5113,5114,5116],{"class":470,"line":1703},[468,5115,5086],{"class":485},[468,5117,5118],{"class":489}," .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n",[468,5120,5121,5123],{"class":470,"line":1709},[468,5122,5086],{"class":485},[468,5124,5125],{"class":489}," buzz-caddy-data:\u002Fdata\n",[468,5127,5128,5130],{"class":470,"line":1715},[468,5129,5086],{"class":485},[468,5131,5132],{"class":489}," buzz-caddy-config:\u002Fconfig\n",[468,5134,5135,5138,5140],{"class":470,"line":1721},[468,5136,5137],{"class":481},"    restart",[468,5139,486],{"class":485},[468,5141,5142],{"class":489}," unless-stopped\n",[468,5144,5145,5148],{"class":470,"line":1727},[468,5146,5147],{"class":481},"    networks",[468,5149,2976],{"class":485},[468,5151,5152,5154],{"class":470,"line":1733},[468,5153,5086],{"class":485},[468,5155,5156],{"class":489}," buzz-net\n",[468,5158,5159],{"class":470,"line":1739},[468,5160,513],{"emptyLinePlaceholder":512},[468,5162,5163,5166],{"class":470,"line":1745},[468,5164,5165],{"class":481},"volumes",[468,5167,2976],{"class":485},[468,5169,5170,5173],{"class":470,"line":1751},[468,5171,5172],{"class":481},"  buzz-caddy-data",[468,5174,2976],{"class":485},[468,5176,5177,5180],{"class":470,"line":1756},[468,5178,5179],{"class":481},"    labels",[468,5181,2976],{"class":485},[468,5183,5184,5187,5189],{"class":470,"line":1761},[468,5185,5186],{"class":481},"      com.buzz.volume",[468,5188,486],{"class":485},[468,5190,5191],{"class":489}," caddy-data\n",[468,5193,5194,5197],{"class":470,"line":1767},[468,5195,5196],{"class":481},"  buzz-caddy-config",[468,5198,2976],{"class":485},[468,5200,5201,5203],{"class":470,"line":1772},[468,5202,5179],{"class":481},[468,5204,2976],{"class":485},[468,5206,5207,5209,5211],{"class":470,"line":1778},[468,5208,5186],{"class":481},[468,5210,486],{"class":485},[468,5212,5213],{"class":489}," caddy-config\n",[3734,5215,5217],{"id":5216},"start-the-docker-containers","Start the Docker containers",[460,5219,5221],{"className":885,"code":5220,"language":887,"meta":423,"style":423},"docker compose -f compose.yml -f compose.caddy.yml up -d\n\n#Check the Docker status\ndocker compose ps\n",[442,5222,5223,5246,5250,5255],{"__ignoreMap":423},[468,5224,5225,5227,5229,5232,5235,5237,5240,5243],{"class":470,"line":471},[468,5226,2784],{"class":474},[468,5228,2787],{"class":489},[468,5230,5231],{"class":489}," -f",[468,5233,5234],{"class":489}," compose.yml",[468,5236,5231],{"class":489},[468,5238,5239],{"class":489}," compose.caddy.yml",[468,5241,5242],{"class":489}," up",[468,5244,5245],{"class":489}," -d\n",[468,5247,5248],{"class":470,"line":478},[468,5249,513],{"emptyLinePlaceholder":512},[468,5251,5252],{"class":470,"line":493},[468,5253,5254],{"class":2703},"#Check the Docker status\n",[468,5256,5257,5259,5261],{"class":470,"line":504},[468,5258,2784],{"class":474},[468,5260,2787],{"class":489},[468,5262,5263],{"class":489}," ps\n",[567,5265],{"src":5266,"alt":5267,"style":5268},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fdocker-compose-ps-status-terminal.webp","Terminal window displaying running containers for Buzz services via docker compose ps","max-width: 700px; width: 100%; height: auto;",[433,5270,5271,5272,5275],{},"Open your web browser and navigate to ",[442,5273,5274],{},"http:\u002F\u002Fbuzz.pafor.me"," to verify that the relay is running.",[567,5277],{"src":5278,"alt":5279,"style":5280},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-relay-running-browser-verification.webp","Browser verification showing successful response from self-hosted Block's Buzz relay","max-width: 500px; width: 100%; height: auto;",[572,5282,5284],{"id":5283},"step-5-back-up-from-day-one","Step 5: Back up from day one",[460,5286,5288],{"className":885,"code":5287,"language":887,"meta":423,"style":423},"mkdir -p \u002Fbuzz_backups\ncrontab -e\n",[442,5289,5290,5301],{"__ignoreMap":423},[468,5291,5292,5295,5298],{"class":470,"line":471},[468,5293,5294],{"class":474},"mkdir",[468,5296,5297],{"class":489}," -p",[468,5299,5300],{"class":489}," \u002Fbuzz_backups\n",[468,5302,5303,5306],{"class":470,"line":478},[468,5304,5305],{"class":474},"crontab",[468,5307,5308],{"class":489}," -e\n",[433,5310,5311],{},"Add a nightly database dump cron job:",[460,5313,5316],{"className":5314,"code":5315,"language":1017},[1015],"0 3 * * * cd \u002Fhome\u002F\u003Cuser>\u002Fbuzz\u002Fdeploy\u002Fcompose && docker compose exec -T postgres pg_dump -U buzz buzz > \u002Fbuzz_backups\u002Fbuzz-$(date +\\%Y\\%m\\%d).sql\n",[442,5317,5315],{"__ignoreMap":423},[433,5319,5320],{},"Note: Treat BUZZ_RELAY_PRIVATE_KEY as permanent. Events signed by it will fail verification if the key changes; a restored database paired with a fresh key is not treated as the same relay.",[428,5322,5324],{"id":5323},"setting-up-the-buzz-desktop-client-and-nostr-identities","Setting Up the Buzz Desktop Client and Nostr Identities",[433,5326,5327,5328,5332],{},"Download the Buzz desktop app from ",[450,5329,5330],{"href":5330,"rel":5331},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Freleases",[454]," and start it. Fill in the profile details until you reach the \"Join or create a community\" page.",[433,5334,5335],{},[567,5336],{"alt":5337,"src":5338},"Buzz Desktop Client initial setup screen for joining or creating a community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-setup-community.webp",[433,5340,5341],{},"Click \"Join a community\" and copy your public key.",[433,5343,5344],{},[567,5345],{"alt":5346,"src":5347},"Buzz client display showing public key identity before joining community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-join-community-public-key.webp",[433,5349,5350,5351,5354],{},"Run the following command on the ",[437,5352,5353],{},"VPS"," to add yourself as the first member:",[460,5356,5358],{"className":885,"code":5357,"language":887,"meta":423,"style":423},"docker compose exec relay buzz-admin add-member --pubkey npub1yourkeyhere\n",[442,5359,5360],{"__ignoreMap":423},[468,5361,5362,5364,5366,5368,5370,5372,5374,5376],{"class":470,"line":471},[468,5363,2784],{"class":474},[468,5365,2787],{"class":489},[468,5367,2790],{"class":489},[468,5369,2793],{"class":489},[468,5371,2796],{"class":489},[468,5373,2799],{"class":489},[468,5375,2802],{"class":489},[468,5377,5378],{"class":489}," npub1yourkeyhere\n",[433,5380,4808,5381,5384],{},[442,5382,5383],{},"wss:\u002F\u002Fbuzz.pafor.me"," as the community URL and click \"Next\".",[433,5386,5387],{},[567,5388],{"alt":5389,"src":5390},"Entering the self-hosted community relay URL in the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-input-community-url.webp",[433,5392,5393],{},"Enter a name and click the Next button.",[433,5395,5396],{},[567,5397],{"alt":5398,"src":5399},"Profile configuration screen in Buzz app to enter display name","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-profile-name-input.webp",[572,5401,5403],{"id":5402},"channels-and-agents","Channels and Agents",[433,5405,5406],{},"Channels are task groups or project groups. Create a channel per task or project and pull the humans and agents in.",[433,5408,5409],{},"Everything within a channel is shared automatically, eliminating the need to brief each member individually. Every agent can be mentioned using @ and reads the relevant messages. Also, agents can @ each other.",[433,5411,5412],{},"Let's send a DM to a preconfigured agent",[433,5414,5415],{},[567,5416],{"alt":5417,"src":5418},"Sending direct message to an AI agent in the Buzz collaborative desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-dm-agent.webp",[433,5420,5421],{},"Let's create a channel and add some agents to it",[433,5423,5424],{},[567,5425],{"alt":5426,"src":5427},"Creating a new task or project channel inside the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-create-channel-dialog.webp",[433,5429,5430],{},[567,5431],{"alt":5432,"src":5433},"Adding human members and AI agents to the newly created channel","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-agents-to-channel.webp",[433,5435,5436],{},[567,5437],{"alt":5438,"src":5439},"Active channel view displaying consolidated chat history and project tasks","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-view.webp",[567,5441],{"src":5442,"alt":5443,"style":5444},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-active-agents.webp","Detail view of active AI agents integrated into the collaborative project channel","max-width: 367px; width: 100%; height: auto;",[572,5446,5448],{"id":5447},"enable-agent-runtimes","Enable Agent Runtimes",[433,5450,5451,5452,5455,5456,5459],{},"Preset runtimes rely on auto-discovery detecting launcher binaries (e.g. ",[442,5453,5454],{},"hermes-acp",") in standard directories like ",[442,5457,5458],{},"~\u002F.local\u002Fbin",". If a tool was installed in a non-standard location, Buzz cannot resolve it.",[433,5461,5462,5463,5466],{},"For Kimi Code, the agent ID is kimi, and Buzz looks for its binary at ",[442,5464,5465],{},"~\u002F.local\u002Fbin\u002Fkimi",". A symbolic link does the job:",[460,5468,5471],{"className":5469,"code":5470,"language":1017},[1015],"ln -s kimi-cli \u002FUsers\u002F\u003Cuser>\u002F.local\u002Fbin\u002Fkimi\n",[442,5472,5470],{"__ignoreMap":423},[433,5474,5475],{},"Kimi Code now appears under Agent runtimes.",[433,5477,5478],{},[567,5479],{"alt":5480,"src":5481},"Buzz application settings displaying configured AI Agent runtimes including Kimi","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-agent-runtimes-list.webp",[572,5483,5485],{"id":5484},"projects-and-repositories","Projects and Repositories",[433,5487,5488,5489,5492],{},"Enable the '",[437,5490,5491],{},"Projects","' feature in Settings → Experiments first:",[433,5494,5495],{},[567,5496],{"alt":5497,"src":5498},"Enabling experimental Projects feature in the Buzz desktop settings tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-experiments-projects.webp",[433,5500,5501,5502,5504],{},"Currently, a project must be created using the ",[442,5503,2814],{}," (though direct project creation from the UI is planned for a future release).",[3734,5506,5508],{"id":5507},"install-buzz-cli","Install buzz-cli",[433,5510,5511,5512,5514,5515,486],{},"Run the following commands to install ",[442,5513,2814],{}," on the ",[437,5516,5353],{},[460,5518,5520],{"className":885,"code":5519,"language":887,"meta":423,"style":423},"sudo apt install cargo\ncd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-cli\necho 'export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"' >> ~\u002F.bashrc && source ~\u002F.bashrc\n",[442,5521,5522,5533,5540,5553],{"__ignoreMap":423},[468,5523,5524,5526,5528,5530],{"class":470,"line":471},[468,5525,916],{"class":474},[468,5527,919],{"class":489},[468,5529,4588],{"class":489},[468,5531,5532],{"class":489}," cargo\n",[468,5534,5535,5537],{"class":470,"line":478},[468,5536,4699],{"class":2603},[468,5538,5539],{"class":489}," ~\u002Fbuzz\n",[468,5541,5542,5545,5547,5550],{"class":470,"line":493},[468,5543,5544],{"class":474},"cargo",[468,5546,4588],{"class":489},[468,5548,5549],{"class":489}," --path",[468,5551,5552],{"class":489}," crates\u002Fbuzz-cli\n",[468,5554,5555,5557,5560,5563,5566,5569,5572,5574,5577],{"class":470,"line":504},[468,5556,4514],{"class":2603},[468,5558,5559],{"class":485}," '",[468,5561,5562],{"class":489},"export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"",[468,5564,5565],{"class":485},"'",[468,5567,5568],{"class":485}," >>",[468,5570,5571],{"class":489}," ~\u002F.bashrc",[468,5573,925],{"class":485},[468,5575,5576],{"class":2603}," source",[468,5578,5579],{"class":489}," ~\u002F.bashrc\n",[433,5581,5582,5583,5586,5587,5589,5590,5592],{},"Generate a pair of private and public keys using the ",[450,5584,4765],{"href":5585},"\u002Ftools\u002Fnostr-key-generator"," or ",[442,5588,2814],{},". This pair is the identity of the ",[442,5591,2814],{}," in Nostr relay.",[460,5594,5596],{"className":885,"code":5595,"language":887,"meta":423,"style":423},"docker run --rm --entrypoint \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin ghcr.io\u002Fblock\u002Fbuzz:main generate-key\n\n# Use the generated Public Key\ndocker compose exec relay buzz-admin add-member --pubkey generated_Public_key\n",[442,5597,5598,5620,5624,5629],{"__ignoreMap":423},[468,5599,5600,5602,5605,5608,5611,5614,5617],{"class":470,"line":471},[468,5601,2784],{"class":474},[468,5603,5604],{"class":489}," run",[468,5606,5607],{"class":489}," --rm",[468,5609,5610],{"class":489}," --entrypoint",[468,5612,5613],{"class":489}," \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin",[468,5615,5616],{"class":489}," ghcr.io\u002Fblock\u002Fbuzz:main",[468,5618,5619],{"class":489}," generate-key\n",[468,5621,5622],{"class":470,"line":478},[468,5623,513],{"emptyLinePlaceholder":512},[468,5625,5626],{"class":470,"line":493},[468,5627,5628],{"class":2703},"# Use the generated Public Key\n",[468,5630,5631,5633,5635,5637,5639,5641,5643,5645],{"class":470,"line":504},[468,5632,2784],{"class":474},[468,5634,2787],{"class":489},[468,5636,2790],{"class":489},[468,5638,2793],{"class":489},[468,5640,2796],{"class":489},[468,5642,2799],{"class":489},[468,5644,2802],{"class":489},[468,5646,5647],{"class":489}," generated_Public_key\n",[433,5649,5650],{},"Configure the CLI:",[460,5652,5654],{"className":885,"code":5653,"language":887,"meta":423,"style":423},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\necho 'export BUZZ_PRIVATE_KEY=\"nsec1...\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n\necho 'export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n",[442,5655,5656,5661,5692,5696],{"__ignoreMap":423},[468,5657,5658],{"class":470,"line":471},[468,5659,5660],{"class":2703},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\n",[468,5662,5663,5665,5667,5670,5672,5675,5678,5681,5684,5687,5689],{"class":470,"line":478},[468,5664,4514],{"class":2603},[468,5666,5559],{"class":485},[468,5668,5669],{"class":489},"export BUZZ_PRIVATE_KEY=\"nsec1...\"",[468,5671,5565],{"class":485},[468,5673,5674],{"class":485},"  >>",[468,5676,5677],{"class":489}," \u002Fhome\u002F",[468,5679,5680],{"class":485},"\u003C",[468,5682,5683],{"class":489},"use",[468,5685,5686],{"class":961},"r",[468,5688,2857],{"class":485},[468,5690,5691],{"class":489},"\u002F.bashrc\n",[468,5693,5694],{"class":470,"line":493},[468,5695,513],{"emptyLinePlaceholder":512},[468,5697,5698,5700,5702,5705,5707,5709,5711,5713,5715,5717,5719],{"class":470,"line":504},[468,5699,4514],{"class":2603},[468,5701,5559],{"class":485},[468,5703,5704],{"class":489},"export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"",[468,5706,5565],{"class":485},[468,5708,5674],{"class":485},[468,5710,5677],{"class":489},[468,5712,5680],{"class":485},[468,5714,5683],{"class":489},[468,5716,5686],{"class":961},[468,5718,2857],{"class":485},[468,5720,5691],{"class":489},[433,5722,5723,5724,5726],{},"Run the following command to verify ",[442,5725,2814],{}," is configured properly:",[460,5728,5730],{"className":885,"code":5729,"language":887,"meta":423,"style":423},"buzz channels list\n",[442,5731,5732],{"__ignoreMap":423},[468,5733,5734,5736,5738],{"class":470,"line":471},[468,5735,2837],{"class":474},[468,5737,2840],{"class":489},[468,5739,5740],{"class":489}," list\n",[433,5742,5743],{},[567,5744],{"alt":5745,"src":5746},"Terminal command execution verifying buzz-cli configuration by listing active channels","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-cli-channels-list-terminal.webp",[3734,5748,5750],{"id":5749},"create-a-project-with-buzz-cli","Create a Project with buzz-cli",[460,5752,5754],{"className":885,"code":5753,"language":887,"meta":423,"style":423},"# --channel refers to the UUID of the channel\nbuzz repos create --id TestKOA --name 'Display Name' --channel \"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b\"\n",[442,5755,5756,5761],{"__ignoreMap":423},[468,5757,5758],{"class":470,"line":471},[468,5759,5760],{"class":2703},"# --channel refers to the UUID of the channel\n",[468,5762,5763,5765,5768,5771,5774,5777,5780,5782,5785,5787,5789,5791,5794],{"class":470,"line":478},[468,5764,2837],{"class":474},[468,5766,5767],{"class":489}," repos",[468,5769,5770],{"class":489}," create",[468,5772,5773],{"class":489}," --id",[468,5775,5776],{"class":489}," TestKOA",[468,5778,5779],{"class":489}," --name",[468,5781,5559],{"class":485},[468,5783,5784],{"class":489},"Display Name",[468,5786,5565],{"class":485},[468,5788,2845],{"class":489},[468,5790,4424],{"class":485},[468,5792,5793],{"class":489},"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b",[468,5795,3534],{"class":485},[433,5797,5798,5799,5801],{},"A project can only be removed by its owner. Because the \"Display Name\" project was created by the ",[442,5800,2814],{},", which lacks a removal command, it cannot be deleted this way.",[433,5803,5804],{},"Check back the Buzz desktop app to verify the project is created.",[433,5806,5807],{},[567,5808],{"alt":5809,"src":5810},"Buzz desktop application projects view confirming successful project creation","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-project-view.webp",[433,5812,5813],{},"Once a project is available in Projects, more projects can be added using the \"+\" button at the top right corner.",[433,5815,5816],{},[567,5817],{"alt":5818,"src":5819},"Adding new developer projects using the plus icon in Buzz desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-project-button.webp",[3734,5821,5823],{"id":5822},"check-in-existing-git-repositories","Check In Existing Git Repositories",[433,5825,4075,5826,5829,5830,5833,5834,486],{},[442,5827,5828],{},"git-credential-nostr"," on the machine where git repositories are. It requires ",[437,5831,5832],{},"git 2.46+"," and the Rust toolchain. Refer to this ",[450,5835,5838],{"href":5836,"rel":5837},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Ftree\u002Fmain\u002Fcrates\u002Fgit-credential-nostr",[454],"Readme",[460,5840,5842],{"className":885,"code":5841,"language":887,"meta":423,"style":423},"cargo install --path crates\u002Fgit-credential-nostr\n",[442,5843,5844],{"__ignoreMap":423},[468,5845,5846,5848,5850,5852],{"class":470,"line":471},[468,5847,5544],{"class":474},[468,5849,4588],{"class":489},[468,5851,5549],{"class":489},[468,5853,5854],{"class":489}," crates\u002Fgit-credential-nostr\n",[433,5856,5857,5858,5860],{},"Set up ",[442,5859,5828],{}," for Buzz relay authorisation:",[460,5862,5864],{"className":885,"code":5863,"language":887,"meta":423,"style":423},"# 1. Register the helper and enable per-path credentials.\ngit config --global credential.helper nostr\ngit config --global credential.useHttpPath true\n\n# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\nmkdir -p ~\u002F.nostr\necho \"nsec1...\" > ~\u002F.nostr\u002Fkey && chmod 600 ~\u002F.nostr\u002Fkey\ngit config --global nostr.keyfile ~\u002F.nostr\u002Fkey\n",[442,5865,5866,5871,5887,5900,5904,5909,5918,5945],{"__ignoreMap":423},[468,5867,5868],{"class":470,"line":471},[468,5869,5870],{"class":2703},"# 1. Register the helper and enable per-path credentials.\n",[468,5872,5873,5875,5878,5881,5884],{"class":470,"line":478},[468,5874,4684],{"class":474},[468,5876,5877],{"class":489}," config",[468,5879,5880],{"class":489}," --global",[468,5882,5883],{"class":489}," credential.helper",[468,5885,5886],{"class":489}," nostr\n",[468,5888,5889,5891,5893,5895,5898],{"class":470,"line":493},[468,5890,4684],{"class":474},[468,5892,5877],{"class":489},[468,5894,5880],{"class":489},[468,5896,5897],{"class":489}," credential.useHttpPath",[468,5899,2987],{"class":485},[468,5901,5902],{"class":470,"line":504},[468,5903,513],{"emptyLinePlaceholder":512},[468,5905,5906],{"class":470,"line":509},[468,5907,5908],{"class":2703},"# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\n",[468,5910,5911,5913,5915],{"class":470,"line":516},[468,5912,5294],{"class":474},[468,5914,5297],{"class":489},[468,5916,5917],{"class":489}," ~\u002F.nostr\n",[468,5919,5920,5922,5924,5927,5929,5931,5934,5936,5939,5942],{"class":470,"line":522},[468,5921,4514],{"class":2603},[468,5923,4424],{"class":485},[468,5925,5926],{"class":489},"nsec1...",[468,5928,4430],{"class":485},[468,5930,4549],{"class":485},[468,5932,5933],{"class":489}," ~\u002F.nostr\u002Fkey",[468,5935,925],{"class":485},[468,5937,5938],{"class":474}," chmod",[468,5940,5941],{"class":5003}," 600",[468,5943,5944],{"class":489}," ~\u002F.nostr\u002Fkey\n",[468,5946,5947,5949,5951,5953,5956],{"class":470,"line":527},[468,5948,4684],{"class":474},[468,5950,5877],{"class":489},[468,5952,5880],{"class":489},[468,5954,5955],{"class":489}," nostr.keyfile",[468,5957,5944],{"class":489},[433,5959,5960],{},"Create a repo on the Buzz relay:",[460,5962,5965],{"className":5963,"code":5964,"language":1017},[1015],"buzz repos create --id koa-email-routing --name \"KOA Email Routing\" --clone \"https:\u002F\u002Fbuzz.pafor.me\u002Fgit\u002F\u003Cpub_key>\u002Fkoa-email-routing\" --nostr-relay \"wss:\u002F\u002Fbuzz.pafor.me\"\n",[442,5966,5964],{"__ignoreMap":423},[433,5968,5969,5970,5973,5974,5977],{},"On your first ",[442,5971,5972],{},"git push",", you will encounter a ",[442,5975,5976],{},"remote: missing Authorization header"," error. To resolve this, you need to bind the repository ID to a Buzz channel, as channel membership dictates Git write permissions (ACLs):",[460,5979,5981],{"className":885,"code":5980,"language":887,"meta":423,"style":423},"buzz repos bind --id koa-email-routing --channel \u003CCHANNEL_UUID>\n\n# push the code again\ngit push\n",[442,5982,5983,6008,6012,6017],{"__ignoreMap":423},[468,5984,5985,5987,5989,5992,5994,5997,5999,6001,6003,6005],{"class":470,"line":471},[468,5986,2837],{"class":474},[468,5988,5767],{"class":489},[468,5990,5991],{"class":489}," bind",[468,5993,5773],{"class":489},[468,5995,5996],{"class":489}," koa-email-routing",[468,5998,2845],{"class":489},[468,6000,2848],{"class":485},[468,6002,2851],{"class":489},[468,6004,2854],{"class":961},[468,6006,6007],{"class":485},">\n",[468,6009,6010],{"class":470,"line":478},[468,6011,513],{"emptyLinePlaceholder":512},[468,6013,6014],{"class":470,"line":493},[468,6015,6016],{"class":2703},"# push the code again\n",[468,6018,6019,6021],{"class":470,"line":504},[468,6020,4684],{"class":474},[468,6022,6023],{"class":489}," push\n",[433,6025,6026,6027,6029],{},"Checking the project in the Buzz desktop app shows the following, because the app needs ",[437,6028,5832],{}," — launching the app directly may pick up an older version of Git:",[433,6031,6032],{},[567,6033],{"alt":6034,"src":6035},"Buzz client rendering Git loading error due to outdated local Git version below 2.46","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-git-version-error.webp",[433,6037,6038,6039,6042,6043,1557],{},"Export the PATH via ",[442,6040,6041],{},"launchctl setenv PATH \"\u002Fopt\u002Fhomebrew\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin:\u002Fusr\u002Fsbin:\u002Fsbin\""," in the shell profile and launch the Buzz app from the shell. Refer to this ",[450,6044,6047],{"href":6045,"rel":6046},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Fissues\u002F5348",[454],"issue",[460,6049,6051],{"className":885,"code":6050,"language":887,"meta":423,"style":423},"open -a Buzz\n",[442,6052,6053],{"__ignoreMap":423},[468,6054,6055,6058,6061],{"class":470,"line":471},[468,6056,6057],{"class":474},"open",[468,6059,6060],{"class":489}," -a",[468,6062,6063],{"class":489}," Buzz\n",[433,6065,6066],{},"Check back the Projects in the Buzz app, the repository details are now loaded.",[433,6068,6069],{},[567,6070],{"alt":6071,"src":6072},"Buzz desktop interface with successfully loaded Git repository details and commit logs","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-repository-details-loaded.webp",[428,6074,6076],{"id":6075},"syncing-ai-agents-with-the-buzz-mobile-app-via-qr-code","Syncing AI Agents with the Buzz Mobile App via QR Code",[433,6078,6079,6080,6083,6084,1557],{},"The Buzz mobile app pairing only accepts the HTTPS protocol and the ",[442,6081,6082],{},"buzz-pair-relay"," is not started by default on ",[437,6085,5353],{},[460,6087,6089],{"className":885,"code":6088,"language":887,"meta":423,"style":423},"cd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-pair-relay\n",[442,6090,6091,6097],{"__ignoreMap":423},[468,6092,6093,6095],{"class":470,"line":471},[468,6094,4699],{"class":2603},[468,6096,5539],{"class":489},[468,6098,6099,6101,6103,6105],{"class":470,"line":478},[468,6100,5544],{"class":474},[468,6102,4588],{"class":489},[468,6104,5549],{"class":489},[468,6106,6107],{"class":489}," crates\u002Fbuzz-pair-relay\n",[433,6109,6110,6111,6114,6115,6117],{},"Add the following to ",[442,6112,6113],{},"compose.yml"," to start the ",[442,6116,6082],{}," service:",[460,6119,6121],{"className":2951,"code":6120,"language":2953,"meta":423,"style":423},"  pair:\n    image: ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n    entrypoint: [\"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay\"]\n    environment:\n      BUZZ_PAIR_RELAY_BIND_ADDR: 0.0.0.0:5000\n    ports:\n      - \"${BUZZ_PAIR_RELAY_PORT:-5000}:5000\"\n    restart: unless-stopped\n    networks:\n      [buzz-net]\n",[442,6122,6123,6130,6139,6159,6165,6175,6181,6192,6200,6206],{"__ignoreMap":423},[468,6124,6125,6128],{"class":470,"line":471},[468,6126,6127],{"class":481},"  pair",[468,6129,2976],{"class":485},[468,6131,6132,6134,6136],{"class":470,"line":478},[468,6133,5019],{"class":481},[468,6135,486],{"class":485},[468,6137,6138],{"class":489}," ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n",[468,6140,6141,6144,6146,6149,6151,6154,6156],{"class":470,"line":493},[468,6142,6143],{"class":481},"    entrypoint",[468,6145,486],{"class":485},[468,6147,6148],{"class":485}," [",[468,6150,4430],{"class":485},[468,6152,6153],{"class":489},"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay",[468,6155,4430],{"class":485},[468,6157,6158],{"class":485},"]\n",[468,6160,6161,6163],{"class":470,"line":504},[468,6162,5053],{"class":481},[468,6164,2976],{"class":485},[468,6166,6167,6170,6172],{"class":470,"line":509},[468,6168,6169],{"class":481},"      BUZZ_PAIR_RELAY_BIND_ADDR",[468,6171,486],{"class":485},[468,6173,6174],{"class":489}," 0.0.0.0:5000\n",[468,6176,6177,6179],{"class":470,"line":516},[468,6178,4967],{"class":481},[468,6180,2976],{"class":485},[468,6182,6183,6185,6187,6190],{"class":470,"line":522},[468,6184,5086],{"class":485},[468,6186,4424],{"class":485},[468,6188,6189],{"class":489},"${BUZZ_PAIR_RELAY_PORT:-5000}:5000",[468,6191,3534],{"class":485},[468,6193,6194,6196,6198],{"class":470,"line":527},[468,6195,5137],{"class":481},[468,6197,486],{"class":485},[468,6199,5142],{"class":489},[468,6201,6202,6204],{"class":470,"line":533},[468,6203,5147],{"class":481},[468,6205,2976],{"class":485},[468,6207,6208,6211,6214],{"class":470,"line":538},[468,6209,6210],{"class":485},"      [",[468,6212,6213],{"class":489},"buzz-net",[468,6215,6158],{"class":485},[433,6217,4808,6218,1915,6221,4841,6224,3775],{},[442,6219,6220],{},"BUZZ_PAIRING_RELAY_URL",[442,6222,6223],{},"BUZZ_PAIR_RELAY_PORT",[442,6225,4726],{},[460,6227,6230],{"className":6228,"code":6229,"language":1017},[1015],"BUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_PAIR_RELAY_PORT=5000\n",[442,6231,6229],{"__ignoreMap":423},[433,6233,6234,6235,6238],{},"Head to the '",[437,6236,6237],{},"Mobile","' in the Buzz desktop Settings:",[433,6240,6241],{},[567,6242],{"alt":6243,"src":6244},"Settings dialog in Buzz app showing the Mobile devices configuration tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-mobile-tab.webp",[433,6246,6247],{},"Click \"Start pairing\" — a QR code is generated; scan this QR code with the Buzz app on the mobile device. It will be paired after you click \"Code Match\".",[433,6249,6250],{},[567,6251],{"alt":6252,"src":6253},"Generating secure pairing QR code in desktop client for Buzz mobile synchronization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-pairing-qr-code.webp",[433,6255,6256],{},"The agents on the Buzz mobile app are available only if they are running on the Buzz desktop app. The desktop machine has to be running for the agents to work.",[433,6258,6259],{},[567,6260],{"alt":6261,"src":6262},"Buzz mobile application interface showcasing synced active AI companion agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-mobile-app-active-agents.webp",[428,6264,6266],{"id":6265},"final-thought","Final Thought",[433,6268,6269],{},"While Buzz is still too early for large scale production environments with several bugs and UI limitations, it is an exciting experience for small teams and solo developers. It offers a preview of what a collaborative, AI-first workspace truly feels like.",[428,6271,6273],{"id":6272},"reference","Reference",[724,6275,6276,6283,6290,6297],{},[580,6277,6278],{},[450,6279,6282],{"href":6280,"rel":6281},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz",[454],"Buzz releases",[580,6284,6285],{},[450,6286,6289],{"href":6287,"rel":6288},"https:\u002F\u002Fblock.xyz\u002Finside\u002Fintroducing-buzz-where-humans-and-agents-work-together",[454],"Introducing Buzz",[580,6291,6292],{},[450,6293,6296],{"href":6294,"rel":6295},"https:\u002F\u002Fwww.hostinger.com\u002Ftutorials\u002Fwhat-is-buzz",[454],"What is buzz",[580,6298,6299],{},[450,6300,6303],{"href":6301,"rel":6302},"https:\u002F\u002Fmiget.com\u002Fblog\u002Fhow-to-self-host-buzz",[454],"How to self-host Buzz (Miget)",[822,6305,6306],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":423,"searchDepth":478,"depth":493,"links":6308},[6309,6310,6311,6325,6334,6335,6336],{"id":4213,"depth":478,"text":4214},{"id":4258,"depth":478,"text":4259},{"id":4306,"depth":478,"text":4307,"children":6312},[6313,6314,6318,6319,6320,6324],{"id":4310,"depth":493,"text":4311},{"id":4338,"depth":493,"text":4339,"children":6315},[6316,6317],{"id":4342,"depth":504,"text":4343},{"id":4443,"depth":504,"text":4444},{"id":4461,"depth":493,"text":4462},{"id":4673,"depth":493,"text":4674},{"id":4827,"depth":493,"text":4828,"children":6321},[6322,6323],{"id":4831,"depth":504,"text":4832},{"id":5216,"depth":504,"text":5217},{"id":5283,"depth":493,"text":5284},{"id":5323,"depth":478,"text":5324,"children":6326},[6327,6328,6329],{"id":5402,"depth":493,"text":5403},{"id":5447,"depth":493,"text":5448},{"id":5484,"depth":493,"text":5485,"children":6330},[6331,6332,6333],{"id":5507,"depth":504,"text":5508},{"id":5749,"depth":504,"text":5750},{"id":5822,"depth":504,"text":5823},{"id":6075,"depth":478,"text":6076},{"id":6265,"depth":478,"text":6266},{"id":6272,"depth":478,"text":6273},[3261,836,2837],"2026-09-08",{"schemaOrg":6340,"robots":846,"sitemap":6359},[6341,6342],{"@type":3270,"headline":382,"description":2124,"image":2125},{"@type":845,"name":382,"description":2124,"image":2125,"step":6343},[6344,6347,6350,6353,6356],{"@type":1511,"name":6345,"text":6346},"Phase 1: Cloudflare Setup","Create a Cloudflare API Token and configure DNS settings.",{"@type":1511,"name":6348,"text":6349},"Phase 2: Install Docker","Set up and install Docker Engine on Ubuntu VPS.",{"@type":1511,"name":6351,"text":6352},"Phase 3: Clone and Configure","Clone the repository and configure compose variables.",{"@type":1511,"name":6354,"text":6355},"Phase 4: Caddy Integration","Build custom Caddy with Cloudflare DNS challenge module.",{"@type":1511,"name":6357,"text":6358},"Phase 5: Automated Backup","Configure a cron job to automatically back up PostgreSQL.",{"lastmod":6360},"2026-09-03",{"title":6362,"description":2124,"ogTitle":382,"ogDescription":2124,"twitterTitle":382,"twitterDescription":2124},"How to Self-Host Block's Buzz Relay on Ubuntu VPS",[3295,6364,2115,6365,6366],"Docker","Caddy","Cloudflare","ir8b59r6ypIp92KOOIJHFgPU_UhHH0zic0M1up4soME",1792489980141]