pi-central 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +204 -2
- package/bin/pi-central.js +2836 -0
- package/bin/pi-central.js.map +7 -0
- package/dist/ui/assets/1c-CM5UDbeN.js +1 -0
- package/dist/ui/assets/1c-query-DVSXgUoE.js +1 -0
- package/dist/ui/assets/abap-BdImnpbu.js +1 -0
- package/dist/ui/assets/ada-BIOnG6TC.js +1 -0
- package/dist/ui/assets/adoc-DYxrpSh4.js +1 -0
- package/dist/ui/assets/ahk1-D2f7Ijez.js +1 -0
- package/dist/ui/assets/ahk2-8Zs4aa1G.js +1 -0
- package/dist/ui/assets/angular-expression-C9JlwiXB.js +1 -0
- package/dist/ui/assets/angular-html-D2F1cIM9.js +1 -0
- package/dist/ui/assets/angular-inline-style-aI-YlMgr.js +1 -0
- package/dist/ui/assets/angular-inline-template-BhVWr-GB.js +1 -0
- package/dist/ui/assets/angular-let-declaration-tXF0G55Y.js +1 -0
- package/dist/ui/assets/angular-template-PU1Sa1kY.js +1 -0
- package/dist/ui/assets/angular-template-blocks-D4Ew2WDq.js +1 -0
- package/dist/ui/assets/angular-ts-B5vx3S6V.js +1 -0
- package/dist/ui/assets/apache-Pmp26Uib.js +1 -0
- package/dist/ui/assets/apex-DhZFqWV2.js +1 -0
- package/dist/ui/assets/apl-BD0Fkm--.js +1 -0
- package/dist/ui/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/ui/assets/ara-BRHolxvo.js +1 -0
- package/dist/ui/assets/as3-CDRFp3-Q.js +1 -0
- package/dist/ui/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/ui/assets/astro-CeWFm1CR.js +1 -0
- package/dist/ui/assets/awk-DMzUqQB5.js +1 -0
- package/dist/ui/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/ui/assets/be-DZEKi0sx.js +1 -0
- package/dist/ui/assets/beancount-BgSHGh8x.js +1 -0
- package/dist/ui/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/ui/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/ui/assets/bird-CeWWThpZ.js +1 -0
- package/dist/ui/assets/blade-CQs288pm.js +1 -0
- package/dist/ui/assets/c-BIGW1oBm.js +1 -0
- package/dist/ui/assets/c3-Dp5svz6Z.js +1 -0
- package/dist/ui/assets/cairo-Ba9TFftT.js +1 -0
- package/dist/ui/assets/cdc-Dyf7ylpP.js +1 -0
- package/dist/ui/assets/chpl-QDWX03Hx.js +1 -0
- package/dist/ui/assets/clarity-Dn5IMItf.js +1 -0
- package/dist/ui/assets/clj-CZPsrr31.js +1 -0
- package/dist/ui/assets/closure-templates-Cv0TS44c.js +1 -0
- package/dist/ui/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/ui/assets/cmd-T6t9F4r8.js +1 -0
- package/dist/ui/assets/cobol-D6oRQjbg.js +1 -0
- package/dist/ui/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/ui/assets/coffeescript-l2w2Enha.js +1 -0
- package/dist/ui/assets/console-JZr4tX8D.js +1 -0
- package/dist/ui/assets/coq-BqXF5kFF.js +1 -0
- package/dist/ui/assets/core-CcaQSRDK.js +12 -0
- package/dist/ui/assets/cpp-2YYZ9QPt.js +1 -0
- package/dist/ui/assets/cpp-macro-BD_u8FP2.js +1 -0
- package/dist/ui/assets/cql-BEVj694s.js +1 -0
- package/dist/ui/assets/crystal-HlmihOZ-.js +1 -0
- package/dist/ui/assets/cs-CYZm7ub4.js +1 -0
- package/dist/ui/assets/css-Z72CF80r.js +1 -0
- package/dist/ui/assets/csv-fuZLfV_i.js +1 -0
- package/dist/ui/assets/cue-D82EKSYY.js +1 -0
- package/dist/ui/assets/d-85-TOEBH.js +1 -0
- package/dist/ui/assets/dart-CtKP3W-j.js +1 -0
- package/dist/ui/assets/dax-CEL-wOlO.js +1 -0
- package/dist/ui/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/ui/assets/diff-D97Zzqfu.js +1 -0
- package/dist/ui/assets/dockerfile-D5eKlNGy.js +1 -0
- package/dist/ui/assets/dotenv-De0Btta0.js +1 -0
- package/dist/ui/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/ui/assets/edge-BA25uoI8.js +1 -0
- package/dist/ui/assets/elisp-BQtZl9iK.js +1 -0
- package/dist/ui/assets/elixir-BzU7DNz_.js +1 -0
- package/dist/ui/assets/elm-DbKCFpqz.js +1 -0
- package/dist/ui/assets/engine-javascript-CuxHA8oH.js +141 -0
- package/dist/ui/assets/erb-B-_FUE16.js +1 -0
- package/dist/ui/assets/erl-btUkaAv0.js +1 -0
- package/dist/ui/assets/es-tag-css-Di8q07hx.js +1 -0
- package/dist/ui/assets/es-tag-glsl-DuY_gmju.js +1 -0
- package/dist/ui/assets/es-tag-html-CFifETgQ.js +1 -0
- package/dist/ui/assets/es-tag-sql-B4Gn1aEo.js +1 -0
- package/dist/ui/assets/es-tag-xml-BsowVsUr.js +1 -0
- package/dist/ui/assets/f95-OKqbxTCS.js +1 -0
- package/dist/ui/assets/fennel-BYunw83y.js +1 -0
- package/dist/ui/assets/fish-BvzEVeQv.js +1 -0
- package/dist/ui/assets/for-TD-2-mvr.js +1 -0
- package/dist/ui/assets/fs-2PIK3WrC.js +1 -0
- package/dist/ui/assets/fsl-DKWnMB5p.js +1 -0
- package/dist/ui/assets/ftl-anfqXHis.js +1 -0
- package/dist/ui/assets/gd-DmgsuTnj.js +1 -0
- package/dist/ui/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/ui/assets/genie-D0YGMca9.js +1 -0
- package/dist/ui/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/ui/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/ui/assets/git-rebase-Bqs5jo_V.js +1 -0
- package/dist/ui/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/ui/assets/gjs-gYW9DBuS.js +1 -0
- package/dist/ui/assets/gleam-BspZqrRM.js +1 -0
- package/dist/ui/assets/glsl-DplSGwfg.js +1 -0
- package/dist/ui/assets/gn-8iBmfbXw.js +1 -0
- package/dist/ui/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/ui/assets/go-C27-OAKa.js +1 -0
- package/dist/ui/assets/gql-MGiqm7Pm.js +1 -0
- package/dist/ui/assets/grammar-map-VuoEIDon.js +2 -0
- package/dist/ui/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/ui/assets/gts-DqU1Me4G.js +1 -0
- package/dist/ui/assets/hack-V6hhs-tI.js +1 -0
- package/dist/ui/assets/haml-jtrXxllQ.js +1 -0
- package/dist/ui/assets/haxe-CfZj7gIn.js +1 -0
- package/dist/ui/assets/hbs-CsgKbzmm.js +1 -0
- package/dist/ui/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/ui/assets/hjson-D5-asLiD.js +1 -0
- package/dist/ui/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/ui/assets/hs-cv9E3dfg.js +1 -0
- package/dist/ui/assets/html-derivative-zZehN5i_.js +1 -0
- package/dist/ui/assets/html-tMaWOgtj.js +1 -0
- package/dist/ui/assets/http-BS9aPmI9.js +1 -0
- package/dist/ui/assets/hurl-BxI2TCqe.js +1 -0
- package/dist/ui/assets/hxml-2-FPmUDs.js +1 -0
- package/dist/ui/assets/hy-DFXneXwc.js +1 -0
- package/dist/ui/assets/imba-DGztddWO.js +1 -0
- package/dist/ui/assets/index-BGiGoTsW.css +1 -0
- package/dist/ui/assets/index-BiOcGwMm.js +1 -0
- package/dist/ui/assets/index-qgPxqDeZ.js +40 -0
- package/dist/ui/assets/jade-CZYBTpjq.js +1 -0
- package/dist/ui/assets/java-CylS5w8V.js +1 -0
- package/dist/ui/assets/jinja-BV377aI7.js +1 -0
- package/dist/ui/assets/jinja-html-J_niBkwy.js +1 -0
- package/dist/ui/assets/jison-CI3IlJ66.js +1 -0
- package/dist/ui/assets/jl-DnT-B-wk.js +1 -0
- package/dist/ui/assets/json-Cp-IABpG.js +1 -0
- package/dist/ui/assets/json5-C9tS-k6U.js +1 -0
- package/dist/ui/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/ui/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/ui/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/ui/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/ui/assets/justfile-DM2KgpEt.js +1 -0
- package/dist/ui/assets/kdl-DV7GczEv.js +1 -0
- package/dist/ui/assets/kql-CAZwdKJH.js +1 -0
- package/dist/ui/assets/kts-DPNV9Nys.js +1 -0
- package/dist/ui/assets/latex-DJVikpzR.js +1 -0
- package/dist/ui/assets/lean4-CwwCO9Zr.js +1 -0
- package/dist/ui/assets/less-B1dDrJ26.js +1 -0
- package/dist/ui/assets/liquid-Bzms4plq.js +1 -0
- package/dist/ui/assets/lisp-d1OqKJ0v.js +1 -0
- package/dist/ui/assets/lit-C5SbI-X-.js +1 -0
- package/dist/ui/assets/llvm-BZoOZj88.js +1 -0
- package/dist/ui/assets/log-2UxHyX5q.js +1 -0
- package/dist/ui/assets/logo-BtOb2qkB.js +1 -0
- package/dist/ui/assets/lua-BaeVxFsk.js +1 -0
- package/dist/ui/assets/luau-nOZpfvQi.js +1 -0
- package/dist/ui/assets/makefile-BSLFislC.js +1 -0
- package/dist/ui/assets/markdown-nix-CTic1qqq.js +1 -0
- package/dist/ui/assets/markdown-vue-Cbnvtjg5.js +1 -0
- package/dist/ui/assets/marko-CPupNq7w.js +1 -0
- package/dist/ui/assets/matlab-D7o27uSR.js +1 -0
- package/dist/ui/assets/mbti-Myp4B69h.js +1 -0
- package/dist/ui/assets/md-Dt3v3XWf.js +1 -0
- package/dist/ui/assets/mdc-BlkeRyZp.js +1 -0
- package/dist/ui/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/ui/assets/mips-D0hiF3sa.js +1 -0
- package/dist/ui/assets/mjs-BOef1GtE.js +1 -0
- package/dist/ui/assets/mmd-CtyOPoVJ.js +1 -0
- package/dist/ui/assets/mojo-DJz3ZmWd.js +1 -0
- package/dist/ui/assets/move-el3G9tDJ.js +1 -0
- package/dist/ui/assets/nar-CgJlRCyo.js +1 -0
- package/dist/ui/assets/nextflow-groovy-CedDknKX.js +1 -0
- package/dist/ui/assets/nf-BAJNoAAx.js +1 -0
- package/dist/ui/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/ui/assets/nim-BCvQ9LSl.js +1 -0
- package/dist/ui/assets/nix-CNulEsOp.js +1 -0
- package/dist/ui/assets/nsis-BlV79W_Q.js +1 -0
- package/dist/ui/assets/nu-AJ1T3e-j.js +1 -0
- package/dist/ui/assets/objc-B7QIVcT6.js +1 -0
- package/dist/ui/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/ui/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/ui/assets/odin-BBf5iR-q.js +1 -0
- package/dist/ui/assets/org-D8hinxRC.js +1 -0
- package/dist/ui/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/ui/assets/perl-9_yHOIUr.js +1 -0
- package/dist/ui/assets/perl6-Czm8BUOa.js +1 -0
- package/dist/ui/assets/php-x4cDdYNa.js +1 -0
- package/dist/ui/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/ui/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/ui/assets/polar-C0HS_06l.js +1 -0
- package/dist/ui/assets/postcss-CXtECtnM.js +1 -0
- package/dist/ui/assets/potx-Zubr0-kU.js +1 -0
- package/dist/ui/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/ui/assets/prisma-Vru482bI.js +1 -0
- package/dist/ui/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/ui/assets/properties-h29QGfEk.js +1 -0
- package/dist/ui/assets/protobuf-S0pP4B9O.js +1 -0
- package/dist/ui/assets/puppet-BMWR74SV.js +1 -0
- package/dist/ui/assets/purescript-CklMAg4u.js +1 -0
- package/dist/ui/assets/pwsh-BpVOxWsY.js +1 -0
- package/dist/ui/assets/py-DWrqmXJp.js +1 -0
- package/dist/ui/assets/ql-CuETlrBG.js +1 -0
- package/dist/ui/assets/qml-CAmqjwmT.js +1 -0
- package/dist/ui/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/ui/assets/qss-IeuSbFQv.js +1 -0
- package/dist/ui/assets/r-Cf5RLm7j.js +1 -0
- package/dist/ui/assets/racket-BqYA7rlc.js +1 -0
- package/dist/ui/assets/razor-CMtLDytp.js +1 -0
- package/dist/ui/assets/rb-COoUipX6.js +1 -0
- package/dist/ui/assets/reg-C-SQnVFl.js +1 -0
- package/dist/ui/assets/regex-4rjvoqip.js +1 -0
- package/dist/ui/assets/rel-C3B-1QV4.js +1 -0
- package/dist/ui/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/ui/assets/ron-D8l8udqQ.js +1 -0
- package/dist/ui/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/ui/assets/rs-BhsT8Mbu.js +1 -0
- package/dist/ui/assets/rst-C2w80Rnv.js +1 -0
- package/dist/ui/assets/ruby-signature-Dr53Dmnh.js +1 -0
- package/dist/ui/assets/sas-BGn39htG.js +1 -0
- package/dist/ui/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/ui/assets/scad-C1CbN4fu.js +1 -0
- package/dist/ui/assets/scala-CqE71os6.js +1 -0
- package/dist/ui/assets/scheme-C98Dy4si.js +1 -0
- package/dist/ui/assets/scss-Cw6XMfVs.js +1 -0
- package/dist/ui/assets/shader-Ca6eN1Do.js +1 -0
- package/dist/ui/assets/smalltalk-BOQMe2GC.js +1 -0
- package/dist/ui/assets/smithy-cds9vsN8.js +1 -0
- package/dist/ui/assets/solidity-DijEV5ha.js +1 -0
- package/dist/ui/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/ui/assets/spl-CYnMqPaz.js +1 -0
- package/dist/ui/assets/sql-DkvoVjww.js +1 -0
- package/dist/ui/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/ui/assets/stata-DACIj5bg.js +1 -0
- package/dist/ui/assets/styl-BRLZixNf.js +1 -0
- package/dist/ui/assets/surql-DuXNjW2b.js +1 -0
- package/dist/ui/assets/svelte-Co4ixzwc.js +1 -0
- package/dist/ui/assets/swift-C2oV4EkX.js +1 -0
- package/dist/ui/assets/system-verilog-0hqHdDBg.js +1 -0
- package/dist/ui/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/ui/assets/talon-Byugm8Eo.js +1 -0
- package/dist/ui/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/ui/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/ui/assets/templ-8ecetEyQ.js +1 -0
- package/dist/ui/assets/tex-D96PA37w.js +1 -0
- package/dist/ui/assets/tfvars-C4cyYA4z.js +1 -0
- package/dist/ui/assets/toml-vGWfd6FD.js +1 -0
- package/dist/ui/assets/ts-muzv-B4Z.js +1 -0
- package/dist/ui/assets/tscn-DU9HihWa.js +1 -0
- package/dist/ui/assets/tsp-Ds05qIuC.js +1 -0
- package/dist/ui/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/ui/assets/tsx-COt5Ahok.js +1 -0
- package/dist/ui/assets/turtle-BsS91CYL.js +1 -0
- package/dist/ui/assets/twig-C3N1ALdA.js +1 -0
- package/dist/ui/assets/typ-BREikwzP.js +1 -0
- package/dist/ui/assets/v-BGw2Nkan.js +1 -0
- package/dist/ui/assets/vala-CsfeWuGM.js +1 -0
- package/dist/ui/assets/vb-Cu-pLBUe.js +1 -0
- package/dist/ui/assets/verilog-nZwndyjY.js +1 -0
- package/dist/ui/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/ui/assets/vimscript-Ct4t_lzx.js +1 -0
- package/dist/ui/assets/vue-Du5E_mGo.js +1 -0
- package/dist/ui/assets/vue-directives-OHNAz0dh.js +1 -0
- package/dist/ui/assets/vue-html-D5SNZKGg.js +1 -0
- package/dist/ui/assets/vue-interpolations-CiJO6OZ_.js +1 -0
- package/dist/ui/assets/vue-sfc-style-variable-injection-Bt3_SK3a.js +1 -0
- package/dist/ui/assets/vue-vine-CXe2Z88O.js +1 -0
- package/dist/ui/assets/vy-tAjnZflE.js +1 -0
- package/dist/ui/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/ui/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/ui/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/ui/assets/wiki-CEMRVyHf.js +1 -0
- package/dist/ui/assets/wit-5i3qLPDT.js +1 -0
- package/dist/ui/assets/wl-CprSW-RW.js +1 -0
- package/dist/ui/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/ui/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/ui/assets/yml-DbVfSbck.js +1 -0
- package/dist/ui/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/ui/assets/zig-VOosw3JB.js +1 -0
- package/dist/ui/assets/zsh-A78Q77OD.js +1 -0
- package/dist/ui/index.html +17 -0
- package/package.json +49 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sven Fillinger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,205 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Pi Central
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> The central station where Pi sessions come together and are orchestrated.
|
|
4
|
+
|
|
5
|
+
Pi Central is a local dashboard for running, watching, and switching between multiple
|
|
6
|
+
[Pi](https://pi.dev) coding-agent sessions that live in **different working directories**, while
|
|
7
|
+
keeping every session inside its own **Agent Safehouse** sandbox.
|
|
8
|
+
|
|
9
|
+
The name is the design brief: a central station is where independent lines arrive, are dispatched,
|
|
10
|
+
and are kept apart from one another. Pi Central does the same for agent sessions.
|
|
11
|
+
|
|
12
|
+
**Status: works end to end, verified, and published.** The version is deliberately not written down
|
|
13
|
+
here: `pi-central --version` reports the version of the package it was actually shipped in, and a
|
|
14
|
+
number restated in prose is a number that drifts. See [docs/RELEASING.md](docs/RELEASING.md).
|
|
15
|
+
|
|
16
|
+
## The problem
|
|
17
|
+
|
|
18
|
+
Pi has no fleet concept. One `pi` process owns one session and one working directory:
|
|
19
|
+
|
|
20
|
+
- Sessions are JSONL files grouped by working directory under `~/.pi/agent/sessions/`.
|
|
21
|
+
- RPC mode (`pi --mode rpc`) is a long-lived child process speaking JSONL over stdio.
|
|
22
|
+
- There is **no daemon, no attach protocol, no socket registry, and no port**. Each RPC process
|
|
23
|
+
privately owns its own stdin/stdout.
|
|
24
|
+
|
|
25
|
+
So working on three repositories means three terminals, three scrollbacks, and no single place to
|
|
26
|
+
see what is running, what is waiting for approval, or how much context each session has burned.
|
|
27
|
+
|
|
28
|
+
## The non-obvious constraint
|
|
29
|
+
|
|
30
|
+
macOS Seatbelt sandboxing does **not nest**. A process already inside `sandbox-exec` cannot apply a
|
|
31
|
+
second profile — `sandbox_init` returns `EPERM`. Safehouse's own profile documents this as not
|
|
32
|
+
fixable with additional allow rules.
|
|
33
|
+
|
|
34
|
+
This single fact rules out the obvious design (a Pi extension that hosts other sessions in-process)
|
|
35
|
+
and dictates the architecture: **the orchestrator must live outside any sandbox, and each session
|
|
36
|
+
must be its own `safehouse` invocation.** See [docs/CONSTRAINTS.md](docs/CONSTRAINTS.md).
|
|
37
|
+
|
|
38
|
+
It also means Pi Central must run from a **plain terminal** — not from an editor task, a sandboxed
|
|
39
|
+
shell, or an agent harness. It checks this before binding a port and refuses to start with an
|
|
40
|
+
explanation rather than failing confusingly later.
|
|
41
|
+
|
|
42
|
+
## Design in one picture
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
┌──────────────────────────────┐
|
|
46
|
+
│ Pi Central UI (localhost) │ session rail · transcript · approvals · tool trace
|
|
47
|
+
│ React + Vite, TypeScript │ Markdown rendered inert (ADR-0006)
|
|
48
|
+
└──────────────┬───────────────┘
|
|
49
|
+
│ WebSocket over loopback (typed envelopes)
|
|
50
|
+
┌──────────────▼───────────────┐
|
|
51
|
+
│ Orchestrator (unsandboxed) │ session registry · process supervision
|
|
52
|
+
│ TypeScript on Node │ · one sandboxed pi process per session
|
|
53
|
+
└──────────────┬───────────────┘
|
|
54
|
+
│ spawn: safehouse --workdir <cwd> -- pi --mode rpc
|
|
55
|
+
┌─────────┼─────────┐
|
|
56
|
+
▼ ▼ ▼
|
|
57
|
+
┌──────┐ ┌──────┐ ┌──────┐
|
|
58
|
+
│ pi │ │ pi │ │ pi │ one sandbox per working directory
|
|
59
|
+
│ /a │ │ /b │ │ /c │ isolation preserved per session
|
|
60
|
+
└──────┘ └──────┘ └──────┘
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Each session gets a correctly composed Safehouse profile for its own workdir. The orchestrator
|
|
64
|
+
never runs untrusted content, so being outside the sandbox is safe by construction.
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
**One process.** The orchestrator serves the built UI and the WebSocket from the same origin, so
|
|
69
|
+
there is no dev server to start and no port to coordinate. It must run from a plain terminal (see
|
|
70
|
+
the constraint above).
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install
|
|
74
|
+
npm run ui:build # once, and after any UI change
|
|
75
|
+
npm run server # the orchestrator, which also serves the UI
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then open <http://127.0.0.1:8787> — the URL the server prints.
|
|
79
|
+
|
|
80
|
+
### From the packaged artifact
|
|
81
|
+
|
|
82
|
+
Nothing is published yet, but the artifact is buildable and installable today (issue #52):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm run build:package # bundles the orchestrator, copies the built UI
|
|
86
|
+
npm pack --dry-run # show exactly what would ship
|
|
87
|
+
npm run serve:package # run the packaged binary from ./bin
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
It ships as JavaScript — TypeScript cannot be loaded from `node_modules` — as **one bundled ESM
|
|
91
|
+
file plus the built UI**, with a single runtime dependency. `pi-central --version` reports the
|
|
92
|
+
version of the package it was actually shipped in, read from that `package.json` rather than
|
|
93
|
+
restated in code. See [ADR-0011](docs/decisions/0011-distribution-and-update.md).
|
|
94
|
+
|
|
95
|
+
Serving the UI from the orchestrator is not only convenience. A Vite dev server watches
|
|
96
|
+
`packages/ui/src`, so an agent editing a component reloads the interface you are using out from
|
|
97
|
+
under you, mid-edit, into a syntax-error overlay. A built UI removes the watcher. It also makes
|
|
98
|
+
the `connect-src 'self'` in the CSP truthful by construction: the socket really is same-origin with
|
|
99
|
+
the document. See [docs/DOGFOODING.md](docs/DOGFOODING.md).
|
|
100
|
+
|
|
101
|
+
### Working on the UI
|
|
102
|
+
|
|
103
|
+
For hot reload while editing components, run the dev server instead — it proxies `/ws` to the
|
|
104
|
+
orchestrator and still needs no configuration:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm run server -- --no-ui # terminal 1 — socket only
|
|
108
|
+
npm run ui:dev # terminal 2 — Vite, on http://localhost:5173
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Key | Action |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `⌘N` | New session in an app-owned scratch workspace — no directory to choose |
|
|
114
|
+
| `⌘⇧O` | Open in a directory (the secondary path) |
|
|
115
|
+
| `Enter` | Send, or queue while a run is in progress |
|
|
116
|
+
| `Esc` | Answer an open dialog → close a popover → stop the run. Never clears your draft |
|
|
117
|
+
|
|
118
|
+
**Settings** (top of the window) shows which build is running, which protocol it speaks, and where
|
|
119
|
+
Pi Central keeps sessions, workspaces and the agent root — facts that were previously only in the
|
|
120
|
+
terminal's startup output. It has no preference controls yet, deliberately: update checking
|
|
121
|
+
([#55](https://github.com/sven1103-agent/pi-central/issues/55)) will add the first one, and it will be
|
|
122
|
+
opt-in.
|
|
123
|
+
|
|
124
|
+
## What works, and what does not
|
|
125
|
+
|
|
126
|
+
Stated plainly, because a dashboard that overstates itself is worse than one that does less.
|
|
127
|
+
|
|
128
|
+
**Works:** multiple sandboxed sessions in different directories with verified isolation; live
|
|
129
|
+
transcripts reconstructed from Pi's delta-only stream; the approval dock (`confirm` / `select` /
|
|
130
|
+
`input` / `editor`) answerable for any session; a bounded tool trace with full traversal; history
|
|
131
|
+
searchable by content, with a clear refusal when a session's directory is gone; agent-scoped
|
|
132
|
+
credentials with the host's own credentials denied, and commits signed as the agent when the store is
|
|
133
|
+
configured to sign.
|
|
134
|
+
|
|
135
|
+
**Not yet:** no file navigation. It is an issue rather than a wish — see below.
|
|
136
|
+
|
|
137
|
+
## Working on this project
|
|
138
|
+
|
|
139
|
+
Work is organised as **increments** (GitHub milestones) containing **slices** (issues). A slice is
|
|
140
|
+
sized to land in one pull request and to be verifiable on its own.
|
|
141
|
+
|
|
142
|
+
- [docs/INCREMENTS.md](docs/INCREMENTS.md) — what each increment delivers and why it is ordered
|
|
143
|
+
that way
|
|
144
|
+
- Issues — the slices, with acceptance criteria
|
|
145
|
+
- [docs/ROADMAP.md](docs/ROADMAP.md) — the long view, including what is deliberately out of scope
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm test # unit + component tests, all packages
|
|
149
|
+
npm run typecheck # two configs: Node libs and DOM libs cannot share one
|
|
150
|
+
npm run check:docs # every reference in every Markdown file resolves
|
|
151
|
+
npm run check:version # one version, declared once
|
|
152
|
+
npm run ui:build # production build of the UI
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The `check:docs` step exists because this repository is docs-driven, and a reference to a deleted
|
|
156
|
+
file still *looks* authoritative. It has caught real rot more than once. `check:version` exists for
|
|
157
|
+
the same reason one level up: the version was previously claimed in three places — `package.json`,
|
|
158
|
+
`README.md`, and a `CHANGELOG.md` heading — and three claims are three chances to disagree.
|
|
159
|
+
|
|
160
|
+
Releases are described in [docs/RELEASING.md](docs/RELEASING.md).
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
| Document | What it covers |
|
|
165
|
+
|---|---|
|
|
166
|
+
| [docs/USER-STORIES.md](docs/USER-STORIES.md) | What users need, and the constraints those needs create |
|
|
167
|
+
| [docs/CONSTRAINTS.md](docs/CONSTRAINTS.md) | The Seatbelt nesting limit and its consequences (C1–C15c) |
|
|
168
|
+
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Components, trust boundaries, lifecycle |
|
|
169
|
+
| [docs/STACK.md](docs/STACK.md) | TypeScript/Node orchestrator, React UI, rendering pipeline |
|
|
170
|
+
| [docs/PROTOCOL.md](docs/PROTOCOL.md) | The Pi RPC surface Pi Central depends on |
|
|
171
|
+
| [docs/SANDBOX.md](docs/SANDBOX.md) | How safehouse is invoked per session, and what the composed policy denies |
|
|
172
|
+
| [docs/AGENT-SETUP.md](docs/AGENT-SETUP.md) | Creating the agent identity a session runs as: SSH key, gitconfig, signing, `gh` |
|
|
173
|
+
| [docs/INCREMENTS.md](docs/INCREMENTS.md) | Increments, slices, and how work is sequenced |
|
|
174
|
+
| [docs/DOGFOODING.md](docs/DOGFOODING.md) | Using Pi Central to develop Pi Central, and what breaks if you run it from the checkout you edit |
|
|
175
|
+
| [docs/RELEASING.md](docs/RELEASING.md) | Cutting a release: the version source, the tag, provenance, and how to roll back |
|
|
176
|
+
| [docs/ROADMAP.md](docs/ROADMAP.md) | Phases, verification status, and out-of-scope items |
|
|
177
|
+
| [docs/OPEN-QUESTIONS.md](docs/OPEN-QUESTIONS.md) | Unresolved decisions |
|
|
178
|
+
| [docs/decisions/](docs/decisions/) | Architecture decision records |
|
|
179
|
+
| [packages/ui/DESIGN.md](packages/ui/DESIGN.md) | The UI design system, as implemented |
|
|
180
|
+
|
|
181
|
+
## Principles
|
|
182
|
+
|
|
183
|
+
1. **Isolation is the feature.** Never trade per-session sandboxing for convenience.
|
|
184
|
+
2. **The orchestrator is the trust boundary.** It stays local, holds no untrusted content, and
|
|
185
|
+
never executes model output.
|
|
186
|
+
3. **Pi is the source of truth.** Do not re-implement session semantics; consume RPC and the
|
|
187
|
+
persisted session tree.
|
|
188
|
+
4. **Additive, not a replacement.** Pi Central supervises `pi`; it does not fork it.
|
|
189
|
+
5. **Local first.** No telemetry, no network egress beyond providers Pi already calls.
|
|
190
|
+
6. **Untrusted content is inert.** Transcripts and file contents are strings to display, never
|
|
191
|
+
markup to execute — see [ADR-0006](docs/decisions/0006-untrusted-markdown-rendering.md).
|
|
192
|
+
7. **Confine the agents, not the user.** Safehouse constrains model-generated actions in a workdir.
|
|
193
|
+
The orchestrator is a user-level app acting as the user, on the user's files — see
|
|
194
|
+
[ADR-0007](docs/decisions/0007-filesystem-access-model.md).
|
|
195
|
+
8. **Never state something false.** A displayed value that is wrong is a defect, not a cosmetic
|
|
196
|
+
issue: this project has shipped misleading counts, a mislabelled session id, and a permission
|
|
197
|
+
error reported as a missing directory, and treats each as a bug.
|
|
198
|
+
9. **A peer, not a configurator.** Pi Central does not write into a user's Pi environment — no
|
|
199
|
+
skills, no extensions, no settings. It reads what exists and writes only its own state. A
|
|
200
|
+
defense does not require a new artifact in the environment it defends, and any setup a session
|
|
201
|
+
needs is a documented action the user takes (see [docs/AGENT-SETUP.md](docs/AGENT-SETUP.md)).
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT — see [LICENSE](LICENSE).
|