dev-cockpit 0.3.3 → 0.3.4

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 +1 @@
1
- {"version":3,"file":"Health.d.ts","sourceRoot":"","sources":["../../../src/cockpit/panes/Health.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,wBAAgB,MAAM,IAAI,KAAK,CAAC,YAAY,CAgE3C"}
1
+ {"version":3,"file":"Health.d.ts","sourceRoot":"","sources":["../../../src/cockpit/panes/Health.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AA+BvC,wBAAgB,MAAM,IAAI,KAAK,CAAC,YAAY,CAqE3C"}
@@ -60,6 +60,12 @@ export interface CockpitState {
60
60
  actions: ActionConfig[];
61
61
  commandFilter: string;
62
62
  selectedActionIndex: number;
63
+ /**
64
+ * Normalised `config.keybindings`. Maps a single key character to the
65
+ * ordered list of health check ids that should fire on press. Empty when
66
+ * the user hasn't declared any explicit bindings.
67
+ */
68
+ keybindings: Record<string, string[]>;
63
69
  health: HealthStatus[];
64
70
  previousHealth: HealthStatus[];
65
71
  selectedHealthIndex: number;
@@ -97,6 +103,7 @@ export interface CockpitState {
97
103
  } | null) => void;
98
104
  setHelpConfig: (config: HelpConfig) => void;
99
105
  setFocus: (focus: FocusTarget) => void;
106
+ setKeybindings: (bindings: Record<string, string[]>) => void;
100
107
  }
101
108
  export declare const cockpitStore: import("zustand/vanilla").StoreApi<CockpitState>;
102
109
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cockpit/state/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/cockpit/state/store.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAA6C,MAAM,kBAAkB,CAAC;AAqB3F,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2V5E"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAA6C,MAAM,kBAAkB,CAAC;AAsB3F,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6V5E"}
@@ -275,6 +275,7 @@ export declare const BaseCockpitConfigSchema: z.ZodObject<{
275
275
  }, {
276
276
  packageDirs?: string[] | undefined;
277
277
  }>>>;
278
+ keybindings: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>>>;
278
279
  /** Which pane the cockpit lands on when it boots. Profile may override. */
279
280
  defaultPane: z.ZodDefault<z.ZodOptional<z.ZodEnum<["repos", "output", "health", "help"]>>>;
280
281
  /** Named keystroke-bound shell commands surfaced via the `:` palette. */
