Commit 79ac008
Eric Bower
·
2026-05-19 21:00:56 -0400 EDT
parent 766f8b9
docs: site copy
1 files changed,
+39,
-83
+39,
-83
| ... | ... | @@ -2,7 +2,9 @@ | |
| 2 | 2 | <html lang="en"> | |
| 3 | 3 | <head> | |
| 4 | 4 | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> | |
| 6 | + | <meta name="apple-mobile-web-app-capable" content="yes"> | |
| 7 | + | <meta name="apple-mobile-web-app-status-bar-style" content="black"> | |
| 6 | 8 | <title>pici – Your Build Isn't a Log. It's a Terminal.</title> | |
| 7 | 9 | <style> | |
| 8 | 10 | /* ============================================================ |
| ... | ... | @@ -76,9 +78,9 @@ section { | |
| 76 | 78 | ============================================================ */ | |
| 77 | 79 | ||
| 78 | 80 | nav { | |
| 81 | + | z-index: 1; | |
| 79 | 82 | position: sticky; | |
| 80 | 83 | top: 0; | |
| 81 | - | z-index: 100; | |
| 82 | 84 | background: var(--bg-deep); | |
| 83 | 85 | border-bottom: 1px solid var(--surface); | |
| 84 | 86 | padding: 0.75rem 0; |
| ... | ... | @@ -113,7 +115,7 @@ nav ul { | |
| 113 | 115 | ||
| 114 | 116 | nav ul a { | |
| 115 | 117 | color: var(--text-dim); | |
| 116 | - | font-size: 0.85rem; | |
| 118 | + | font-size: 0.7rem; | |
| 117 | 119 | text-transform: uppercase; | |
| 118 | 120 | letter-spacing: 0.05em; | |
| 119 | 121 | } |
| ... | ... | @@ -615,7 +617,7 @@ details .faq-answer { | |
| 615 | 617 | You re-run the job and wait 10 minutes to find out you were wrong. Repeat. | |
| 616 | 618 | </p> | |
| 617 | 619 | <p> | |
| 618 | - | Debugging CI should not be an archaeological dig through log files in a browser. | |
| 620 | + | Debugging CI shouldn't require you to guess what happened. | |
| 619 | 621 | </p> | |
| 620 | 622 | </div> | |
| 621 | 623 | <div class="terminal"> |
| ... | ... | @@ -648,23 +650,17 @@ details .faq-answer { | |
| 648 | 650 | <section id="how"> | |
| 649 | 651 | <div class="container"> | |
| 650 | 652 | <p class="section-label">The Solution</p> | |
| 651 | - | <h2>Jump into your failing build.</h2> | |
| 653 | + | <h2>Attach to your failing build.</h2> | |
| 652 | 654 | <div class="two-col"> | |
| 653 | 655 | <div> | |
| 654 | 656 | <p> | |
| 655 | 657 | Every build step in <code>pici</code> runs as a <strong>real terminal session</strong>: a PTY you can attach to. | |
| 656 | - | No "enable debugging" flag. No "re-run with SSH" button. No waiting for a tunnel. | |
| 658 | + | No "enable debugging" or "re-run with SSH" buttons. | |
| 657 | 659 | </p> | |
| 658 | 660 | <p> | |
| 659 | 661 | A test fails? Attach to the session, press <code>↑</code> + <code>Enter</code> to rerun the command, | |
| 660 | - | inspect the environment, fix the issue. You're already there. | |
| 662 | + | inspect the environment, and fix the issue before trying again. | |
| 661 | 663 | </p> | |
| 662 | - | <ul class="check-list"> | |
| 663 | - | <li><code>zmx attach ci.myrepo.test</code> to jump in</li> | |
| 664 | - | <li>Press <code>↑</code> to rerun the failing command</li> | |
| 665 | - | <li>Inspect files, env vars, network state</li> | |
| 666 | - | <li>No debug mode. It's just a terminal.</li> | |
| 667 | - | </ul> | |
| 668 | 664 | </div> | |
| 669 | 665 | <div> | |
| 670 | 666 | <div class="terminal"> |
| ... | ... | @@ -706,7 +702,7 @@ details .faq-answer { | |
| 706 | 702 | <section id="engine"> | |
| 707 | 703 | <div class="container"> | |
| 708 | 704 | <p class="section-label">Job Engine</p> | |
| 709 | - | <h2>Parallel tasks. Zero config. Same commands everywhere.</h2> | |
| 705 | + | <h2>Parallel tasks, zero config, and zero install.</h2> | |
| 710 | 706 | <div class="two-col"> | |
| 711 | 707 | <div class="terminal"> | |
| 712 | 708 | <div class="terminal-bar"> |
| ... | ... | @@ -719,17 +715,18 @@ details .faq-answer { | |
| 719 | 715 | <div><span class="comment">#!/usr/bin/env bash</span></div> | |
| 720 | 716 | <div><span class="cmd">set -euo pipefail</span></div> | |
| 721 | 717 | <div> </div> | |
| 722 | - | <div><span class="comment"># These run in parallel, no config needed</span></div> | |
| 718 | + | <div><span class="comment"># This step runs until it's finished</span></div> | |
| 723 | 719 | <div><span class="cmd">zmx run lint docker run golangci-lint run</span></div> | |
| 724 | - | <div><span class="info"> → started session: ci.myrepo.lint</span></div> | |
| 720 | + | <div><span class="info"> → No issues found!</span></div> | |
| 725 | 721 | <div> </div> | |
| 726 | - | <div><span class="cmd">zmx run test go test ./...</span></div> | |
| 722 | + | <div><span class="comment"># These run in parallel</span></div> | |
| 723 | + | <div><span class="cmd">zmx run test -d go test ./...</span></div> | |
| 727 | 724 | <div><span class="info"> → started session: ci.myrepo.test</span></div> | |
| 728 | 725 | <div> </div> | |
| 729 | - | <div><span class="cmd">zmx run build go build -o bin/pici .</span></div> | |
| 726 | + | <div><span class="cmd">zmx run build -d go build -o bin/pici .</span></div> | |
| 730 | 727 | <div><span class="info"> → started session: ci.myrepo.build</span></div> | |
| 731 | 728 | <div> </div> | |
| 732 | - | <div><span class="comment"># Wait for all to finish</span></div> | |
| 729 | + | <div><span class="comment"># Wait for all tasks to finish</span></div> | |
| 733 | 730 | <div><span class="cmd">zmx wait "*"</span></div> | |
| 734 | 731 | <div> </div> | |
| 735 | 732 | <div><span class="comment"># Runs identically locally and in CI</span></div> |
| ... | ... | @@ -738,18 +735,19 @@ details .faq-answer { | |
| 738 | 735 | <div> | |
| 739 | 736 | <p> | |
| 740 | 737 | Your pipeline is <code>pico.sh</code>: a bash script that runs <strong>identically on your machine | |
| 741 | - | and on the CI runner</strong>. No YAML, no DSL, no "it works on my machine" gap. | |
| 738 | + | and on the CI runner</strong>; no yaml required. | |
| 742 | 739 | </p> | |
| 743 | 740 | <p> | |
| 744 | 741 | <a href="https://zmx.sh"><strong>zmx</strong></a> is the job engine. Each <code>zmx run</code> spawns | |
| 745 | 742 | a parallel terminal session. <code>zmx wait "*"</code> blocks until they all finish. | |
| 746 | - | Run tasks sequentially by just calling them one after another, or in parallel; it's bash, | |
| 747 | - | you control the flow. | |
| 743 | + | Run tasks sequentially by just calling them one after another, or in parallel by using the | |
| 744 | + | detach (<code>-d</code>) flag. | |
| 748 | 745 | </p> | |
| 749 | 746 | <ul class="check-list"> | |
| 750 | 747 | <li>Same <code>zmx run</code> commands locally and in CI</li> | |
| 751 | - | <li>Parallel by default, sequential when you want it</li> | |
| 748 | + | <li>Sequential by default, parallel when you want it</li> | |
| 752 | 749 | <li>Every step is an attachable terminal session</li> | |
| 750 | + | <li>Bring your own isolation: use docker in your step commands</li> | |
| 753 | 751 | <li>No YAML matrices, no <code>run: parallel</code> keywords</li> | |
| 754 | 752 | </ul> | |
| 755 | 753 | </div> |
| ... | ... | @@ -774,15 +772,6 @@ details .faq-answer { | |
| 774 | 772 | Git post-receive hooks are just one trigger. You can fire builds from anything: | |
| 775 | 773 | a cron job, a file watcher, a webhook receiver on your own server, a button press. | |
| 776 | 774 | </p> | |
| 777 | - | <div class="flow"> | |
| 778 | - | <div class="node">rsync workspace</div> | |
| 779 | - | <div class="arrow">→</div> | |
| 780 | - | <div class="node">ssh pub event</div> | |
| 781 | - | <div class="arrow">→</div> | |
| 782 | - | <div class="node">pico.sh runs</div> | |
| 783 | - | <div class="arrow">→</div> | |
| 784 | - | <div class="node">artifacts synced</div> | |
| 785 | - | </div> | |
| 786 | 775 | </div> | |
| 787 | 776 | <div> | |
| 788 | 777 | <img src="flow.png" style="width: 100%; border-radius: 10px;" /> |
| ... | ... | @@ -806,7 +795,7 @@ details .faq-answer { | |
| 806 | 795 | </p> | |
| 807 | 796 | <p> | |
| 808 | 797 | The managed service runs on our own hardware, not a cloud provider. Self-hosted | |
| 809 | - | is coming once the source is ready. | |
| 798 | + | is coming once the runner is ready. | |
| 810 | 799 | </p> | |
| 811 | 800 | <ul class="check-list"> | |
| 812 | 801 | <li>SSH keys are your auth</li> |
| ... | ... | @@ -867,12 +856,12 @@ details .faq-answer { | |
| 867 | 856 | <div> | |
| 868 | 857 | <p> | |
| 869 | 858 | <strong>ci.pico.sh</strong> runs on <a href="https://cd.pico.sh"><strong>cd.pico.sh</strong></a>: our SSH VM service | |
| 870 | - | on hardware we own. Not AWS. Not GCP. Not a cloud provider. | |
| 859 | + | on hardware we own. | |
| 871 | 860 | </p> | |
| 872 | 861 | <p> | |
| 873 | 862 | Push a <code>docker-compose.yml</code> to an SSH endpoint and your containers are live. | |
| 874 | - | Label a service and it gets a public HTTP URL. No cloud console, no CLI SDK, | |
| 875 | - | no provider lock-in. | |
| 863 | + | Label a service and it gets a public HTTP URL. There's no provider lock-in because it's a tool | |
| 864 | + | you likely already use for local development. | |
| 876 | 865 | </p> | |
| 877 | 866 | <p> | |
| 878 | 867 | The same platform that runs your CI runs your apps. |
| ... | ... | @@ -924,38 +913,39 @@ details .faq-answer { | |
| 924 | 913 | <section id="features"> | |
| 925 | 914 | <div class="container"> | |
| 926 | 915 | <p class="section-label">Features</p> | |
| 927 | - | <h2>Built for terminals, agents, and humans.</h2> | |
| 916 | + | <h2>Built for terminals, humans, and automation</h2> | |
| 928 | 917 | <div class="feature-grid"> | |
| 929 | 918 | <div class="feature-card"> | |
| 930 | - | <h3>AI-Agent Friendly</h3> | |
| 919 | + | <h3>Terminal Friendly</h3> | |
| 931 | 920 | <p> | |
| 932 | - | Terminal workflows, rsync + SSH pubsub, JSONL status streams. Everything an agent | |
| 933 | - | needs to trigger builds, monitor progress, and attach to failures. No OAuth flows, | |
| 934 | - | no API rate limits, no webhooks. An agent can start as many jobs as it wants | |
| 935 | - | and read results as structured text. | |
| 921 | + | Because <code>pici</code> doesn't rely on git-ops and triggering a | |
| 922 | + | build is done with rsync + ssh, we have the building blocks for you | |
| 923 | + | or a code agent to trigger builds, monitor progress, and attach to | |
| 924 | + | failures. Start as many jobs as you need and read results | |
| 925 | + | synchronously. | |
| 936 | 926 | </p> | |
| 937 | 927 | </div> | |
| 938 | 928 | <div class="feature-card"> | |
| 939 | 929 | <h3>SSH-First</h3> | |
| 940 | 930 | <p> | |
| 941 | - | No HTTP APIs to expose. No webhooks to configure. No OAuth tokens to manage. | |
| 942 | - | SSH keys are your auth. SSH pubsub is your event bus. | |
| 943 | - | If SSH works, CI works. | |
| 931 | + | SSH keys are your auth and we even support using SSH certificates for RBAC control. | |
| 932 | + | Rsync to upload workspaces, build artifacts, and ssh pubsub as your event bus. | |
| 944 | 933 | </p> | |
| 945 | 934 | </div> | |
| 946 | 935 | <div class="feature-card"> | |
| 947 | 936 | <h3>Static Site Artifacts</h3> | |
| 948 | 937 | <p> | |
| 949 | - | Build artifacts are plain HTML + CSS. No JavaScript. No app server. No build step. | |
| 950 | - | Serve the directory with any static host: nginx, s3, pgs.sh, <code>python -m http.server</code>. | |
| 951 | - | Zero runtime dependencies. | |
| 938 | + | Build artifacts are plain HTML + CSS. There's no app server or build step. | |
| 939 | + | Serve the directory with any static host: nginx, s3, <a href="https://pgs.sh">pgs.sh</a>, | |
| 940 | + | <code>python -m http.server</code>. | |
| 941 | + | It's a static site with zero runtime dependencies. | |
| 952 | 942 | </p> | |
| 953 | 943 | </div> | |
| 954 | 944 | <div class="feature-card"> | |
| 955 | 945 | <h3>Build Attestation</h3> | |
| 956 | 946 | <p> | |
| 957 | 947 | Automatic provenance baked into every job: runner hostname, OS, arch, repo, branch, | |
| 958 | - | commit, and workspace checksum. Supply-chain ready without extra tooling. | |
| 948 | + | commit, and workspace checksum. | |
| 959 | 949 | </p> | |
| 960 | 950 | </div> | |
| 961 | 951 | </div> |
| ... | ... | @@ -1052,18 +1042,6 @@ details .faq-answer { | |
| 1052 | 1042 | </div> | |
| 1053 | 1043 | </details> | |
| 1054 | 1044 | ||
| 1055 | - | <details> | |
| 1056 | - | <summary>How is this different from GitHub Actions, Jenkins, etc.?</summary> | |
| 1057 | - | <div class="faq-answer"> | |
| 1058 | - | <p> | |
| 1059 | - | Every build step in <code>pici</code> runs as a real terminal session (PTY) you can attach to. | |
| 1060 | - | No "re-run with SSH" button, no waiting for a tunnel. A test fails? Jump into the session, | |
| 1061 | - | press <code>↑</code> + <code>Enter</code> to rerun the command, inspect the environment, | |
| 1062 | - | fix the issue. Your pipeline is a bash script, same commands locally and in CI. | |
| 1063 | - | </p> | |
| 1064 | - | </div> | |
| 1065 | - | </details> | |
| 1066 | - | ||
| 1067 | 1045 | <details> | |
| 1068 | 1046 | <summary>How much does it cost?</summary> | |
| 1069 | 1047 | <div class="faq-answer"> |
| ... | ... | @@ -1084,28 +1062,6 @@ details .faq-answer { | |
| 1084 | 1062 | </p> | |
| 1085 | 1063 | </div> | |
| 1086 | 1064 | </details> | |
| 1087 | - | ||
| 1088 | - | <details> | |
| 1089 | - | <summary>How do I trigger builds?</summary> | |
| 1090 | - | <div class="faq-answer"> | |
| 1091 | - | <p> | |
| 1092 | - | Publish an event to <code>pipe.pico.sh</code> on the <code>build.event</code> channel with a | |
| 1093 | - | JSON payload containing the event type and workspace. Git post-receive hooks are the common | |
| 1094 | - | pattern, but anything that can SSH can trigger a build: cron, webhooks, file watchers, a button press. | |
| 1095 | - | </p> | |
| 1096 | - | </div> | |
| 1097 | - | </details> | |
| 1098 | - | ||
| 1099 | - | <details> | |
| 1100 | - | <summary>Can I use my own runners?</summary> | |
| 1101 | - | <div class="faq-answer"> | |
| 1102 | - | <p> | |
| 1103 | - | Yes, it's a first-class citizen. Bring your own hardware, your own isolation strategy: docker, | |
| 1104 | - | namespaces, bare metal. The same <code>pico.sh</code> and <code>zmx</code> sessions work | |
| 1105 | - | identically whether you run on your infra or ours. | |
| 1106 | - | </p> | |
| 1107 | - | </div> | |
| 1108 | - | </details> | |
| 1109 | 1065 | </div> | |
| 1110 | 1066 | </section> | |
| 1111 | 1067 |