chamba 0.7.0 → 0.9.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.
Files changed (134) hide show
  1. package/LICENSE +53 -14
  2. package/README.md +34 -8
  3. package/dist/commands/advanced.js +7 -278
  4. package/dist/commands/dev.js +11 -612
  5. package/dist/commands/doctor.js +1 -29
  6. package/dist/commands/menu.js +1 -80
  7. package/dist/commands/onboard.js +6 -230
  8. package/dist/commands/settings.js +15 -349
  9. package/dist/lib/agent-commands.js +2 -0
  10. package/dist/lib/agent-context.js +6 -210
  11. package/dist/lib/browser.js +1 -40
  12. package/dist/lib/chamba-yaml.js +10 -191
  13. package/dist/lib/constants.js +1 -125
  14. package/dist/lib/dockerfile-builder.js +41 -261
  15. package/dist/lib/env.js +2 -78
  16. package/dist/lib/git-env.js +1 -21
  17. package/dist/lib/global-config.js +4 -66
  18. package/dist/lib/pnpm-store.js +1 -19
  19. package/dist/lib/ports.js +1 -210
  20. package/dist/lib/safe-rm.js +1 -36
  21. package/dist/lib/sessions.js +2 -34
  22. package/dist/lib/shadows.js +1 -176
  23. package/dist/lib/skills.js +2 -0
  24. package/dist/lib/templates.js +1 -0
  25. package/dist/lib/webterm.js +1 -305
  26. package/dist/lib/workspace-identity.js +4 -260
  27. package/package.json +4 -4
  28. package/templates/Dockerfile +15 -22
  29. package/templates/claude-statusline.sh +5 -7
  30. package/templates/context/baseline.md +4 -2
  31. package/templates/context/web-pane-craft.md +1 -1
  32. package/templates/pane-apps/client/assets/api-BBDf_rzz.js +12 -0
  33. package/templates/pane-apps/client/assets/api-DNLbSBpK.css +1 -0
  34. package/templates/pane-apps/client/assets/bee-B7t97l5B.webp +0 -0
  35. package/templates/pane-apps/client/assets/buzz-CUUsbnXH.mp3 +0 -0
  36. package/templates/pane-apps/client/assets/c-BNa-DeUl.json +3552 -0
  37. package/templates/pane-apps/client/assets/cpp-B-T4NRoH.json +20239 -0
  38. package/templates/pane-apps/client/assets/csharp-BbxHChhA.json +6010 -0
  39. package/templates/pane-apps/client/assets/css-CWCxuwmz.json +1860 -0
  40. package/templates/pane-apps/client/assets/diff-B-2N89g8.json +154 -0
  41. package/templates/pane-apps/client/assets/docker-DWTvYW26.json +103 -0
  42. package/templates/pane-apps/client/assets/files-BkmyervY.js +1 -0
  43. package/templates/pane-apps/client/assets/go-B2hyYeNg.json +3156 -0
  44. package/templates/pane-apps/client/assets/graphql-Z6Id2aNO.json +1292 -0
  45. package/templates/pane-apps/client/assets/home-3SeGzySM.css +1 -0
  46. package/templates/pane-apps/client/assets/home-Cu9xOd2i.js +1 -0
  47. package/templates/pane-apps/client/assets/html-BtzvlIfu.json +2627 -0
  48. package/templates/pane-apps/client/assets/ini-Bn3Twap1.json +108 -0
  49. package/templates/pane-apps/client/assets/java-C7t2dwLO.json +1885 -0
  50. package/templates/pane-apps/client/assets/javascript-DuC2v0C0.json +5996 -0
  51. package/templates/pane-apps/client/assets/json-CwdkWeV5.json +206 -0
  52. package/templates/pane-apps/client/assets/jsonc-MYWDbTU3.json +206 -0
  53. package/templates/pane-apps/client/assets/jsx-Cn8EZuIC.json +5996 -0
  54. package/templates/pane-apps/client/assets/kotlin-CFNOz1gw.json +580 -0
  55. package/templates/pane-apps/client/assets/make-BVnlFCcl.json +629 -0
  56. package/templates/pane-apps/client/assets/markdown-B4Xk2WM_.json +3263 -0
  57. package/templates/pane-apps/client/assets/php-CAQzQmmI.json +4188 -0
  58. package/templates/pane-apps/client/assets/pop-D5ZANBC3.mp3 +0 -0
  59. package/templates/pane-apps/client/assets/python-CYQee8m4.json +4174 -0
  60. package/templates/pane-apps/client/assets/reviews-DMrGB-kG.js +153 -0
  61. package/templates/pane-apps/client/assets/reviews-nK_yRav9.css +1 -0
  62. package/templates/pane-apps/client/assets/ruby-D7R58tus.json +3114 -0
  63. package/templates/pane-apps/client/assets/rust-BFBbFiei.json +1103 -0
  64. package/templates/pane-apps/client/assets/scss-TQRhBkPG.json +1874 -0
  65. package/templates/pane-apps/client/assets/shellscript-DieAkC4W.json +2375 -0
  66. package/templates/pane-apps/client/assets/specs-Cabb15F0.js +13 -0
  67. package/templates/pane-apps/client/assets/sql-Bxd030LV.json +634 -0
  68. package/templates/pane-apps/client/assets/toml-ChrKGzsV.json +430 -0
  69. package/templates/pane-apps/client/assets/tsx-D2e90MFw.json +5996 -0
  70. package/templates/pane-apps/client/assets/typescript-DonXQ_n1.json +5747 -0
  71. package/templates/pane-apps/client/assets/useNow-BHFKFraS.js +1 -0
  72. package/templates/pane-apps/client/assets/xml-B17r2RXF.json +382 -0
  73. package/templates/pane-apps/client/assets/yaml-CKn4h1zy.json +627 -0
  74. package/templates/pane-apps/client/home/index.html +16 -0
  75. package/templates/pane-apps/client/reviews/index.html +17 -0
  76. package/templates/pane-apps/client/specs/index.html +4 -2
  77. package/templates/pane-apps/server/home.mjs +12 -0
  78. package/templates/pane-apps/server/reviews.mjs +21 -0
  79. package/templates/pane-apps/server/specs.mjs +5 -1588
  80. package/templates/skills/chamba-statusline/SKILL.md +7 -19
  81. package/templates/skills/dx-review/SKILL.md +136 -0
  82. package/templates/skills/dx-review/references/acts.md +233 -0
  83. package/templates/skills/dx-spec/SKILL.md +230 -30
  84. package/templates/skills/dx-spec/references/principles-template.md +2 -0
  85. package/templates/skills/dx-spec/references/review-guide.md +6 -52
  86. package/templates/skills/dx-spec/references/spec-guide.md +25 -5
  87. package/templates/skills/dx-spec/references/stages.md +149 -60
  88. package/templates/skills/dx-spec-execute/SKILL.md +217 -38
  89. package/templates/startup.mjs +22 -16
  90. package/templates/tool-helper.sh +168 -0
  91. package/templates/webterm/README.md +82 -27
  92. package/templates/webterm/color.js +61 -0
  93. package/templates/webterm/config.js +55 -4
  94. package/templates/webterm/context/claude.md +0 -1
  95. package/templates/webterm/public/app/alerts.js +95 -14
  96. package/templates/webterm/public/app/anchored.js +81 -0
  97. package/templates/webterm/public/app/composer.js +37 -3
  98. package/templates/webterm/public/app/connection.js +23 -0
  99. package/templates/webterm/public/app/dom.js +3 -0
  100. package/templates/webterm/public/app/frames.js +52 -18
  101. package/templates/webterm/public/app/home-host.js +16 -0
  102. package/templates/webterm/public/app/main.js +24 -8
  103. package/templates/webterm/public/app/new-session.js +13 -41
  104. package/templates/webterm/public/app/palette.js +58 -0
  105. package/templates/webterm/public/app/pane-shape.js +169 -0
  106. package/templates/webterm/public/app/pane-shell.js +240 -135
  107. package/templates/webterm/public/app/pane.js +39 -24
  108. package/templates/webterm/public/app/reviews-host.js +19 -0
  109. package/templates/webterm/public/app/specs-host.js +12 -218
  110. package/templates/webterm/public/app/state.js +5 -0
  111. package/templates/webterm/public/app/tabs.js +6 -2
  112. package/templates/webterm/public/app/theme.js +75 -27
  113. package/templates/webterm/public/app/tool-host.js +318 -0
  114. package/templates/webterm/public/app/workspace-color.js +192 -0
  115. package/templates/webterm/public/index.html +22 -4
  116. package/templates/webterm/public/styles.css +195 -21
  117. package/templates/webterm/server.js +198 -150
  118. package/templates/webterm/tool-document.js +3 -2
  119. package/templates/webterm/tools/commands.js +61 -0
  120. package/templates/webterm/tools/home.js +58 -0
  121. package/templates/webterm/tools/index.js +26 -0
  122. package/templates/webterm/tools/mount.js +337 -0
  123. package/templates/webterm/tools/paths.js +34 -0
  124. package/templates/webterm/tools/reviews.js +137 -0
  125. package/templates/webterm/tools/specs.js +154 -0
  126. package/templates/webterm/typed-line.js +70 -7
  127. package/templates/context/context-usage.md +0 -1
  128. package/templates/context-usage.sh +0 -266
  129. package/templates/pane-apps/client/assets/specs-B1970L17.css +0 -1
  130. package/templates/pane-apps/client/assets/specs-cEee_SPn.js +0 -23
  131. package/templates/skills/dx-spec-config/SKILL.md +0 -313
  132. package/templates/skills/dx-spec-config/references/principles-template.md +0 -12
  133. package/templates/specs.sh +0 -106
  134. package/templates/webterm/specs.js +0 -358
