@willh/copilotstatusline 0.1.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.
@@ -0,0 +1,79 @@
1
+ # Development
2
+
3
+ ## Setup
4
+
5
+ ```sh
6
+ bun install
7
+ ```
8
+
9
+ The project is written in TypeScript. Bun runs source files and tests; the published bundle targets Node.js 22 or newer.
10
+
11
+ ## Verification
12
+
13
+ ```sh
14
+ bun run lint
15
+ bun test
16
+ bun run build
17
+ bun run example
18
+ ```
19
+
20
+ `bun run lint` runs TypeScript checking before ESLint. The lint configuration is intentionally strict. Fix the implementation instead of suppressing a rule.
21
+
22
+ ## Architecture
23
+
24
+ The external Copilot payload is parsed into `NormalizedCopilotStatus` before rendering. This boundary prevents payload aliases and nullable fields from spreading through widget logic.
25
+
26
+ Formatter settings and Copilot CLI settings are separate:
27
+
28
+ - formatter settings control lines, widgets, colors, Powerline, and local command behavior;
29
+ - Copilot settings control whether and how Copilot invokes the formatter.
30
+
31
+ Both settings writers use a temporary file and atomic rename. Copilot settings also receive timestamped backups because the file belongs to another application.
32
+
33
+ ## Adding a payload field
34
+
35
+ 1. Add the known optional field to `CopilotStatusSchema`.
36
+ 2. Normalize it in `normalizeCopilotStatus`.
37
+ 3. Add a widget type and catalog entry only if the value is useful independently.
38
+ 4. Render absence as `null` instead of a fabricated fallback.
39
+ 5. Add payload and rendering tests.
40
+
41
+ Keep the top-level and nested schemas loose so future Copilot fields do not break existing installations.
42
+
43
+ ## Adding a widget
44
+
45
+ 1. Add its type to `WIDGET_TYPES` in `src/types/Settings.ts`.
46
+ 2. Add metadata to `WIDGET_CATALOG` in `src/widgets/catalog.ts`.
47
+ 3. Add rendering behavior to `renderWidget`.
48
+ 4. Add a focused renderer or widget test.
49
+
50
+ Subprocess widgets must suppress stderr, use a short timeout, work with an absent command, and avoid filesystem mutations. Git and Jujutsu values should go through the existing TTL cache.
51
+
52
+ ## Integration testing
53
+
54
+ Use a temporary Copilot home so local user settings are never touched:
55
+
56
+ ```sh
57
+ temporary_home="$(mktemp -d)"
58
+ COPILOT_HOME="$temporary_home" bun run src/copilotstatusline.ts --install global
59
+ COPILOT_HOME="$temporary_home" bun run src/copilotstatusline.ts --check
60
+ COPILOT_HOME="$temporary_home" bun run src/copilotstatusline.ts --uninstall
61
+ ```
62
+
63
+ For custom formatter settings:
64
+
65
+ ```sh
66
+ temporary_config="$(mktemp)"
67
+ rm "$temporary_config"
68
+ COPILOT_HOME="$temporary_home" bun run src/copilotstatusline.ts \
69
+ --config "$temporary_config" --install global
70
+ ```
71
+
72
+ ## Build
73
+
74
+ ```sh
75
+ bun run build
76
+ node dist/copilotstatusline.js --version
77
+ ```
78
+
79
+ The postbuild script replaces the `__PACKAGE_VERSION__` placeholder from `package.json`. The bundle must remain executable as the npm `copilotstatusline` binary.
package/docs/USAGE.md ADDED
@@ -0,0 +1,135 @@
1
+ # Usage
2
+
3
+ ## Runtime model
4
+
5
+ GitHub Copilot CLI executes the configured shell command and sends a JSON object on stdin. `copilotstatusline` validates the known fields, normalizes aliases, loads formatter settings, and writes rendered lines to stdout.
6
+
7
+ Unknown payload fields are accepted for forward compatibility. Missing optional fields hide the corresponding widgets. Invalid known field types fail the invocation with a concise stderr message and a nonzero exit code.
8
+
9
+ ## Installation
10
+
11
+ Interactive installation:
12
+
13
+ ```sh
14
+ npx -y copilotstatusline@latest
15
+ ```
16
+
17
+ Non-interactive installation:
18
+
19
+ ```sh
20
+ npx -y copilotstatusline@latest --install npm
21
+ bunx -y copilotstatusline@latest --install bunx
22
+ copilotstatusline --install global
23
+ ```
24
+
25
+ The accepted install modes are `npm`, `bunx`, and `global`. Installation writes only to `$COPILOT_HOME/settings.json`, with `~/.copilot/settings.json` as the fallback. Existing files are backed up as `settings.json.bak.<timestamp>` before replacement.
26
+
27
+ The installer:
28
+
29
+ - preserves unrelated root and footer keys;
30
+ - sets `statusLine.type` to `command`;
31
+ - sets status-line padding to zero;
32
+ - enables `footer.showCustom`;
33
+ - refuses an installed Copilot CLI version older than 1.0.52.
34
+
35
+ If the `copilot` executable cannot be resolved, installation still writes the configuration. This supports configuring an environment before Copilot CLI is added to `PATH`.
36
+
37
+ ## Uninstallation safety
38
+
39
+ ```sh
40
+ copilotstatusline --uninstall
41
+ ```
42
+
43
+ Uninstallation removes `statusLine` only when its command is recognized as belonging to `copilotstatusline`. A different custom status-line command is left untouched.
44
+
45
+ ## Formatter settings
46
+
47
+ Default path:
48
+
49
+ ```text
50
+ ~/.config/copilotstatusline/settings.json
51
+ ```
52
+
53
+ `XDG_CONFIG_HOME` changes the Unix root. `%APPDATA%` is used on Windows. A custom path can be selected with:
54
+
55
+ ```sh
56
+ copilotstatusline --config /absolute/path/settings.json
57
+ ```
58
+
59
+ Combine the flag with installation so Copilot always invokes the same file:
60
+
61
+ ```sh
62
+ copilotstatusline --config /absolute/path/settings.json --install global
63
+ ```
64
+
65
+ The settings schema is versioned independently of Copilot settings:
66
+
67
+ ```json
68
+ {
69
+ "version": 1,
70
+ "lines": [
71
+ [
72
+ {
73
+ "id": "model",
74
+ "type": "model",
75
+ "color": "cyan",
76
+ "backgroundColor": "none",
77
+ "bold": false,
78
+ "raw": false,
79
+ "prefix": "",
80
+ "suffix": "",
81
+ "merge": false,
82
+ "hideWhenZero": false
83
+ }
84
+ ]
85
+ ],
86
+ "defaultSeparator": " · ",
87
+ "colorLevel": 2,
88
+ "powerline": {
89
+ "enabled": false,
90
+ "separator": ""
91
+ },
92
+ "gitCacheTtlSeconds": 5
93
+ }
94
+ ```
95
+
96
+ `colorLevel` accepts zero through three. Zero disables ANSI styling. The current renderer uses ANSI 16-color names; values above zero enable them.
97
+
98
+ ## Widget configuration
99
+
100
+ Every widget has an `id`, `type`, foreground and background colors, bold and raw-value flags, prefix and suffix text, merge behavior, and an optional zero-hiding flag.
101
+
102
+ Additional widget fields:
103
+
104
+ - `custom-text`: set `value`.
105
+ - `custom-command`: set `command`.
106
+ - `separator`: set `value`.
107
+ - `flex`: no additional value; it consumes remaining terminal width.
108
+
109
+ Custom commands execute through the local shell with a 500 ms timeout. Only the first output line is rendered. Store only trusted commands in the settings file.
110
+
111
+ ## Payload fields
112
+
113
+ The normalized widgets currently use:
114
+
115
+ - session: `session_id`, `session_name`, `cwd`, `workspace`, and `version`;
116
+ - model: string or object `model`, `modelName`, `current_model`, `reasoning_effort`, and `effort.level`;
117
+ - context: cumulative input, output, cache read/write, reasoning and total tokens, last-call tokens, current context, displayed limit, and used percentage;
118
+ - cost: API duration, total duration, premium requests, and added/removed lines;
119
+ - permission state: `allow_all`.
120
+
121
+ ## Diagnostics
122
+
123
+ Inspect integration status:
124
+
125
+ ```sh
126
+ copilotstatusline --check
127
+ ```
128
+
129
+ Test rendering without changing Copilot settings:
130
+
131
+ ```sh
132
+ bun run example
133
+ ```
134
+
135
+ Warnings about malformed formatter settings go to stderr. Status-line content remains on stdout so Copilot does not receive diagnostics as display content.
@@ -0,0 +1,54 @@
1
+ # Windows
2
+
3
+ ## Requirements
4
+
5
+ - GitHub Copilot CLI 1.0.52 or newer
6
+ - Node.js 22 or newer
7
+ - Windows Terminal or another terminal with ANSI support
8
+
9
+ ## Paths
10
+
11
+ Copilot user settings:
12
+
13
+ ```text
14
+ %COPILOT_HOME%\settings.json
15
+ ```
16
+
17
+ When `COPILOT_HOME` is not set, the fallback is the `.copilot` directory in the current user's home directory.
18
+
19
+ Formatter settings:
20
+
21
+ ```text
22
+ %APPDATA%\copilotstatusline\settings.json
23
+ ```
24
+
25
+ `--config <path>` overrides the formatter settings path. Installing with the same command writes the absolute Windows path into Copilot settings.
26
+
27
+ ## Installation
28
+
29
+ PowerShell:
30
+
31
+ ```powershell
32
+ npx -y copilotstatusline@latest --install npm
33
+ ```
34
+
35
+ If a global package is installed:
36
+
37
+ ```powershell
38
+ copilotstatusline --install global
39
+ ```
40
+
41
+ Restart Copilot CLI after installation.
42
+
43
+ ## Powerline
44
+
45
+ The default Powerline separator requires a font containing U+E0B0. If the glyph is missing, disable Powerline in the TUI or install a compatible terminal font and select it in the terminal profile.
46
+
47
+ ## Diagnostics
48
+
49
+ ```powershell
50
+ copilotstatusline --check
51
+ Get-Content $env:COPILOT_HOME\settings.json
52
+ ```
53
+
54
+ All helper subprocesses are launched with hidden Windows process windows. Missing Git or Jujutsu executables cause only the related widgets to be omitted.
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@willh/copilotstatusline",
3
+ "version": "0.1.0",
4
+ "bugs": {
5
+ "url": "https://github.com/sirmalloc/copilotstatusline/issues"
6
+ },
7
+ "description": "A customizable status line formatter for GitHub Copilot CLI",
8
+ "main": "./dist/copilotstatusline.js",
9
+ "module": "./dist/copilotstatusline.js",
10
+ "type": "module",
11
+ "bin": {
12
+ "copilotstatusline": "./dist/copilotstatusline.js"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/copilotstatusline.js",
17
+ "default": "./dist/copilotstatusline.js"
18
+ },
19
+ "./package.json": "./package.json"
20
+ },
21
+ "files": [
22
+ "dist/",
23
+ "docs/",
24
+ "NOTICE"
25
+ ],
26
+ "scripts": {
27
+ "start": "bun run src/copilotstatusline.ts",
28
+ "build": "rm -rf dist/* && bun build src/copilotstatusline.ts --target=node --outfile=dist/copilotstatusline.js --target-version=22",
29
+ "postbuild": "bun run scripts/replace-version.ts",
30
+ "example": "bun run src/copilotstatusline.ts < scripts/payload.example.json",
31
+ "prepublishOnly": "bun run build",
32
+ "lint": "bun tsc --noEmit && eslint . --config eslint.config.js --max-warnings=0",
33
+ "lint:fix": "bun tsc --noEmit && eslint . --config eslint.config.js --max-warnings=0 --fix",
34
+ "docs": "typedoc",
35
+ "docs:clean": "rm -rf typedoc"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^10.0.1",
39
+ "@stylistic/eslint-plugin": "^5.2.3",
40
+ "@types/bun": "latest",
41
+ "@types/react": "^19.1.10",
42
+ "eslint": "^10.0.0",
43
+ "eslint-import-resolver-typescript": "^4.4.4",
44
+ "eslint-plugin-import-newlines": "^2.0.0",
45
+ "eslint-plugin-import-x": "^4.16.2",
46
+ "eslint-plugin-react": "^7.37.5",
47
+ "eslint-plugin-react-hooks": "^7.0.1",
48
+ "globals": "^17.3.0",
49
+ "ink": "6.2.0",
50
+ "ink-select-input": "^6.2.0",
51
+ "ink-text-input": "^6.0.0",
52
+ "react": "19.2.7",
53
+ "slice-ansi": "^7.1.2",
54
+ "string-width": "^8.1.0",
55
+ "strip-ansi": "^7.1.0",
56
+ "typedoc": "^0.28.12",
57
+ "typescript": "^6.0.2",
58
+ "typescript-eslint": "^8.39.1",
59
+ "vitest": "^4.0.18",
60
+ "zod": "^4.0.17"
61
+ },
62
+ "keywords": [
63
+ "github-copilot",
64
+ "copilot-cli",
65
+ "cli",
66
+ "status-line",
67
+ "terminal"
68
+ ],
69
+ "author": "",
70
+ "license": "MIT",
71
+ "repository": {
72
+ "type": "git",
73
+ "url": "git+https://github.com/sirmalloc/copilotstatusline.git"
74
+ },
75
+ "engines": {
76
+ "node": ">=22.0.0"
77
+ },
78
+ "trustedDependencies": [
79
+ "unrs-resolver"
80
+ ]
81
+ }