repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

commit
0fc145b
parent
c5afd39
author
Eric Bower
date
2026-01-02 12:22:40 -0500 EST
chore: move marketing materials to pipe
1 files changed,  +2, -236
M pkg/apps/pipe/html/marketing.page.tmpl
+2, -236
  1@@ -1,6 +1,6 @@
  2 {{template "base" .}}
  3 
  4-{{define "title"}}pipe: authenticated pubsub over ssh{{end}}
  5+{{define "title"}}pipe: pubsub without the infrastructure. stream data between machines using ssh.{{end}}
  6 
  7 {{define "meta"}}
  8 <meta name="description" content="authenticated *nix pipes over ssh" />
  9@@ -21,246 +21,12 @@
 10     <canvas id="canvas" width="50" height="50"></canvas>
 11     <hr width="100%" class="m-0" />
 12   </div>
 13-  <h1 class="text-2xl font-bold text-center">Authenticated *nix pipes over ssh</h1>
 14+  <h1 class="text-2xl font-bold text-center">PubSub without the infrastructure. Stream data between machines using ssh.</h1>
 15   <div class="text-center flex gap">
 16     <a href="https://pico.sh/getting-started" class="btn-link mt inline-block">GET STARTED</a>
 17     <a href="https://pico.sh/pipe" class="btn-link mt inline-block">DOCS</a>
 18   </div>
 19 </header>
 20 
 21-<article class="flex flex-col gap-2">
 22-  <div>
 23-    <p>
 24-      The simplest authenticated pubsub system.  Send messages through
 25-      user-defined topics (aka channels).  By default, topics are private to the authenticated
 26-      ssh user.  The default pubsub model is multicast with bidirectional
 27-      blocking, meaning a publisher (<code>pub</code>) will send its message to all
 28-      subscribers (<code>sub</code>) for a topic.  There can be many publishers
 29-      and many subscribers on a topic. Further, both <code>pub</code> and
 30-      <code>sub</code> will wait for at least one event to be sent or received on the topic.
 31-    </p>
 32-
 33-    <h2 class="text-lg">Features</h2>
 34-
 35-    <ol>
 36-      <li>Familiar *nix pipes API</li>
 37-      <li>Zero-install</li>
 38-      <li>Authenticated pubsub using ssh</li>
 39-      <li>Private pubsub by default</li>
 40-      <li>Public pubsub by topic (opt-in)</li>
 41-      <li>Multicast (many pubs to many subs)</li>
 42-      <li>Bidirectional (e.g. chat)</li>
 43-      <li>Paradigms for connecting to a topic:
 44-        <ol>
 45-          <li>Read (<code>sub</code>)</li>
 46-          <li>Write (<code>pub</code>)</li>
 47-          <li>Read & Write (<code>pipe</code>)</li>
 48-        </ol>
 49-      </li>
 50-    </ol>
 51-  </div>
 52-
 53-  <div>
 54-    <h2 class="text-xl">A basic API</h2>
 55-    <p>Pipe some data into our ssh app and we will send it to anyone listening.</p>
 56-    <pre>ssh {{.Site.Domain}} sub mykey</pre>
 57-    <pre>echo "hello world!" | ssh {{.Site.Domain}} pub mykey</pre>
 58-
 59-    <details>
 60-      <summary>Demo</summary>
 61-      <script
 62-        src="https://asciinema.org/a/679717.js"
 63-        id="asciicast-679717"
 64-        async="true"
 65-        data-theme="dracula"
 66-        data-loop="true"
 67-        data-speed="1.5"
 68-        data-idle-time-limit="2"
 69-      ></script>
 70-    </details>
 71-  </div>
 72-
 73-  <div>
 74-    <h2 class="text-xl">Simple desktop notifications</h2>
 75-    <p>Want to quickly receive a notification when a job is done?  It can be as simple as:</p>
 76-    <pre>ssh {{.Site.Domain}} sub notify; notify-send "job done!"</pre>
 77-    <pre>./longjob.sh; ssh {{.Site.Domain}} pub notify -e</pre>
 78-  </div>
 79-
 80-  <div>
 81-    <h2 class="text-xl">File sharing</h2>
 82-    <p>Sometimes you need data exfiltration and all you have is SSH:</p>
 83-    <pre>cat doc.md | ssh {{.Site.Domain}} pub thedoc</pre>
 84-    <pre>ssh {{.Site.Domain}} sub thedoc > ./important.md</pre>
 85-
 86-    <details>
 87-      <summary>Demo</summary>
 88-      <script
 89-        src="https://asciinema.org/a/679715.js"
 90-        id="asciicast-679715"
 91-        async="true"
 92-        data-theme="dracula"
 93-        data-loop="true"
 94-        data-speed="1.5"
 95-        data-idle-time-limit="2"
 96-      ></script>
 97-    </details>
 98-  </div>
 99-