@@ -634,13 +634,13 @@ body.dragging {
634
634
  }
635
635
 
636
636
  /* The width is app/pane-shell.js's, in a custom property so the three rules that must win - the collapsed
637
- spine, the full row and the narrow-screen layout - still do. The value here is what shows before the first
638
- drag. */
637
+ spine, the full row and the narrow-screen layout - still do. The value here shows for the moment before the
638
+ first draw sets the property, so it is the same half the pane's own default is. */
639
639
  #pane {
640
640
  display: flex;
641
641
  flex: none;
642
642
  flex-direction: column;
643
- width: var(--pane-width, 44%);
643
+ width: var(--pane-width, 50%);
644
644
  min-width: 0;
645
645
  background: var(--bg);
646
646
  }
@@ -706,9 +706,9 @@ body.dragging {
706
706
  #panebar {
707
707
  display: flex;
708
708
  flex: none;
709
- align-items: flex-end;
709
+ align-items: center;
710
710
  gap: 2px;
711
- padding: 7px 10px 0;
711
+ padding: 0 8px;
712
712
  background: var(--bg);
713
713
  border-bottom: 1px solid var(--border);
714
714
  }
@@ -720,21 +720,23 @@ body.dragging {
720
720
  overflow: hidden;
721
721
  }
722
722
 
723
- /* A tab is a folder mouth: the open one carries the panel's own background up into the bar, so the two read
724
- as one surface and the others read as behind it. */
723
+ /* A tab is a label with a line under it: the pane's bar is chrome rather than a surface of its own, and the
724
+ workspace's colour under the open one is what says which tool is on the screen. */
725
725
  .tool-tab {
726
726
  display: flex;
727
727
  flex: none;
728
728
  align-items: center;
729
729
  gap: 6px;
730
- padding: 4px 14px;
731
- border: 1px solid transparent;
732
- border-bottom: none;
733
- border-radius: 7px 7px 0 0;
730
+ height: 34px;
731
+ padding: 0 12px;
732
+ border: none;
733
+ /* On every tab, transparent until one is open, so the open one takes no extra height and the row of them
734
+ does not move as the tool changes. */
735
+ border-bottom: 2px solid transparent;
734
736
  background: none;
735
737
  color: var(--muted);
736
738
  font: inherit;
737
- font-size: 12.5px;
739
+ font-size: 13px;
738
740
  cursor: pointer;
739
741
  }
740
742
 
@@ -743,8 +745,7 @@ body.dragging {
743
745
  }
744
746
 
745
747
  .tool-tab.on {
746
- background: var(--panel);
747
- border-color: var(--border);
748
+ border-bottom-color: var(--ws);
748
749
  color: var(--text);
749
750
  }
750
751
 
@@ -759,22 +760,74 @@ body.dragging {
759
760
  font-weight: 700;
760
761
  }
761
762
 
763
+ /* Something landed in a tool the user is not looking at: a ring around its mark, three times, then rest.
764
+ TAB_PULSE_MS in app/pane-shell.js must match three turns of this - it is what takes the class off again,
765
+ since a tab, unlike the pane, is rebuilt from one frame to the next. The delay is how far a rebuilt tab is
766
+ already into the ring, so a redraw in the middle of a pulse resumes it. */
767
+ .tool-mark.pulse {
768
+ position: relative;
769
+ }
770
+
771
+ .tool-mark.pulse::after {
772
+ content: "";
773
+ position: absolute;
774
+ inset: -4px;
775
+ border: 2px solid var(--accent);
776
+ border-radius: 12px;
777
+ animation: toolMarkRing 1.6s ease-out 3;
778
+ animation-delay: var(--ring-delay, 0s);
779
+ }
780
+
781
+ @keyframes toolMarkRing {
782
+ from {
783
+ opacity: 0.9;
784
+ transform: scale(0.8);
785
+ }
786
+ to {
787
+ opacity: 0;
788
+ transform: scale(1.5);
789
+ }
790
+ }
791
+
792
+ /* The same moment, held instead of pulsed, the way the pane's own arrival highlight is. Without this the
793
+ ring would never appear at all for someone who asked for less movement. */
794
+ @media (prefers-reduced-motion: reduce) {
795
+ .tool-mark.pulse::after {
796
+ opacity: 0.9;
797
+ animation: none;
798
+ }
799
+ }
800
+
801
+ /* A tool that counts nothing says only that something arrived, so its mark carries no number and is drawn
802
+ as the dot it means. */
803
+ .tool-mark.dot {
804
+ width: 6px;
805
+ height: 6px;
806
+ padding: 0;
807
+ border-radius: 50%;
808
+ align-self: center;
809
+ }
810
+
762
811
  #pane-ctl {
763
812
  display: flex;
764
813
  flex: none;
765
814
  margin-left: auto;
766
- gap: 4px;
767
- padding-bottom: 5px;
815
+ gap: 2px;
768
816
  }
769
817
 
818
+ /* The three widths, drawn as one row: the whole window, half of it, and away. */
770
819
  #pane-ctl .pane-nav {
771
820
  display: flex;
772
821
  align-items: center;
773
822
  justify-content: center;
774
- padding: 2px 5px;
823
+ width: 28px;
824
+ height: 28px;
825
+ padding: 0;
826
+ border-radius: 6px;
775
827
  }
776
828
 
777
- /* The pane is already at the far end, and the button is the way back from it. */
829
+ /* The pane is already in the state the button names, so the button says so - and for the far end it is also
830
+ the way back from it. */
778
831
  #pane-ctl .pane-nav.on {
779
832
  background: #10151c;
780
833
  color: var(--accent);
@@ -1053,6 +1106,14 @@ body.dragging .tool-frame {
1053
1106
  writing-mode: horizontal-tb;
1054
1107
  }
1055
1108
 
1109
+ #spine-badge.dot {
1110
+ display: inline-block;
1111
+ width: 6px;
1112
+ height: 6px;
1113
+ padding: 0;
1114
+ border-radius: 50%;
1115
+ }
1116
+
1056
1117
  #spine-badge[hidden] {
1057
1118
  display: none;
1058
1119
  }
@@ -1071,13 +1132,17 @@ body.dragging .tool-frame {
1071
1132
 
1072
1133
  /* ---- Overlay cards (take over / end session / limit reached) ---- */
1073
1134
 
1135
+ /* Fixed to the viewport and above every pop, so the card is in the middle of the screen whatever the width of
1136
+ the terminal column beside the pane. */
1074
1137
  #overlay {
1075
1138
  display: none;
1076
- position: absolute;
1139
+ position: fixed;
1077
1140
  inset: 0;
1141
+ z-index: 70;
1078
1142
  background: rgba(13, 17, 23, 0.82);
1079
1143
  align-items: center;
1080
1144
  justify-content: center;
1145
+ padding: 16px;
1081
1146
  }
1082
1147
 
1083
1148
  #overlay.show {
@@ -1085,7 +1150,9 @@ body.dragging .tool-frame {
1085
1150
  }
1086
1151
 
1087
1152
  .card {
1153
+ width: 100%;
1088
1154
  max-width: 460px;
1155
+ box-sizing: border-box;
1089
1156
  padding: 18px 20px;
1090
1157
  background: var(--panel);
1091
1158
  border: 1px solid var(--border);
@@ -1201,9 +1268,102 @@ body.dragging .tool-frame {
1201
1268
  }
1202
1269
  }
1203
1270
 
1271
+ /* ---- The workspace colour ---- */
1272
+
1273
+ /* The one control in the bar about what this window *is* rather than what it does, so it sits beside the name
1274
+ it belongs with. It carries no colour of its own, and is drawn exactly as the bell and the power button
1275
+ are: the bar already says which colour is in force, on the edge of the active tab, and a filled swatch in
1276
+ a row of glyphs reads as something that wandered in rather than as one of the row. */
1277
+ #wscolorbtn {
1278
+ display: flex;
1279
+ align-items: center;
1280
+ justify-content: center;
1281
+ padding: 4px;
1282
+ background: transparent;
1283
+ color: var(--muted);
1284
+ border: 1px solid transparent;
1285
+ border-radius: 7px;
1286
+ cursor: pointer;
1287
+ }
1288
+
1289
+ #wscolorbtn:hover:not(:disabled),
1290
+ #wscolorbtn.open {
1291
+ color: var(--text);
1292
+ border-color: var(--border);
1293
+ }
1294
+
1295
+ /* Nothing to open while this window is not talking to the server: a pick it could not send would be undone by
1296
+ the next frame, which is worse than not offering it. */
1297
+ #wscolorbtn:disabled {
1298
+ opacity: 0.45;
1299
+ cursor: default;
1300
+ }
1301
+
1302
+ /* Anchored under the button and hung off the body, like the new-session panel: the bar is emptied on every
1303
+ frame, and picking a colour is itself a frame, so a panel inside the bar would close as it was used. */
1304
+ #wscolorpop {
1305
+ position: fixed;
1306
+ z-index: 60;
1307
+ display: flex;
1308
+ flex-direction: column;
1309
+ width: 268px;
1310
+ padding: 12px;
1311
+ background: var(--panel);
1312
+ border: 1px solid var(--border);
1313
+ border-radius: 10px;
1314
+ box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5);
1315
+ }
1316
+
1317
+ .wsgrid {
1318
+ display: grid;
1319
+ grid-template-columns: repeat(6, 1fr);
1320
+ gap: 8px;
1321
+ }
1322
+
1323
+ .wscell {
1324
+ display: flex;
1325
+ align-items: center;
1326
+ justify-content: center;
1327
+ aspect-ratio: 1;
1328
+ padding: 0;
1329
+ border: 1px solid rgba(255, 255, 255, 0.08);
1330
+ border-radius: 7px;
1331
+ cursor: pointer;
1332
+ }
1333
+
1334
+ /* Two rings rather than a thicker border, so the mark reads on every one of the eleven and the cell does not
1335
+ move when it lands. The mark says what is *stored*, so it sits on the automatic cell when nothing is. */
1336
+ .wscell.chosen {
1337
+ box-shadow:
1338
+ 0 0 0 2px var(--panel),
1339
+ 0 0 0 3.5px var(--text);
1340
+ }
1341
+
1342
+ /* Automatic takes the last cell: it is one of the choices rather than a button underneath them. */
1343
+ .wscell.auto {
1344
+ background: repeating-linear-gradient(135deg, var(--border) 0 4px, #21262d 4px 8px);
1345
+ color: var(--muted);
1346
+ font-size: 15px;
1347
+ line-height: 1;
1348
+ }
1349
+
1350
+ .wscolorfoot {
1351
+ margin: 11px 0 0;
1352
+ padding-top: 10px;
1353
+ color: var(--muted);
1354
+ border-top: 1px solid var(--border);
1355
+ font-size: 11.5px;
1356
+ line-height: 1.45;
1357
+ }
1358
+
1204
1359
  /* The moment the socket drops, before any curtain: a control whose answer goes nowhere must stop taking
1205
- clicks. The composer disables itself, so this is about the bar - its tabs, its X, its + New session. */
1206
- body.offline #tabbar {
1360
+ clicks. The composer disables itself, so this is about the bar - its tabs, its X, its + New session.
1361
+ The two anchored panels are named as well: they hang off the body rather than the bar, so the bar's own
1362
+ selector does not cover them. connection.js closes them outright when the socket goes, and this is the second
1363
+ line - a rule that holds whatever order things happen in. */
1364
+ body.offline #tabbar,
1365
+ body.offline #newpop,
1366
+ body.offline #wscolorpop {
1207
1367
  pointer-events: none;
1208
1368
  }
1209
1369
 
@@ -1371,6 +1531,20 @@ body.offline #tabbar {
1371
1531
  /* Border carries the state (no separate status dot): lit in the workspace's colour when you can type into the
1372
1532
  attached session, plain grey while this window is between sessions or reconnecting. A dropped connection is
1373
1533
  not a failure here - the session on the other side kept running - so it goes quiet rather than warning. */
1534
+ /* The ruler autoGrow() measures the text in: out of the flow, out of sight, and of no height of its own, so
1535
+ its scroll height is the height of the text and nothing about it moves the composer. */
1536
+ #input-mirror {
1537
+ position: absolute;
1538
+ top: 0;
1539
+ left: 0;
1540
+ height: 0;
1541
+ min-height: 0;
1542
+ overflow: hidden;
1543
+ visibility: hidden;
1544
+ pointer-events: none;
1545
+ resize: none;
1546
+ }
1547
+
1374
1548
  #input.online {
1375
1549
  border-color: var(--ws);
1376
1550
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ws) 25%, transparent);