@@ -393,6 +394,7 @@ export declare const BaseCockpitConfigSchema: z.ZodObject<{
393
394
  composer: {
394
395
  packageDirs: string[];
395
396
  };
397
+ keybindings: Record<string, string | string[]>;
396
398
  defaultPane: "repos" | "health" | "help" | "output";
397
399
  actions: {
398
400
  id: string;
@@ -490,6 +492,7 @@ export declare const BaseCockpitConfigSchema: z.ZodObject<{
490
492
  composer?: {
491
493
  packageDirs?: string[] | undefined;
492
494
  } | undefined;
495
+ keybindings?: Record<string, string | string[]> | undefined;
493
496
  defaultPane?: "repos" | "health" | "help" | "output" | undefined;
494
497
  actions?: {
495
498
  id: string;
@@ -502,6 +505,12 @@ export declare const BaseCockpitConfigSchema: z.ZodObject<{
502
505
  profile?: Record<string, unknown> | undefined;
503
506
  }>;
504
507
  export type BaseCockpitConfig = z.infer<typeof BaseCockpitConfigSchema>;
508
+ /**
509
+ * Normalise the freely-typed `keybindings` map (each value may be a single
510
+ * id string or a list) into a uniform `Record<string, string[]>`. Empty
511
+ * strings/arrays are dropped so dispatchers never iterate noise.
512
+ */
513
+ export declare function normaliseKeybindings(raw: BaseCockpitConfig['keybindings'] | undefined): Record<string, string[]>;
505
514
  export declare class ConfigVersionError extends Error {
506
515
  readonly filePath: string;
507
516
  readonly found: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,mFAAmF;AACnF,eAAO,MAAM,cAAc,IAAI,CAAC;AA8JhC,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAlHlC;;;;;;;eAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2FH;;;;;;WAMG;;QAEH,iDAAiD;;QAEjD,gEAAgE;;;;;;;;;;;;QArBhE;;;;;;WAMG;;;;;;;IAwCH,2EAA2E;;IAE3E,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEzE;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,QAAQ,EAAE,MAAM;aAChB,KAAK,EAAE,OAAO;aACd,SAAS,EAAE,MAAM;gBAFjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM;CAOpC;AAED,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,QAAQ,EAAE,MAAM;aAChB,KAAK,EAAE,OAAO;gBADd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO;CAKjC;AAID,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC7C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,iBAAiB,CA0C5F"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,mFAAmF;AACnF,eAAO,MAAM,cAAc,IAAI,CAAC;AA6KhC,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAjIlC;;;;;;;eAOG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0GH;;;;;;WAMG;;QAEH,iDAAiD;;QAEjD,gEAAgE;;;;;;;;;;;;QApChE;;;;;;WAMG;;;;;;;;IAwDH,2EAA2E;;IAE3E,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEzE;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,iBAAiB,CAAC,aAAa,CAAC,GAAG,SAAS,GAChD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAS1B;AAID,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,QAAQ,EAAE,MAAM;aAChB,KAAK,EAAE,OAAO;aACd,SAAS,EAAE,MAAM;gBAFjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM;CAOpC;AAED,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,QAAQ,EAAE,MAAM;aAChB,KAAK,EAAE,OAAO;gBADd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO;CAKjC;AAID,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC7C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,iBAAiB,CA0C5F"}
@@ -1,6 +1,20 @@
1
1
  import type { HealthCheck, HealthContext, Remediation } from './types.js';
2
2
  export type RemediationKey = string;
3
- export declare function runRemediation(key: RemediationKey, checks: HealthCheck[], ctx: HealthContext, workspaceRoot: string): Promise<void>;
3
+ /**
4
+ * Resolve which health checks should fire for a given keypress. Order:
5
+ * 1. `keybindings[key]` — explicit list of ids. Each found id contributes
6
+ * a check in declared order. Unknown ids are silently dropped (a warn
7
+ * log would be nice but isn't free in this hot path).
8
+ * 2. Fallback: scan `checks` for `remediation.key === key`. Single match.
9
+ *
10
+ * Returns an empty array when nothing matches.
11
+ */
12
+ export declare function findChecksByKey(key: RemediationKey, checks: HealthCheck[], keybindings?: Record<string, string[]>): HealthCheck[];
13
+ export declare function runRemediation(key: RemediationKey, checks: HealthCheck[], ctx: HealthContext, workspaceRoot: string, keybindings?: Record<string, string[]>): Promise<void>;
14
+ /**
15
+ * @deprecated kept for callers that need single-target lookups. Prefer
16
+ * {@link findChecksByKey} which returns the full ordered list.
17
+ */
4
18
  export declare function findRemediation(key: RemediationKey, checks: HealthCheck[]): HealthCheck | undefined;
5
19
  export declare function dispatchRemediation(remediation: Remediation, ctx: HealthContext, workspaceRoot: string, sourceId: string): Promise<void>;
6
20
  //# sourceMappingURL=remediations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/health/remediations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,WAAW,GAAG,SAAS,CAEzB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf"}
1
+ {"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/health/remediations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,WAAW,EAAE,CASf;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,WAAW,GAAG,SAAS,CAEzB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -32,6 +32,13 @@ export interface UseHealthOptions {
32
32
  * Useful for tests + advanced consumers who want to peek.
33
33
  */
34
34
  onResults?: (statuses: HealthStatus[]) => void;
35
+ /**
36
+ * `key → [check-id, ...]` map normalised from `config.keybindings`. When a
37
+ * pressed key is listed here, every referenced check's remediation fires
38
+ * in order (multi-fire). Otherwise dispatch falls back to scanning
39
+ * `remediation.key` on each check.
40
+ */
41
+ keybindings?: Record<string, string[]>;
35
42
  }
36
43
  export interface UseHealthHandle {
37
44
  runRemediation: (key: string) => RemediationDispatch | null;
@@ -1 +1 @@
1
- {"version":3,"file":"useHealth.d.ts","sourceRoot":"","sources":["../../src/health/useHealth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhF,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,oCAAoC;IACpC,aAAa,EAAE,mBAAmB,CAAC;IACnC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACzE;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,IAAI,CAAC;CAC7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,eAAe,GAAG,IAAI,CA4FpF"}
1
+ {"version":3,"file":"useHealth.d.ts","sourceRoot":"","sources":["../../src/health/useHealth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AASrD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhF,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,oCAAoC;IACpC,aAAa,EAAE,mBAAmB,CAAC;IACnC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACzE;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAC/C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,IAAI,CAAC;CAC7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,eAAe,GAAG,IAAI,CAqGpF"}
package/dist/index.js CHANGED
@@ -15378,18 +15378,18 @@ var require_react_jsx_runtime_development = __commonJS({
15378
15378
  function isValidElement(object) {
15379
15379
  return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
15380
15380
  }
15381
- var React7 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React7.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
15381
+ var React8 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React8.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
15382
15382
  return null;
15383
15383
  };
15384
- React7 = {
15384
+ React8 = {
15385
15385
  react_stack_bottom_frame: function(callStackForError) {
15386
15386
  return callStackForError();
15387
15387
  }
15388
15388
  };
15389
15389
  var specialPropKeyWarningShown;
15390
15390
  var didWarnAboutElementRef = {};
15391
- var unknownOwnerDebugStack = React7.react_stack_bottom_frame.bind(
15392
- React7,
15391
+ var unknownOwnerDebugStack = React8.react_stack_bottom_frame.bind(
15392
+ React8,
15393
15393
  UnknownOwner
15394
15394
  )();
15395
15395
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -84007,6 +84007,7 @@ var ComposerSettingsSchema = external_exports.object({
84007
84007
  */
84008
84008
  packageDirs: external_exports.array(external_exports.string()).optional().default(["."])
84009
84009
  });
84010
+ var KeybindingsSchema = external_exports.record(external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]));
84010
84011
  var MountSettingsSchema = external_exports.object({
84011
84012
  /**
84012
84013
  * Override path for the generated docker-compose overlay. When unset
@@ -84040,6 +84041,7 @@ var BaseCockpitConfigSchema = external_exports.object({
84040
84041
  manifestFile: "mount.manifest.json"
84041
84042
  }),
84042
84043
  composer: ComposerSettingsSchema.optional().default({ packageDirs: ["."] }),
84044
+ keybindings: KeybindingsSchema.optional().default({}),
84043
84045
  /** Which pane the cockpit lands on when it boots. Profile may override. */
84044
84046
  defaultPane: external_exports.enum(["repos", "output", "health", "help"]).optional().default("repos"),
84045
84047
  /** Named keystroke-bound shell commands surfaced via the `:` palette. */
@@ -84051,6 +84053,16 @@ var BaseCockpitConfigSchema = external_exports.object({
84051
84053
  */
84052
84054
  profile: external_exports.record(external_exports.unknown()).optional().default({})
84053
84055
  });
84056
+ function normaliseKeybindings(raw) {
84057
+ const out = {};
84058
+ if (!raw) return out;
84059
+ for (const [key, value] of Object.entries(raw)) {
84060
+ const ids = Array.isArray(value) ? value : [value];
84061
+ const clean = ids.filter((s) => typeof s === "string" && s.length > 0);
84062
+ if (clean.length > 0) out[key] = clean;
84063
+ }
84064
+ return out;
84065
+ }
84054
84066
  var ConfigVersionError = class extends Error {
84055
84067
  constructor(filePath, found, supported) {
84056
84068
  super(
@@ -84166,7 +84178,7 @@ var {
84166
84178
  } = import_index.default;
84167
84179
 
84168
84180
  // src/cockpit/Cockpit.tsx
84169
- var import_react8 = __toESM(require_react(), 1);
84181
+ var import_react9 = __toESM(require_react(), 1);
84170
84182
 
84171
84183
  // src/cockpit/hooks/useCockpitStore.ts
84172
84184
  var import_react = __toESM(require_react(), 1);
@@ -84213,6 +84225,7 @@ var cockpitStore = createStore()((set, get2) => ({
84213
84225
  output: [],
84214
84226
  outputFilter: {},
84215
84227
  knownSources: [],
84228
+ keybindings: {},
84216
84229
  activeModal: null,
84217
84230
  actions: [],
84218
84231
  commandFilter: "",
@@ -84306,6 +84319,7 @@ var cockpitStore = createStore()((set, get2) => ({
84306
84319
  setActiveRemediation: (remediation) => set({ activeRemediation: remediation }),
84307
84320
  setHelpConfig: (config) => set({ helpConfig: config }),
84308
84321
  setFocus: (focus) => set({ focus }),
84322
+ setKeybindings: (bindings) => set({ keybindings: bindings }),
84309
84323
  setActions: (actions) => set({ actions }),
84310
84324
  setCommandFilter: (filter) => set((state) => {
84311
84325
  const filtered = filterActions(state.actions, filter);
@@ -84678,7 +84692,17 @@ function RecentErrorRow({ err }) {
84678
84692
  }
84679
84693
 
84680
84694
  // src/cockpit/panes/Health.tsx
84695
+ var import_react4 = __toESM(require_react(), 1);
84681
84696
  var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
84697
+ function buildReverseKeybindings(bindings) {
84698
+ const out = {};
84699
+ for (const [key, ids] of Object.entries(bindings)) {
84700
+ for (const id of ids) {
84701
+ if (!(id in out)) out[id] = key;
84702
+ }
84703
+ }
84704
+ return out;
84705
+ }
84682
84706
  var SEVERITY_GLYPH = { ok: "\u2713", warn: "\u26A0", error: "\u2717" };
84683
84707
  var SEVERITY_COLOR = {
84684
84708
  ok: "green",
@@ -84692,6 +84716,8 @@ function Health() {
84692
84716
  const focus = useCockpitStore((s) => s.focus);
84693
84717
  const notificationsEnabledSession = useCockpitStore((s) => s.notificationsEnabledSession);
84694
84718
  const activeRemediation = useCockpitStore((s) => s.activeRemediation);
84719
+ const keybindings = useCockpitStore((s) => s.keybindings);
84720
+ const idToKey = (0, import_react4.useMemo)(() => buildReverseKeybindings(keybindings), [keybindings]);
84695
84721
  const isFocused = focus === "health";
84696
84722
  if (health.length === 0) {
84697
84723
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "running health checks\u2026" }) });
@@ -84708,7 +84734,8 @@ function Health() {
84708
84734
  const isRunning = activeRemediation?.healthId === item.id;
84709
84735
  const glyph = isRunning ? "\u2026" : SEVERITY_GLYPH[item.severity] ?? "?";
84710
84736
  const color = isRunning ? "yellow" : SEVERITY_COLOR[item.severity] ?? "white";
84711
- const remKey = item.remediationKey ? ` [${item.remediationKey}]` : "";
84737
+ const displayKey = idToKey[item.id] ?? item.remediationKey ?? null;
84738
+ const remKey = displayKey ? ` [${displayKey}]` : "";
84712
84739
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", children: [
84713
84740
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { children: [
84714
84741
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: isSelected ? "cyan" : void 0, children: isSelected ? "\u25B6 " : " " }),
@@ -84731,7 +84758,7 @@ function Health() {
84731
84758
  }
84732
84759
 
84733
84760
  // src/cockpit/panes/Help.tsx
84734
- var import_react4 = __toESM(require_react(), 1);
84761
+ var import_react5 = __toESM(require_react(), 1);
84735
84762
 
84736
84763
  // src/cockpit/help/loader.ts
84737
84764
  import fs5 from "node:fs";
@@ -87542,7 +87569,7 @@ function Help2() {
87542
87569
  const helpConfig = useCockpitStore((s) => s.helpConfig);
87543
87570
  const { stdout } = use_stdout_default();
87544
87571
  const isActive = focus === "help";
87545
- const initial = (0, import_react4.useMemo)(() => {
87572
+ const initial = (0, import_react5.useMemo)(() => {
87546
87573
  const result = loadHelpPages({
87547
87574
  sources: helpConfig.sources,
87548
87575
  defaultPage: helpConfig.defaultPage
@@ -87551,17 +87578,17 @@ function Help2() {
87551
87578
  return { pages: [FALLBACK_PAGE], defaultIndex: 0 };
87552
87579
  }, [helpConfig.sources, helpConfig.defaultPage]);
87553
87580
  const pages = initial.pages;
87554
- const [pageIndex, setPageIndex] = (0, import_react4.useState)(initial.defaultIndex);
87555
- const [scrollOffset, setScrollOffset] = (0, import_react4.useState)(0);
87556
- const lastPageIndexRef = (0, import_react4.useRef)(pageIndex);
87557
- (0, import_react4.useEffect)(() => {
87581
+ const [pageIndex, setPageIndex] = (0, import_react5.useState)(initial.defaultIndex);
87582
+ const [scrollOffset, setScrollOffset] = (0, import_react5.useState)(0);
87583
+ const lastPageIndexRef = (0, import_react5.useRef)(pageIndex);
87584
+ (0, import_react5.useEffect)(() => {
87558
87585
  if (lastPageIndexRef.current !== pageIndex) {
87559
87586
  lastPageIndexRef.current = pageIndex;
87560
87587
  setScrollOffset(0);
87561
87588
  }
87562
87589
  }, [pageIndex]);
87563
87590
  const activePage = pages[pageIndex] ?? pages[0];
87564
- const renderedLines = (0, import_react4.useMemo)(
87591
+ const renderedLines = (0, import_react5.useMemo)(
87565
87592
  () => renderMarkdown(activePage.body).split("\n"),
87566
87593
  [activePage.body]
87567
87594
  );
@@ -87689,20 +87716,20 @@ function Footer({ legends } = {}) {
87689
87716
  }
87690
87717
 
87691
87718
  // src/cockpit/panes/FilterModal.tsx
87692
- var import_react5 = __toESM(require_react(), 1);
87719
+ var import_react6 = __toESM(require_react(), 1);
87693
87720
  var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
87694
87721
  var SEVERITIES = [void 0, "info", "warn", "error"];
87695
87722
  function FilterModal() {
87696
87723
  const outputFilter = useCockpitStore((s) => s.outputFilter);
87697
87724
  const knownSources = useCockpitStore((s) => s.knownSources);
87698
- const [severityDraft, setSeverityDraft] = (0, import_react5.useState)(
87725
+ const [severityDraft, setSeverityDraft] = (0, import_react6.useState)(
87699
87726
  outputFilter.severity
87700
87727
  );
87701
87728
  const initialSelected = new Set(
87702
87729
  outputFilter.sources && outputFilter.sources.length > 0 ? outputFilter.sources : knownSources
87703
87730
  );
87704
- const [selectedSources, setSelectedSources] = (0, import_react5.useState)(initialSelected);
87705
- const [cursor, setCursor] = (0, import_react5.useState)(0);
87731
+ const [selectedSources, setSelectedSources] = (0, import_react6.useState)(initialSelected);
87732
+ const [cursor, setCursor] = (0, import_react6.useState)(0);
87706
87733
  const sources = knownSources;
87707
87734
  const hasSources = sources.length > 0;
87708
87735
  use_input_default((input, key) => {
@@ -87787,11 +87814,11 @@ function FilterModal() {
87787
87814
  }
87788
87815
 
87789
87816
  // src/cockpit/panes/SearchModal.tsx
87790
- var import_react6 = __toESM(require_react(), 1);
87817
+ var import_react7 = __toESM(require_react(), 1);
87791
87818
  var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
87792
87819
  function SearchModal() {
87793
87820
  const outputFilter = useCockpitStore((s) => s.outputFilter);
87794
- const [query, setQuery] = (0, import_react6.useState)(outputFilter.search ?? "");
87821
+ const [query, setQuery] = (0, import_react7.useState)(outputFilter.search ?? "");
87795
87822
  use_input_default((input, key) => {
87796
87823
  if (key.escape) {
87797
87824
  cockpitStore.getState().setActiveModal(null);
@@ -88026,7 +88053,7 @@ function useGlobalKeys(opts) {
88026
88053
  }
88027
88054
 
88028
88055
  // src/health/useHealth.ts
88029
- var import_react7 = __toESM(require_react(), 1);
88056
+ var import_react8 = __toESM(require_react(), 1);
88030
88057
 
88031
88058
  // src/health/scheduler.ts
88032
88059
  import path9 from "node:path";
@@ -88159,10 +88186,21 @@ var HealthScheduler = class {
88159
88186
  };
88160
88187
 
88161
88188
  // src/health/remediations.ts
88162
- async function runRemediation(key, checks, ctx, workspaceRoot) {
88163
- const check = checks.find((c3) => c3.remediation.key === key);
88164
- if (!check) return;
88165
- await dispatchRemediation(check.remediation, ctx, workspaceRoot, check.id);
88189
+ function findChecksByKey(key, checks, keybindings) {
88190
+ const ids = keybindings?.[key];
88191
+ if (ids && ids.length > 0) {
88192
+ return ids.map((id) => checks.find((c4) => c4.id === id)).filter((c4) => Boolean(c4));
88193
+ }
88194
+ const c3 = checks.find((c4) => c4.remediation.key === key);
88195
+ return c3 ? [c3] : [];
88196
+ }
88197
+ async function runRemediation(key, checks, ctx, workspaceRoot, keybindings) {
88198
+ const matched = findChecksByKey(key, checks, keybindings);
88199
+ await Promise.all(
88200
+ matched.map(
88201
+ (check) => dispatchRemediation(check.remediation, ctx, workspaceRoot, check.id)
88202
+ )
88203
+ );
88166
88204
  }
88167
88205
  function findRemediation(key, checks) {
88168
88206
  return checks.find((c3) => c3.remediation.key === key);
@@ -88449,23 +88487,23 @@ function buildHealthContext(workspaceRoot, appendOutput) {
88449
88487
 
88450
88488
  // src/health/useHealth.ts
88451
88489
  function useHealth(opts) {
88452
- const checks = (0, import_react7.useMemo)(() => {
88490
+ const checks = (0, import_react8.useMemo)(() => {
88453
88491
  if (!opts) return [];
88454
88492
  return buildHealthRegistry({
88455
88493
  profileChecks: opts.profileChecks,
88456
88494
  configEntries: opts.configEntries
88457
88495
  });
88458
88496
  }, [opts]);
88459
- const checksRef = (0, import_react7.useRef)(checks);
88460
- const ctxRef = (0, import_react7.useRef)(opts?.ctx);
88461
- const optsRef = (0, import_react7.useRef)(opts);
88462
- const schedulerRef = (0, import_react7.useRef)(null);
88463
- (0, import_react7.useEffect)(() => {
88497
+ const checksRef = (0, import_react8.useRef)(checks);
88498
+ const ctxRef = (0, import_react8.useRef)(opts?.ctx);
88499
+ const optsRef = (0, import_react8.useRef)(opts);
88500
+ const schedulerRef = (0, import_react8.useRef)(null);
88501
+ (0, import_react8.useEffect)(() => {
88464
88502
  checksRef.current = checks;
88465
88503
  ctxRef.current = opts?.ctx;
88466
88504
  optsRef.current = opts;
88467
88505
  }, [checks, opts]);
88468
- (0, import_react7.useEffect)(() => {
88506
+ (0, import_react8.useEffect)(() => {
88469
88507
  if (!opts) return;
88470
88508
  if (checks.length === 0) return;
88471
88509
  const scheduler3 = new HealthScheduler({
@@ -88504,21 +88542,25 @@ function useHealth(opts) {
88504
88542
  runRemediation: (key) => {
88505
88543
  const list3 = checksRef.current;
88506
88544
  const ctx = ctxRef.current ?? buildDefaultCtx(optsRef.current?.workspaceRoot ?? ".");
88507
- const check = list3.find((c3) => c3.remediation.key === key);
88508
- if (!check) return null;
88545
+ const keybindings = optsRef.current?.keybindings;
88546
+ const matched = findChecksByKey(key, list3, keybindings);
88547
+ if (matched.length === 0) return null;
88548
+ const first = matched[0];
88549
+ const banner = matched.length === 1 ? first.remediation.label : `${matched.length} remediations`;
88509
88550
  const promise = runRemediation(
88510
88551
  key,
88511
88552
  list3,
88512
88553
  ctx,
88513
- optsRef.current?.workspaceRoot ?? "."
88554
+ optsRef.current?.workspaceRoot ?? ".",
88555
+ keybindings
88514
88556
  ).finally(() => {
88515
88557
  void schedulerRef.current?.runAll();
88516
88558
  });
88517
88559
  return {
88518
- label: check.remediation.label,
88560
+ label: banner,
88519
88561
  promise,
88520
- healthId: check.id,
88521
- healthLabel: check.label
88562
+ healthId: first.id,
88563
+ healthLabel: first.label
88522
88564
  };
88523
88565
  }
88524
88566
  };
@@ -88551,8 +88593,8 @@ function Cockpit(props) {
88551
88593
  const { stdout } = use_stdout_default();
88552
88594
  const focus = useCockpitStore((s) => s.focus);
88553
88595
  const activeModal = useCockpitStore((s) => s.activeModal);
88554
- const [rows, setRows] = (0, import_react8.useState)(stdout.rows ?? 24);
88555
- (0, import_react8.useEffect)(() => {
88596
+ const [rows, setRows] = (0, import_react9.useState)(stdout.rows ?? 24);
88597
+ (0, import_react9.useEffect)(() => {
88556
88598
  const onResize = () => setRows(stdout.rows ?? 24);
88557
88599
  stdout.on("resize", onResize);
88558
88600
  return () => {
@@ -91386,7 +91428,7 @@ function hasLockfile(workspaceRoot) {
91386
91428
  }
91387
91429
 
91388
91430
  // src/runCockpit.ts
91389
- var import_react9 = __toESM(require_react(), 1);
91431
+ var import_react10 = __toESM(require_react(), 1);
91390
91432
  var ENTER_ALT_SCREEN = "\x1B[?1049h\x1B[H";
91391
91433
  var EXIT_ALT_SCREEN = "\x1B[?1049l";
91392
91434
  function runCockpit(opts = {}) {
@@ -91425,7 +91467,7 @@ function runCockpit(opts = {}) {
91425
91467
  throw err;
91426
91468
  });
91427
91469
  }
91428
- const ink = render_default(import_react9.default.createElement(Cockpit, cockpitProps), { exitOnCtrlC: true });
91470
+ const ink = render_default(import_react10.default.createElement(Cockpit, cockpitProps), { exitOnCtrlC: true });
91429
91471
  return {
91430
91472
  waitUntilExit: async () => {
91431
91473
  try {
@@ -91533,6 +91575,7 @@ async function devCommand(opts = {}) {
91533
91575
  const requestedHidden = requestedPane === "repos" && reposEmpty || requestedPane === "health" && healthEmpty;
91534
91576
  const initialFocus = requestedHidden ? "output" : requestedPane;
91535
91577
  cockpitStore.getState().setFocus(initialFocus);
91578
+ cockpitStore.getState().setKeybindings(normaliseKeybindings(config.keybindings));
91536
91579
  const builtinActions = buildBuiltinActions(config);
91537
91580
  const actions = buildActionRegistry(
91538
91581
  [...config.actions],
@@ -91664,7 +91707,8 @@ async function devCommand(opts = {}) {
91664
91707
  exclude: config.notifications.exclude
91665
91708
  },
91666
91709
  appName: config.appName,
91667
- subscribeFsEvents: bootResult.subscribeFsEvents
91710
+ subscribeFsEvents: bootResult.subscribeFsEvents,
91711
+ keybindings: normaliseKeybindings(config.keybindings)
91668
91712
  }
91669
91713
  });
91670
91714
  for (const proc of config.processes) {