@ironbee-ai/cli 0.11.3 → 0.12.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 (53) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +14 -1
  3. package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
  4. package/dist/clients/claude/hooks/session-start.js +7 -0
  5. package/dist/clients/claude/hooks/session-start.js.map +1 -1
  6. package/dist/clients/claude/hooks/session-status.d.ts +129 -0
  7. package/dist/clients/claude/hooks/session-status.d.ts.map +1 -0
  8. package/dist/clients/claude/hooks/session-status.js +444 -0
  9. package/dist/clients/claude/hooks/session-status.js.map +1 -0
  10. package/dist/clients/claude/index.d.ts +26 -0
  11. package/dist/clients/claude/index.d.ts.map +1 -1
  12. package/dist/clients/claude/index.js +146 -0
  13. package/dist/clients/claude/index.js.map +1 -1
  14. package/dist/clients/claude/util.d.ts +18 -5
  15. package/dist/clients/claude/util.d.ts.map +1 -1
  16. package/dist/clients/claude/util.js +23 -6
  17. package/dist/clients/claude/util.js.map +1 -1
  18. package/dist/commands/config.d.ts +5 -4
  19. package/dist/commands/config.d.ts.map +1 -1
  20. package/dist/commands/config.js +10 -4
  21. package/dist/commands/config.js.map +1 -1
  22. package/dist/commands/hook.js +44 -0
  23. package/dist/commands/hook.js.map +1 -1
  24. package/dist/commands/statusline-toggle.d.ts +29 -0
  25. package/dist/commands/statusline-toggle.d.ts.map +1 -0
  26. package/dist/commands/statusline-toggle.js +114 -0
  27. package/dist/commands/statusline-toggle.js.map +1 -0
  28. package/dist/commands/statusline.d.ts +24 -0
  29. package/dist/commands/statusline.d.ts.map +1 -0
  30. package/dist/commands/statusline.js +79 -0
  31. package/dist/commands/statusline.js.map +1 -0
  32. package/dist/hooks/core/session-state.d.ts +25 -0
  33. package/dist/hooks/core/session-state.d.ts.map +1 -1
  34. package/dist/hooks/core/session-state.js +49 -1
  35. package/dist/hooks/core/session-state.js.map +1 -1
  36. package/dist/index.js +2 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/lib/config.d.ts +64 -0
  39. package/dist/lib/config.d.ts.map +1 -1
  40. package/dist/lib/config.js +48 -0
  41. package/dist/lib/config.js.map +1 -1
  42. package/dist/lib/event.d.ts +60 -0
  43. package/dist/lib/event.d.ts.map +1 -1
  44. package/dist/lib/event.js +1 -0
  45. package/dist/lib/event.js.map +1 -1
  46. package/dist/lib/gitignore.d.ts.map +1 -1
  47. package/dist/lib/gitignore.js +11 -0
  48. package/dist/lib/gitignore.js.map +1 -1
  49. package/dist/lib/install-snapshots.d.ts +70 -0
  50. package/dist/lib/install-snapshots.d.ts.map +1 -0
  51. package/dist/lib/install-snapshots.js +168 -0
  52. package/dist/lib/install-snapshots.js.map +1 -0
  53. package/package.json +1 -1
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * IronBee — Install Snapshots (raw CRUD)
4
+ *
5
+ * Backs up the slice of host state that `ironbee install` overwrites, so
6
+ * `uninstall` can restore the user's pre-install setup exactly. Today the
7
+ * only consumer is the statusline integration: when the user already has a
8
+ * `statusLine` in the layer IronBee writes its wrapper to
9
+ * (`.claude/settings.local.json`), installing destroys that single command
10
+ * slot — so we snapshot the original block here first, chain to it at
11
+ * runtime, and write it back on uninstall.
12
+ *
13
+ * Storage: `~/.ironbee/install-snapshots.json` — a per-developer global file
14
+ * (NOT under the project's gitignored `.ironbee/`, which `git clean` could
15
+ * wipe; NOT in `projects.json`, which stays pure inventory; NOT in
16
+ * `config.json`, which is user-editable config — this is install-derived
17
+ * state). Atomic write (temp + rename) to survive concurrent installs.
18
+ *
19
+ * {
20
+ * "version": 1,
21
+ * "projects": {
22
+ * "/abs/canonical/project": {
23
+ * "claude": {
24
+ * "statusLine": { "type": "command", "command": "~/.claude/orig.sh", "padding": 2 }
25
+ * }
26
+ * }
27
+ * }
28
+ * }
29
+ *
30
+ * Errors are non-fatal: a corrupt file returns empty and is overwritten on
31
+ * the next successful upsert. Snapshot maintenance MUST NEVER break
32
+ * `install` / `uninstall`.
33
+ */
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.snapshotsPath = snapshotsPath;
36
+ exports.loadInstallSnapshots = loadInstallSnapshots;
37
+ exports.readStatusLineSnapshot = readStatusLineSnapshot;
38
+ exports.upsertStatusLineSnapshot = upsertStatusLineSnapshot;
39
+ exports.clearStatusLineSnapshot = clearStatusLineSnapshot;
40
+ const fs_1 = require("fs");
41
+ const os_1 = require("os");
42
+ const path_1 = require("path");
43
+ const projects_registry_1 = require("./projects-registry");
44
+ const logger_1 = require("./logger");
45
+ const SNAPSHOTS_VERSION = 1;
46
+ function snapshotsDir() {
47
+ return (0, path_1.join)((0, os_1.homedir)(), ".ironbee");
48
+ }
49
+ function snapshotsPath() {
50
+ return (0, path_1.join)(snapshotsDir(), "install-snapshots.json");
51
+ }
52
+ function emptySnapshots() {
53
+ return { version: SNAPSHOTS_VERSION, projects: {} };
54
+ }
55
+ /**
56
+ * Read the snapshots file. Returns empty when missing, unreadable,
57
+ * malformed, or carrying an unexpected schema version. Never throws.
58
+ */
59
+ function loadInstallSnapshots() {
60
+ const path = snapshotsPath();
61
+ if (!(0, fs_1.existsSync)(path)) {
62
+ return emptySnapshots();
63
+ }
64
+ try {
65
+ const raw = (0, fs_1.readFileSync)(path, "utf-8");
66
+ if (raw.trim().length === 0) {
67
+ return emptySnapshots();
68
+ }
69
+ const parsed = JSON.parse(raw);
70
+ if (parsed === null || typeof parsed !== "object") {
71
+ logger_1.logger.debug(`install-snapshots: ${path} is not a JSON object — ignoring`);
72
+ return emptySnapshots();
73
+ }
74
+ const obj = parsed;
75
+ if (obj.version !== SNAPSHOTS_VERSION) {
76
+ logger_1.logger.debug(`install-snapshots: unexpected schema version ${String(obj.version)} — ignoring`);
77
+ return emptySnapshots();
78
+ }
79
+ if (obj.projects === null || typeof obj.projects !== "object" || Array.isArray(obj.projects)) {
80
+ return emptySnapshots();
81
+ }
82
+ return { version: SNAPSHOTS_VERSION, projects: obj.projects };
83
+ }
84
+ catch (e) {
85
+ logger_1.logger.debug(`install-snapshots: failed to read ${path}: ${e instanceof Error ? e.message : e}`);
86
+ return emptySnapshots();
87
+ }
88
+ }
89
+ /**
90
+ * Atomic write: serialize → temp → rename. The rename is atomic on POSIX so
91
+ * a crash mid-write can't leave a half-written file. Same lost-update caveat
92
+ * as `projects-registry` (no cross-process lock) — acceptable for the
93
+ * one-shot CLI install path.
94
+ */
95
+ function writeSnapshots(file) {
96
+ const dir = snapshotsDir();
97
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
98
+ const path = snapshotsPath();
99
+ const tmpPath = `${path}.tmp.${process.pid}.${Date.now()}`;
100
+ const body = JSON.stringify(file, null, 2) + "\n";
101
+ try {
102
+ (0, fs_1.writeFileSync)(tmpPath, body);
103
+ (0, fs_1.renameSync)(tmpPath, path);
104
+ }
105
+ catch (e) {
106
+ try {
107
+ if ((0, fs_1.existsSync)(tmpPath)) {
108
+ (0, fs_1.unlinkSync)(tmpPath);
109
+ }
110
+ }
111
+ catch {
112
+ // best-effort cleanup
113
+ }
114
+ throw e;
115
+ }
116
+ }
117
+ /** Read the statusLine snapshot for a project + client, if any. */
118
+ function readStatusLineSnapshot(projectDir, client) {
119
+ const canonical = (0, projects_registry_1.canonicalizePath)(projectDir);
120
+ const file = loadInstallSnapshots();
121
+ return file.projects[canonical]?.[client]?.statusLine;
122
+ }
123
+ /**
124
+ * Store the user's original statusLine block for a project + client. Only the
125
+ * FIRST install should call this (the snapshot is the pre-install state) —
126
+ * callers must guard against overwriting an existing snapshot on re-install.
127
+ * Failures are swallowed + logged: snapshot maintenance must not break install.
128
+ */
129
+ function upsertStatusLineSnapshot(projectDir, client, block) {
130
+ try {
131
+ const canonical = (0, projects_registry_1.canonicalizePath)(projectDir);
132
+ const file = loadInstallSnapshots();
133
+ const existing = file.projects[canonical] ?? {};
134
+ existing[client] = { ...existing[client], statusLine: block };
135
+ file.projects[canonical] = existing;
136
+ writeSnapshots(file);
137
+ }
138
+ catch (e) {
139
+ logger_1.logger.debug(`install-snapshots: upsert failed for ${projectDir}/${client}: ${e instanceof Error ? e.message : e}`);
140
+ }
141
+ }
142
+ /**
143
+ * Remove the statusLine snapshot for a project + client. Drops the client
144
+ * entry when it has no other snapshots, and the project entry when it has no
145
+ * clients left. Idempotent — soft no-op when nothing matches.
146
+ */
147
+ function clearStatusLineSnapshot(projectDir, client) {
148
+ try {
149
+ const canonical = (0, projects_registry_1.canonicalizePath)(projectDir);
150
+ const file = loadInstallSnapshots();
151
+ const clients = file.projects[canonical];
152
+ if (!clients || !clients[client]) {
153
+ return;
154
+ }
155
+ delete clients[client].statusLine;
156
+ if (Object.keys(clients[client]).length === 0) {
157
+ delete clients[client];
158
+ }
159
+ if (Object.keys(clients).length === 0) {
160
+ delete file.projects[canonical];
161
+ }
162
+ writeSnapshots(file);
163
+ }
164
+ catch (e) {
165
+ logger_1.logger.debug(`install-snapshots: clear failed for ${projectDir}/${client}: ${e instanceof Error ? e.message : e}`);
166
+ }
167
+ }
168
+ //# sourceMappingURL=install-snapshots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-snapshots.js","sourceRoot":"","sources":["../../src/lib/install-snapshots.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ironbee-ai/cli",
3
- "version": "0.11.3",
3
+ "version": "0.12.0",
4
4
  "description": "The CLI for IronBee — Verification and Intelligence Layer for Agentic Development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {