@leftoff/cli 0.9.17-beta.9 → 0.9.17

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leftoff",
3
- "version": "0.9.17-beta.9",
3
+ "version": "0.9.17",
4
4
  "description": "Leftoff (formerly Checkpoints): WTF was I working on? Tracks every Claude Code session on this machine, writes a 3-line checkpoint when one goes quiet, and adds /cp (checkpoint now), /cp-name and a /leftoff pane. Talks to the local Leftoff daemon on 127.0.0.1:7429 and falls back to writing markdown in ~/checkpoints.",
5
5
  "author": {
6
6
  "name": "One Silly App"
@@ -28,7 +28,7 @@ const END_TIMEOUT_MS = 1000
28
28
  const MODEL_TIMEOUT_MS = 20000
29
29
 
30
30
  // Module state. $.state is not used: the pane redraws with $.ui.invalidate.
31
- const MOD_VERSION = '0.9.17-beta.9' // keep in step with .claude-plugin/plugin.json
31
+ const MOD_VERSION = '0.9.17' // keep in step with .claude-plugin/plugin.json
32
32
 
33
33
  const st = {
34
34
  internal: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leftoff/cli",
3
- "version": "0.9.17-beta.9",
3
+ "version": "0.9.17",
4
4
  "description": "Leftoff: WTF was I working on? Tracks every Claude Code session, writes a 3-line checkpoint when one goes quiet, and gives you a daily digest and a board, on your Mac and (optionally) your phone.",
5
5
  "keywords": [
6
6
  "claude",
package/ui/app.css CHANGED
@@ -4636,7 +4636,7 @@ html:not(.live-full) .fs-side { display: none; }
4636
4636
  .wt-st-h { display: flex; align-items: center; gap: 10px; min-height: 24px; flex-wrap: wrap; }
4637
4637
  .wt-n { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding-top: 1px; box-sizing: border-box; border-radius: 50%; border: 1px solid var(--line-strong); font-size: 12px; font-weight: 650; line-height: 1; color: var(--text2); }
4638
4638
  .wt-st.done .wt-n { background: var(--card2); }
4639
- .wt-st.done :is(.wt-snip, .wt-showc, .wt-cos, .wt-why) { display: none; } /* reviewed: folded to its title; Reviewed again opens it */
4639
+ .wt-st.done :is(.wt-snip, .wt-showc, .wt-cos, .wt-why, .wt-sf, .wt-sfa) { display: none; } /* reviewed: folded to its title; Reviewed again opens it */
4640
4640
  .wt-st.done { padding-bottom: 14px; }
4641
4641
  .wt-st-h h3 { flex: 1 1 14em; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; line-height: 1.3; }
4642
4642
  .wt-tag { flex: none; display: inline-flex; align-items: center; height: 20px; padding: 1px 8px 0; box-sizing: border-box; border: 1px solid var(--line); border-radius: 6px; font-size: 11.5px; font-weight: 600; line-height: 1; color: var(--muted); }
@@ -4713,7 +4713,7 @@ details[open] > summary .wt-g-chev { transform: rotate(90deg); }
4713
4713
  /* 0.9.18 (Joel): a file list on the left (the file map, or the Files view's list) and the reading
4714
4714
  on the right, each in its own scroll box filling the height; pinned headers stay in theirs */
4715
4715
  .wt-2p { flex: 1 1 auto; min-height: 0; display: flex; }
4716
- .wt-2p > .wt-side { flex: 0 0 256px; box-sizing: border-box; position: static; align-self: stretch; max-height: none; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 8px 20px 12px; border-right: 1px solid var(--line); }
4716
+ .wt-2p > .wt-side { flex: 0 0 var(--wt-side-w, 256px); box-sizing: border-box; position: static; align-self: stretch; max-height: none; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 8px 20px 12px; border-right: 1px solid var(--line); }
4717
4717
  .wt-2p > .wt-scroll { flex: 1 1 auto; min-width: 0; }
4718
4718
  .wt-2p .wt-hw { max-width: 1000px; }
4719
4719
  .wt.wt-big .wt-2p .wt-hw { display: block; max-width: 1000px; }
@@ -5209,3 +5209,145 @@ code .file-ref-off { font-size: inherit; }
5209
5209
  .file-ref-off:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 3px; }
5210
5210
  .fs-side-in > .wid { border-top: 1px solid var(--line); margin-top: 4px; }
5211
5211
  .fs-side-in > .wid .wid-toggle h2 { text-transform: none; letter-spacing: normal; font-size: 13.5px; font-weight: 600; color: var(--text2); }
5212
+
5213
+ /* 0.9.19 (Joel): a walkthrough's words render as Markdown (ui/walk-md.js). Inline code is the
5214
+ board's code chip; it wraps anywhere, so a long `--flag` or path never pushes a phone sideways. */
5215
+ .wt-md > :first-child { margin-top: 0; }
5216
+ .wt-md > :last-child { margin-bottom: 0; }
5217
+ .wt-md p { margin: 0 0 8px; }
5218
+ .wt-md :is(ul, ol) { margin: 0 0 8px; padding-left: 20px; }
5219
+ .wt-md li { margin: 2px 0; }
5220
+ .wt-md :is(h2, h3, h4, h5, h6) { margin: 10px 0 4px; font-size: 1em; font-weight: 650; color: var(--text); }
5221
+ .wt-md blockquote { margin: 0 0 8px; padding: 0 0 0 10px; border-left: 3px solid var(--line-strong); }
5222
+ .wt-md a, .md-in a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; overflow-wrap: anywhere; }
5223
+ .wt-md, .md-in { overflow-wrap: break-word; min-width: 0; }
5224
+ :is(.wt-md, .md-in) code { font-family: var(--mono); font-size: .86em; background: var(--bg2); border: 1px solid var(--line); border-radius: 5px; padding: 0 4px; color: var(--text); overflow-wrap: break-word; word-break: normal; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
5225
+ .wt-md pre { margin: 0 0 8px; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; background: var(--field); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font: 12px/1.45 var(--mono); white-space: pre; }
5226
+ .wt-md pre code { background: none; border: 0; padding: 0; font-size: inherit; overflow-wrap: normal; word-break: normal; }
5227
+ .wt-md .code-wrap { position: relative; max-width: 100%; }
5228
+ .wt-st-h h3.md-in code { font-size: .84em; }
5229
+ .wt-ag-t.md-in code { font-size: .86em; }
5230
+ /* "Mark reviewed & next" beside the plain Next (Joel: "2 next buttons. One that marks as viewed") */
5231
+ .wt-dnav .wt-drev { gap: 6px; padding: 1px 14px 0; }
5232
+ .wt-dnav .wt-drev[hidden] { display: none; }
5233
+ @media (max-width: 699.98px) {
5234
+ .wt-dnav .btn.wt-drev { width: auto; flex: none; padding: 1px 12px 0; }
5235
+ .wt-dnav .wt-drev .wt-dl { display: inline; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
5236
+ }
5237
+ .wt-drev .wt-dl-s { display: none; }
5238
+ @media (max-width: 699.98px) { .wt-drev .wt-dl-l { display: none; } .wt-drev .wt-dl-s { display: inline; } }
5239
+
5240
+ /* 0.9.19 Claude's and the summarizer's words with `code` in the quiet lines and Catch me up: the board's code chip */
5241
+ :is(.recap-line, .before-clear, .back-line, .scu) code { font-family: var(--mono); font-size: .88em; background: var(--bg2); border: 1px solid var(--line); border-radius: 5px; padding: 0 4px; overflow-wrap: anywhere; word-break: break-word; }
5242
+
5243
+ /* 2026-10-29 a walkthrough across several repos: the repos line, a header per repo (agenda and page), and a quiet line for a repo that couldn't be read */
5244
+ .wt-repos { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-size: 12.5px; line-height: 1.3; overflow-wrap: anywhere; }
5245
+ .wt-repos .ic { flex: none; width: 13px; height: 13px; }
5246
+ .wt-unr { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
5247
+ .wt-unr li { display: flex; align-items: flex-start; gap: 6px; font-size: 12.5px; line-height: 1.35; overflow-wrap: anywhere; }
5248
+ .wt-unr .ic { flex: none; width: 13px; height: 13px; margin-top: 2px; }
5249
+ .wt-ag-rh { display: flex; align-items: baseline; gap: 2px; margin: 10px 0 0; padding: 0 2px; font-size: 12.5px; min-width: 0; overflow-wrap: anywhere; }
5250
+ .wt-ag-rh:first-child { margin-top: 2px; }
5251
+ .wt-ag-rh b { font-weight: 650; font-size: 12.5px; }
5252
+ .wt-rh .ic { flex: none; width: 14px; height: 14px; color: var(--text2); }
5253
+ .wt-rh .mono { font-size: 13px; }
5254
+ @media (min-width: 700px) { .wt-files-r { max-width: 22em; } }
5255
+ .wt-ag-ok { flex: none; white-space: nowrap; }
5256
+
5257
+ /* 2026-10-30 walkthrough round 3 ------------------------------------------------------------ */
5258
+ /* a step's files, each folding on its own (chevron, status, path, +/−) */
5259
+ .wt-sfa { display: flex; justify-content: flex-end; gap: 4px; margin: 6px 0 -2px; }
5260
+ .wt-sfa-b { display: inline-flex; align-items: center; gap: 5px; min-height: 44px; padding: 0 8px; font-size: 12.5px; color: var(--text2); line-height: 1; }
5261
+ .wt-sfa-b .ic { width: 14px; height: 14px; color: var(--muted); }
5262
+ .wt-sf { margin: 8px 0 0; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; overflow: clip; }
5263
+ .wt-sf > summary { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 10px; cursor: pointer; list-style: none; font-size: 12.5px; background: var(--card2); }
5264
+ .wt-sf > summary::-webkit-details-marker { display: none; }
5265
+ .wt-sf[open] > summary { border-bottom: 1px solid var(--line); }
5266
+ .wt-sf-p { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
5267
+ .wt-sf .wt-snip { margin: 0; }
5268
+ .wt-sf .wt-snip + .wt-snip { border-top: 1px dashed var(--line); }
5269
+ .wt-sf .wt-snip-h { margin: 0; padding: 4px 10px; }
5270
+ @media (pointer: fine) { .wt-sf > summary { min-height: 34px; } .wt-sfa-b { min-height: 32px; } }
5271
+ /* "changed since": a half-filled circle and the words (the stale bar uses the same glyph) */
5272
+ .wt-chg { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 1px 7px 0; box-sizing: border-box; border: 1px dashed var(--line-strong); border-radius: 6px; font-size: 11.5px; font-weight: 600; line-height: 1; color: var(--text2); }
5273
+ .wt-chg-g { flex: none; width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid currentColor; background: linear-gradient(90deg, currentColor 50%, transparent 50%); box-sizing: border-box; }
5274
+ .wt-stale { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; margin: 8px 0 0; padding: 4px 6px 4px 12px; border: 1px dashed var(--line-strong); border-radius: 10px; font-size: 13px; color: var(--text2); }
5275
+ .wt-stale-w { cursor: default; }
5276
+ .wt-upd { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 10px; font-size: 13px; font-weight: 600; color: var(--accent); line-height: 1; }
5277
+ .wt-upd .ic { width: 14px; height: 14px; }
5278
+ .wt-upd[disabled] { color: var(--muted); }
5279
+ @media (pointer: fine) { .wt-upd { min-height: 32px; } }
5280
+ /* Unified / Split: offered on a wide screen only; a quiet toggle like Slides / One page */
5281
+ .wt-dmode { display: none; }
5282
+ @media (min-width: 1000px) { .wt-dmode { display: inline-flex; } }
5283
+ .wt-r2 { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; margin: 6px 0 0; }
5284
+ .wt-r2:not(:has(.wt-spot)):not(:has(.wt-dmode:not([hidden]))) { display: none; }
5285
+ @media (max-width: 999.98px) { .wt-r2:not(:has(.wt-spot)) { display: none; } }
5286
+ /* the side-by-side drawing */
5287
+ .gd-split .gd-srow { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-width: 0; }
5288
+ .gd-half { display: grid; grid-template-columns: var(--gd-gw) 2ch minmax(0, 1fr); min-width: 0; }
5289
+ .gd-half .gd-gut { border-right: 1px solid var(--line); }
5290
+ .gd-hr { border-left: 1px solid var(--line-strong); }
5291
+ .gd-empty { background: var(--bg2); background-image: repeating-linear-gradient(135deg, transparent 0 6px, color-mix(in srgb, var(--line) 60%, transparent) 6px 7px); }
5292
+ .gd-split .gd-row { grid-template-columns: var(--gd-gw) 2ch minmax(0, 1fr); }
5293
+ .gd-split .gd-span { grid-column: 1 / 2; }
5294
+ .gd-split .gd-hunk .gd-c, .gd-split .gd-note .gd-c { grid-column: 2 / 4; }
5295
+ .gd-half.wt-mark .gd-gut { box-shadow: inset 3px 0 0 var(--text); }
5296
+ .gd-half.wt-mark-look .gd-gut { box-shadow: inset 3px 0 0 var(--yellow); }
5297
+ .wt-gd.gd-split .wt-co-in { margin-left: calc(var(--gd-gw, 3.6ch) + 2ch); }
5298
+ /* picked lines: a solid bar on the left (shape) and a tint (colour); the numbers are the handle */
5299
+ .wt-gd .gd-gut:not(.gd-span):not(:empty) { cursor: pointer; }
5300
+ .wt-gd .gd-gut:not(.gd-span):not(:empty):hover { color: var(--text); text-decoration: underline; }
5301
+ .wt-gd .wt-sel { background-image: linear-gradient(color-mix(in srgb, var(--accent) 16%, transparent), color-mix(in srgb, var(--accent) 16%, transparent)); box-shadow: inset 4px 0 0 var(--accent); }
5302
+ .wt-gd .wt-sel .gd-gut { color: var(--text); font-weight: 650; }
5303
+ .wt-gd .wt-sel-a { box-shadow: inset 4px 0 0 var(--accent), inset 0 1px 0 var(--accent); }
5304
+ .wt-gd .wt-sel-b { box-shadow: inset 4px 0 0 var(--accent), inset 0 -1px 0 var(--accent); }
5305
+ .wt-gd .wt-sel-a.wt-sel-b { box-shadow: inset 4px 0 0 var(--accent), inset 0 1px 0 var(--accent), inset 0 -1px 0 var(--accent); }
5306
+ /* touch: the numbers are 44px wide and each line 28px tall (a 44px-tall line would make the code unreadable); a wrapped line keeps its number on its first row */
5307
+ @media (pointer: coarse) { .wt-gd :is(.gd-row:not(.gd-hunk):not(.gd-note):not(.gd-gap), .gd-half) > span { padding-top: 4px; padding-bottom: 4px; } .wt-gd:not(.gd-split) .gd-row { grid-template-columns: 44px 44px 2ch minmax(0, 1fr); } .wt-gd .gd-half { grid-template-columns: 44px 2ch minmax(0, 1fr); } }
5308
+ @media (pointer: coarse) and (max-width: 600px) { .wt-snip-d .wt-gd:not(.gd-split) .gd-row { grid-template-columns: 0 44px 2ch minmax(0, 1fr); } }
5309
+ /* the chips over the ask box, and the floating ask by the newest pick */
5310
+ .wt-refs { flex: none; display: flex; flex-wrap: wrap; gap: 6px; max-width: 804px; width: calc(100% - 32px); margin: 6px auto 0; box-sizing: border-box; }
5311
+ .wt-refs[hidden] { display: none; }
5312
+ .wt-big ~ .wt-refs, .wt.wt-big .wt-refs { max-width: 1000px; }
5313
+ .wt-ref { display: inline-flex; align-items: center; height: 32px; border: 1px solid var(--line-strong); border-left: 3px solid var(--accent); border-radius: 8px; background: var(--card); min-width: 0; max-width: 100%; }
5314
+ .wt-ref-go { min-width: 0; height: 100%; padding: 1px 4px 0 8px; border: 0; background: none; color: var(--text); font-size: 12px; line-height: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
5315
+ .wt-ref-x { flex: none; display: grid; place-items: center; width: 28px; height: 100%; border: 0; background: none; color: var(--muted); cursor: pointer; }
5316
+ .wt-ref-x .ic { width: 13px; height: 13px; }
5317
+ .wt-ref-clr { min-height: 32px; padding: 0 6px; font-size: 12.5px; color: var(--text2); }
5318
+ @media (pointer: coarse) { .wt-ref { height: 44px; } .wt-ref-x { width: 44px; } .wt-ref-clr { min-height: 44px; } }
5319
+ .wt-askl { position: fixed; z-index: 40; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 1px 12px 0; box-sizing: border-box; border: 1px solid var(--line-strong); border-radius: 17px; background: var(--card); color: var(--text); font: inherit; font-size: 12.5px; font-weight: 600; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, .18); cursor: pointer; }
5320
+ .wt-askl[hidden] { display: none; }
5321
+ .wt-askl .ic { width: 14px; height: 14px; color: var(--accent); }
5322
+ @media (pointer: coarse) { .wt-askl { height: 44px; border-radius: 22px; } }
5323
+ /* Next spot */
5324
+ .wt-spot { display: inline-flex; align-items: center; gap: 6px; line-height: 1; min-height: 44px; box-sizing: border-box; }
5325
+ @media (pointer: fine) { .wt-spot { min-height: 32px; height: 32px; } }
5326
+ .wt-spot .ic { width: 15px; height: 15px; }
5327
+ .wt-spot-n { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
5328
+ .wt-gd .wt-spot-on { position: relative; box-shadow: inset 4px 0 0 var(--text), inset 0 0 0 1px var(--line-strong); }
5329
+ .wt-spot-tag { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); z-index: 1; display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 1px 7px 0; box-sizing: border-box; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--card); color: var(--text); font-family: var(--sans, inherit); font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; pointer-events: none; }
5330
+ .wt-spot-tag .ic { width: 11px; height: 11px; }
5331
+ /* the file list: folds to a slim rail, its edge drags */
5332
+ .wt-railt { flex: none; display: grid; place-items: center; width: 32px; height: 32px; margin-left: auto; border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer; }
5333
+ .wt-railt .ic { width: 16px; height: 16px; }
5334
+ .wt-railt:hover { color: var(--text); background: var(--card2); }
5335
+ .wt-2p .wt-fm-h { display: flex; align-items: center; gap: 6px; }
5336
+ .wt-rail { display: none; }
5337
+ .wt-2p.rail > .wt-rail { flex: none; display: flex; flex-direction: column; align-items: center; gap: 10px; width: 44px; padding: 10px 0; box-sizing: border-box; border-right: 1px solid var(--line); }
5338
+ .wt-2p.rail > .wt-side, .wt-2p.rail > .wt-rz { display: none; }
5339
+ .wt-rail .wt-railt { margin: 0; width: 36px; height: 36px; }
5340
+ .wt-rail-s { display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: 11px; color: var(--text2); line-height: 1; }
5341
+ .wt-rail-s .ic { width: 14px; height: 14px; color: var(--muted); }
5342
+ .wt-rail-s b { font-weight: 600; font-variant-numeric: tabular-nums; }
5343
+ .wt-rz { flex: none; width: 7px; margin: 0 -4px 0 -3px; z-index: 2; cursor: col-resize; touch-action: none; position: relative; }
5344
+ .wt-rz::after { content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: transparent; }
5345
+ .wt-rz:hover::after, .wt-rz.on::after, .wt-rz:focus-visible::after { background: var(--accent); width: 2px; left: 2px; }
5346
+ .wt-rz { outline: none; }
5347
+ @media (max-width: 1100px) { .wt.wt-big .wt-2p > .wt-rz, .wt.wt-big .wt-2p > .wt-rail { display: none; } }
5348
+ @media (max-width: 900px) { .wt.wt-fls .wt-2p > .wt-rz, .wt.wt-fls .wt-2p > .wt-rail { display: none; } .wt.wt-fls .wt-2p.rail > .wt-side { display: none; } }
5349
+ @media (prefers-reduced-motion: no-preference) { .wt-sf > summary .wt-g-chev { transition: transform .12s ease; } }
5350
+ /* the sidebar's Walk me through it: how far you got (shape and words) */
5351
+ .fs-wt-rv { display: inline-flex; align-items: center; gap: 4px; height: 18px; margin-left: 6px; padding: 1px 6px 0; box-sizing: border-box; border: 1px solid var(--line); border-radius: 9px; font-size: 11px; font-weight: 600; line-height: 1; color: var(--text2); white-space: nowrap; vertical-align: middle; }
5352
+ .fs-wt-rv .ic { width: 11px; height: 11px; color: var(--green); margin-top: -1px; }
5353
+ .fs-wt-rv-part { border-style: dashed; }