gitroots 0.6.0 → 0.6.1
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/README.md +1 -1
- package/package.json +1 -1
- package/src/runtime.js +1 -1
- package/src/session/logo.js +95 -28
- package/src/session/repl.js +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ gitroots in your terminal, as a session like Claude Code. Run `gitroots` and you
|
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
╭──────────────────────────────────────────────────────────────╮
|
|
7
|
-
│ ██ ██ ██ ██ gitroots v0.6.
|
|
7
|
+
│ ██ ██ ██ ██ gitroots v0.6.1 │
|
|
8
8
|
│ ██ ██ ██ ██ code governance and agent sessions │
|
|
9
9
|
│ ██ ██ ██ ██ Shawki Aladdin · Acme ERP (owner) · gitroots.com│
|
|
10
10
|
│ ██ ██ ██ ██ ~/work/erp · acme/erp @ main │
|
package/package.json
CHANGED
package/src/runtime.js
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
|
|
8
|
-
export const VERSION = '0.6.
|
|
8
|
+
export const VERSION = '0.6.1';
|
|
9
9
|
|
|
10
10
|
// Default download location for install.sh / gitroots update. Override with GITROOTS_DOWNLOAD_BASE.
|
|
11
11
|
export const DOWNLOAD_BASE = process.env.GITROOTS_DOWNLOAD_BASE || 'https://gitroots.com/cli';
|
package/src/session/logo.js
CHANGED
|
@@ -1,40 +1,107 @@
|
|
|
1
|
-
// The gitroots
|
|
1
|
+
// The gitroots logo as terminal pixel art: the 4×4 mark and the "gitroots" wordmark.
|
|
2
|
+
// One pixel is one column wide and half a row tall (▀ ▄ █ with fg/bg colors), so pixels are about square.
|
|
2
3
|
import { state as colorState, c, width, fit } from '../ui/ansi.js';
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
const
|
|
6
|
-
['#
|
|
7
|
-
['#
|
|
8
|
-
['#
|
|
9
|
-
['#
|
|
5
|
+
// Colors sampled from assets/logo.png.
|
|
6
|
+
const CELLS = [
|
|
7
|
+
['#B3DA44', '#97D039', '#59B238', '#20944D'],
|
|
8
|
+
['#7AC135', '#64B532', '#238B32', '#07753E'],
|
|
9
|
+
['#1D872F', '#12743D', '#096736', '#09512E'],
|
|
10
|
+
['#075833', '#0A5229', '#0A3E28', '#0A3929'],
|
|
10
11
|
];
|
|
11
|
-
const
|
|
12
|
+
const WORD = '#E3EDFC';
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
// 8 px tall glyphs: ascenders in rows 0-1, x-height 2-5, descender 6-7.
|
|
15
|
+
const GLYPHS = {
|
|
16
|
+
g: ['....', '....', '.###', '#..#', '#..#', '.###', '...#', '.##.'],
|
|
17
|
+
i: ['#', '.', '#', '#', '#', '#', '.', '.'],
|
|
18
|
+
t: ['.#.', '.#.', '###', '.#.', '.#.', '.##', '...', '...'],
|
|
19
|
+
r: ['...', '...', '#.#', '##.', '#..', '#..', '...', '...'],
|
|
20
|
+
o: ['....', '....', '.##.', '#..#', '#..#', '.##.', '....', '....'],
|
|
21
|
+
s: ['....', '....', '.###', '#...', '..##', '###.', '....', '....'],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const CELL = 2;
|
|
25
|
+
const GAP = 1;
|
|
26
|
+
const MARK = 4 * CELL + 3 * GAP; // 11 px
|
|
27
|
+
const SPACE = 4;
|
|
28
|
+
|
|
29
|
+
function canvas() {
|
|
30
|
+
const word = [...'gitroots'].reduce((rows, ch, i) => rows.map((r, y) => r + (i ? '.' : '') + GLYPHS[ch][y]), Array(8).fill(''));
|
|
31
|
+
let H = Math.max(MARK, 8);
|
|
32
|
+
if (H % 2) H += 1;
|
|
33
|
+
const W = MARK + SPACE + word[0].length;
|
|
34
|
+
const px = Array.from({ length: H }, () => Array(W).fill(null));
|
|
35
|
+
for (let r = 0; r < 4; r++) {
|
|
36
|
+
for (let col = 0; col < 4; col++) {
|
|
37
|
+
for (let y = 0; y < CELL; y++) for (let x = 0; x < CELL; x++) px[r * (CELL + GAP) + y][col * (CELL + GAP) + x] = CELLS[r][col];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const oy = Math.floor((H - 8) / 2);
|
|
41
|
+
word.forEach((row, y) => [...row].forEach((ch, x) => { if (ch === '#') px[oy + y][MARK + SPACE + x] = WORD; }));
|
|
42
|
+
return { px, W, H };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const rgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
|
|
46
|
+
|
|
47
|
+
// Nearest xterm-256 color for terminals without truecolor.
|
|
48
|
+
function x256([r, g, b]) {
|
|
49
|
+
const q = (v) => (v < 48 ? 0 : v < 115 ? 1 : Math.floor((v - 35) / 40));
|
|
50
|
+
const lv = [0, 95, 135, 175, 215, 255];
|
|
51
|
+
const [qr, qg, qb] = [q(r), q(g), q(b)];
|
|
52
|
+
const cube = 16 + 36 * qr + 6 * qg + qb;
|
|
53
|
+
const dc = (lv[qr] - r) ** 2 + (lv[qg] - g) ** 2 + (lv[qb] - b) ** 2;
|
|
54
|
+
const gray = Math.max(0, Math.min(23, Math.round(((r + g + b) / 3 - 8) / 10)));
|
|
55
|
+
const gv = 8 + gray * 10;
|
|
56
|
+
const dg = (gv - r) ** 2 + (gv - g) ** 2 + (gv - b) ** 2;
|
|
57
|
+
return dg < dc ? 232 + gray : cube;
|
|
18
58
|
}
|
|
19
59
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
60
|
+
const fg = (hex) => (colorState.truecolor ? `\x1b[38;2;${rgb(hex).join(';')}m` : `\x1b[38;5;${x256(rgb(hex))}m`);
|
|
61
|
+
const bg = (hex) => (colorState.truecolor ? `\x1b[48;2;${rgb(hex).join(';')}m` : `\x1b[48;5;${x256(rgb(hex))}m`);
|
|
62
|
+
|
|
63
|
+
let cached = null;
|
|
64
|
+
/** The logo as terminal lines (6 rows × 48 columns). */
|
|
65
|
+
export function logoLines() {
|
|
66
|
+
if (cached && cached.color === colorState.color && cached.tc === colorState.truecolor) return cached.lines;
|
|
67
|
+
const { px, W, H } = canvas();
|
|
68
|
+
const lines = [];
|
|
69
|
+
for (let y = 0; y < H; y += 2) {
|
|
70
|
+
let s = '';
|
|
71
|
+
for (let x = 0; x < W; x++) {
|
|
72
|
+
const top = px[y][x];
|
|
73
|
+
const bot = px[y + 1][x];
|
|
74
|
+
if (!colorState.color) { s += top && bot ? '█' : top ? '▀' : bot ? '▄' : ' '; continue; }
|
|
75
|
+
if (!top && !bot) s += ' ';
|
|
76
|
+
else if (top && bot && top === bot) s += `${fg(top)}█\x1b[39m`;
|
|
77
|
+
else if (top && bot) s += `${fg(top)}${bg(bot)}▀\x1b[39;49m`;
|
|
78
|
+
else if (top) s += `${fg(top)}▀\x1b[39m`;
|
|
79
|
+
else s += `${fg(bot)}▄\x1b[39m`;
|
|
80
|
+
}
|
|
81
|
+
lines.push(s);
|
|
82
|
+
}
|
|
83
|
+
cached = { color: colorState.color, tc: colorState.truecolor, lines };
|
|
84
|
+
return lines;
|
|
23
85
|
}
|
|
24
86
|
|
|
25
|
-
|
|
26
|
-
export function welcomeBox(
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
87
|
+
/** Welcome box: the logo with the info lines beside it (or under it in narrow terminals). */
|
|
88
|
+
export function welcomeBox(info, cols) {
|
|
89
|
+
const logo = logoLines();
|
|
90
|
+
const logoW = width(logo[0]);
|
|
91
|
+
const infoW = Math.max(...info.map((l) => width(l)));
|
|
92
|
+
const side = cols >= logoW + infoW + 12;
|
|
93
|
+
const inner = Math.max(logoW + 4, Math.min(cols - 2, side ? logoW + infoW + 9 : Math.max(logoW, infoW) + 6));
|
|
31
94
|
const b = (s) => c.g(s);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
95
|
+
const row = (s) => `${b('│')} ${fit(s, inner - 4)}${' '.repeat(Math.max(0, inner - 4 - width(fit(s, inner - 4))))} ${b('│')}`;
|
|
96
|
+
const out = [b(`╭${'─'.repeat(inner)}╮`), row('')];
|
|
97
|
+
if (side) {
|
|
98
|
+
const off = Math.max(0, Math.floor((logo.length - info.length) / 2));
|
|
99
|
+
for (let i = 0; i < logo.length; i++) out.push(row(`${logo[i]} ${info[i - off] || ''}`));
|
|
100
|
+
} else {
|
|
101
|
+
for (const l of logo) out.push(row(l));
|
|
102
|
+
out.push(row(''));
|
|
103
|
+
for (const l of info) out.push(row(l));
|
|
37
104
|
}
|
|
38
|
-
out.push(b(`╰${'─'.repeat(inner)}╯`));
|
|
105
|
+
out.push(row(''), b(`╰${'─'.repeat(inner)}╯`));
|
|
39
106
|
return out;
|
|
40
107
|
}
|
package/src/session/repl.js
CHANGED
|
@@ -43,8 +43,8 @@ function header(ctx) {
|
|
|
43
43
|
? `${c.b(cfg.user?.name || cfg.username)} ${c.m('·')} ${cfg.org ? `${cfg.org.name} ${c.m(`(${cfg.org.role})`)}` : c.w('no workspace · /workspace')} ${c.m(`· ${ctx.api.host}`)}`
|
|
44
44
|
: `${c.w('Not signed in')} ${c.m('· /login to connect your gitroots account')}`;
|
|
45
45
|
return welcomeBox([
|
|
46
|
-
`${c.
|
|
47
|
-
|
|
46
|
+
`${c.s(`v${VERSION}`)} ${c.m('· code governance and agent sessions')}`,
|
|
47
|
+
'',
|
|
48
48
|
who,
|
|
49
49
|
c.m(`${shortPath(process.cwd())}${repo ? ` · ${repo}${branch ? ` @ ${branch}` : ''}` : ''}`),
|
|
50
50
|
], cols);
|