100-  <div>
101-    <h2 class="text-xl">Pipe command output</h2>
102-    <p>
103-      Send command output through our <code>pipe</code> command.  The
104-      <code>pipe</code> command is just like <code>pub</code> except it
105-      is non-blocking and also acts like a <code>sub</code>.  So a client
106-      that can read and write to the topic.
107-    </p>
108-    <pre>ssh {{.Site.Domain}} sub htop</pre>
109-    <pre>htop | ssh {{.Site.Domain}} pipe htop</pre>
110-
111-    <details>
112-      <summary>Demo</summary>
113-      <script
114-        src="https://asciinema.org/a/679712.js"
115-        id="asciicast-679712"
116-        async="true"
117-        data-theme="dracula"
118-        data-loop="true"
119-        data-speed="1.5"
120-        data-idle-time-limit="2"
121-      ></script>
122-    </details>
123-  </div>
124-
125-  <div>
126-    <h2 class="text-xl">Chat</h2>
127-    <p>Use our <code>pipe</code> command to have a chat with someone.</p>
128-    <pre>ssh {{.Site.Domain}} pipe mychan -p</pre>
129-    <p>
130-      Now anyone with a <code>pico</code> account can subscribe to this
131-      topic using the same command and start typing!
132-    </p>
133-
134-    <details>
135-      <summary>Demo</summary>
136-      <script
137-        src="https://asciinema.org/a/679709.js"
138-        id="asciicast-679709"
139-        async="true"
140-        data-theme="dracula"
141-        data-loop="true"
142-        data-speed="1.5"
143-        data-idle-time-limit="2"
144-      ></script>
145-    </details>
146-  </div>
147-
148-  <div>
149-    <h2 class="text-xl">Pipe reverse shell</h2>
150-    <p>If you squint hard enough you can give users interactive access to your shell.</p>
151-    <pre>mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | ssh {{.Site.Domain}} pipe myshell > /tmp/f</pre>
152-    <pre>ssh {{.Site.Domain}} pipe myshell</pre>
153-
154-    <details>
155-      <summary>Demo</summary>
156-      <script
157-        src="https://asciinema.org/a/679704.js"
158-        id="asciicast-679704"
159-        async="true"
160-        data-theme="dracula"
161-        data-loop="true"
162-        data-speed="1.5"
163-        data-idle-time-limit="2"
164-      ></script>
165-    </details>
166-  </div>
167-
168-  <div>
169-    <h2 class="text-xl">Simple CI/CD</h2>
170-    <p>
171-      I'm always looking for easy ways to simplify deploying apps
172-      automatically.  Having an authenticated, zero-install event system
173-      seems handy for this purpose.
174-    </p>
175-    <pre>while true; do ssh {{.Site.Domain}} sub deploy-app; docker compose pull && docker compose up -d; done</pre>
176-    <pre>docker buildx build --push -t myapp .; ssh {{.Site.Domain}} pub deploy-app -e</pre>
177-  </div>
178-
179-  <div>
180-    <h2 class="text-xl">Pubsub interactions</h2>
181-
182-    <h3 class="text-lg">Multiple subs</h3>
183-    <p>
184-      Have many subscribers, they will all receive the message.
185-    </p>
186-    <pre>ssh {{.Site.Domain}} sub foobar</pre>
187-    <pre>ssh {{.Site.Domain}} sub foobar</pre>
188-    <pre>while true; do echo "foobar1"; sleep 1; done | ssh {{.Site.Domain}} pub foobar</pre>
189-
190-    <details>
191-      <summary>Demo</summary>
192-      <script
193-        src="https://asciinema.org/a/679699.js"
194-        id="asciicast-679699"
195-        async="true"
196-        data-theme="dracula"
197-        data-loop="true"
198-        data-speed="1.5"
199-        data-idle-time-limit="2"
200-      ></script>
201-    </details>
202-
203-    <h3 class="text-lg">Multiple pubs</h3>
204-    <p>Have many publishers send messages to subscribers.</p>
205-    <pre>while true; do echo "foobar1"; sleep 1; done | ssh {{.Site.Domain}} pub foobar</pre>
206-    <pre>while true; do echo "foobar2"; sleep 1; done | ssh {{.Site.Domain}} pub foobar</pre>
207-    <pre>ssh {{.Site.Domain}} sub foobar</pre>
208-
209-    <details>
210-      <summary>Demo</summary>
211-      <script
212-        src="https://asciinema.org/a/679698.js"
213-        id="asciicast-679698"
214-        async="true"
215-        data-theme="dracula"
216-        data-loop="true"
217-        data-speed="1.5"
218-        data-idle-time-limit="2"
219-      ></script>
220-    </details>
221-
222-    <h3 class="text-lg">Multiple pubs and subs</h3>
223-    <p>Have many publishers send messages to many subscribers.</p>
224-    <pre>ssh {{.Site.Domain}} sub foobar</pre>
225-    <pre>ssh {{.Site.Domain}} sub foobar</pre>
226-    <pre>while true; do echo "foobar1"; sleep 1; done | ssh {{.Site.Domain}} pub foobar</pre>
227-    <pre>while true; do echo "foobar2"; sleep 1; done | ssh {{.Site.Domain}} pub foobar</pre>
228-
229-    <details>
230-      <summary>Demo</summary>
231-      <script
232-        src="https://asciinema.org/a/679694.js"
233-        id="asciicast-679694"
234-        async="true"
235-        data-theme="dracula"
236-        data-loop="true"
237-        data-speed="1.5"
238-        data-idle-time-limit="2"
239-      ></script>
240-    </details>
241-  </div>
242-
243-  <div>
244-    <h2 class="text-xl">Send a public message</h2>
245-    <pre>echo "hello world!" | ssh {{.Site.Domain}} pub mychan -p</pre>
246-    <p>Now anyone with a <code>pico</code> account can subscribe to this topic:</p>
247-    <pre>ssh {{.Site.Domain}} sub mychan -p</pre>
248-  </div>
249-
250-  <div class="text-center mb-2">
251-    <a href="https://pico.sh/getting-started" class="btn-link inline-block">GET STARTED</a>
252-  </div>
253-</article>
254-
255 {{template "marketing-footer" .}}
256 {{end}}