skalpel 2.0.24 → 3.0.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.
Files changed (43) hide show
  1. package/INSTALL.md +103 -0
  2. package/LICENSE +201 -21
  3. package/README.md +12 -174
  4. package/design-tokens.json +51 -0
  5. package/npm-bin/colors.js +125 -0
  6. package/npm-bin/skalpel.js +200 -0
  7. package/npm-bin/skalpeld.js +20 -0
  8. package/package.json +50 -68
  9. package/postinstall/index.js +294 -0
  10. package/postinstall/launchd/com.skalpel.skalpeld.plist.tmpl +41 -0
  11. package/postinstall/lib/detect-prior.js +62 -0
  12. package/postinstall/lib/env-inject.js +121 -0
  13. package/postinstall/lib/launch.js +28 -0
  14. package/postinstall/lib/log.js +31 -0
  15. package/postinstall/lib/paths.js +236 -0
  16. package/postinstall/lib/rc-edit.js +167 -0
  17. package/postinstall/lib/rc-edit.test.js +196 -0
  18. package/postinstall/lib/service-register.js +293 -0
  19. package/postinstall/lib/sign-in.js +98 -0
  20. package/postinstall/lib/template.js +36 -0
  21. package/postinstall/snippets/bash.sh.tmpl +12 -0
  22. package/postinstall/snippets/fish.fish.tmpl +11 -0
  23. package/postinstall/snippets/powershell.ps1.tmpl +12 -0
  24. package/postinstall/snippets/zsh.sh.tmpl +13 -0
  25. package/postinstall/systemd/skalpeld.service.tmpl +33 -0
  26. package/postinstall/windows/Task.xml.tmpl +42 -0
  27. package/postinstall/windows/register-task.ps1.tmpl +45 -0
  28. package/dist/cli/index.js +0 -2888
  29. package/dist/cli/index.js.map +0 -1
  30. package/dist/cli/proxy-runner.js +0 -1598
  31. package/dist/cli/proxy-runner.js.map +0 -1
  32. package/dist/index.cjs +0 -2282
  33. package/dist/index.cjs.map +0 -1
  34. package/dist/index.d.cts +0 -165
  35. package/dist/index.d.ts +0 -165
  36. package/dist/index.js +0 -2236
  37. package/dist/index.js.map +0 -1
  38. package/dist/proxy/index.cjs +0 -1731
  39. package/dist/proxy/index.cjs.map +0 -1
  40. package/dist/proxy/index.d.cts +0 -39
  41. package/dist/proxy/index.d.ts +0 -39
  42. package/dist/proxy/index.js +0 -1697
  43. package/dist/proxy/index.js.map +0 -1
package/INSTALL.md ADDED
@@ -0,0 +1,103 @@
1
+ # Install and bundling — `skalpel` and `skalpeld`
2
+
3
+ The `skalpel` npm package is the canonical distribution surface for the Skalpel client on a developer's machine. The package contains two executables: `skalpel`, the Bubble Tea terminal UI specified in `SPEC.md` (in this repo) and `docs/RUN_CLIENT_LOCALLY.md` (also in this repo), and `skalpeld`, the local proxy and daemon. Installing one always installs the other; the two are released, signed, and versioned as a single bundle. A user who runs `npx skalpel`, `npm install -g skalpel`, or pulls a GitHub Releases tarball receives both binaries in a single transaction. There is no separate `skalpeld` package, no separate version cadence, and no "TUI without daemon" install path.
4
+
5
+ This document is the canonical specification for what gets installed where, how the first-run flow lands the user on the Engines tab, and how updates and uninstalls are handled. See `SPEC.md` for the TUI specification, `docs/RUN_CLIENT_LOCALLY.md` for the dev workflow, and the upstream infrastructure / cross-surface-contract documents (when available) for bundle composition and auth-handoff details.
6
+
7
+ The bundling commitment is a product decision before it is an implementation decision. A user who installs the TUI receives the daemon in the same transaction because the configurator (TUI) and the proxy (`skalpeld`) are two halves of the same product surface. Splitting them into independently versioned packages would introduce a class of "TUI-newer-than-daemon" or "daemon-newer-than-TUI" failures that no recovery clause in `SPEC.md` §8 is designed to handle. The bundle is the unit of release; the version is the unit of identity; the install path is the unit of choice.
8
+
9
+ ## What gets installed
10
+
11
+ The npm package places two executables on the user's machine. Both arrive together; neither is shipped without the other.
12
+
13
+ | Binary | Role | On-disk location |
14
+ |---|---|---|
15
+ | `skalpel` | Bubble Tea terminal UI; the configurator the user invokes by typing `skalpel` in a shell. | A directory on the user's `PATH`. For `npx`, this is npm's transient cache. For `npm install -g`, this is the npm global prefix's `bin/` directory (typically `/usr/local/bin/skalpel` on macOS and Linux, `%AppData%\npm\skalpel.cmd` on Windows). |
16
+ | `skalpeld` | Local proxy/daemon; intercepts traffic from coding agents (Cursor, Claude Code, Codex), applies engines, and forwards to upstream providers. | Co-located with `skalpel` in the same `bin/` directory. Per-OS service registration (launchd agent on macOS, systemd user unit on Linux, Task Scheduler entry on Windows) is performed by the `postinstall` script so the daemon survives reboot; see "Daemon lifecycle on subsequent launches" below and `../../Skalpel_Infrastructure/INFRASTRUCTURE.md` for the platform constraints. |
17
+
18
+ Both binaries are produced from the same release workflow named in `INFRASTRUCTURE.md`'s CLI Distribution section. Both are signed keylessly via Sigstore / cosign. Both carry the same version string. Mismatch by version is impossible by construction on a machine that received either binary via a supported install path.
19
+
20
+ ### Platform support
21
+
22
+ The release workflow targets three platforms in v1: macOS (arm64 and amd64), Linux (amd64; arm64 as a follow-on), and Windows (amd64). Each platform receives its own pair of binaries built from the same source revision. The npm package selects the right pair at install time based on the user's `os` and `cpu`; the GitHub Releases tarballs are named per-platform and the user picks. The configuration directory paths and service-registration entry points named elsewhere in this document differ per platform; the bundling and version-coupling commitments do not.
23
+
24
+ ### Configuration directory
25
+
26
+ The configuration directory is per-OS, per `SPEC.md` §7. Both binaries read it: the TUI for `auth.json` and `config.toml`, the daemon for the same files plus its socket and logfile path. The directory is created by the wizard on first run and is owned by the user. It is not part of the npm package; it is created by the binaries on first invocation and survives uninstalls so that reinstalls can resume.
27
+
28
+ ## Install paths
29
+
30
+ Three first-class install paths are supported. Each delivers both binaries; none can deliver one without the other.
31
+
32
+ - **`npx skalpel`** — the zero-install path. npm fetches the package on demand and runs the `skalpel` binary. `skalpeld` is materialized in the same npx cache and is reachable on the same `PATH`-like resolution that npx uses for the lifetime of the invocation. This is the recommended path for users running Skalpel for the first time.
33
+ - **`npm install -g skalpel`** — the persistent-install path. The package is installed into npm's global prefix; both binaries are placed in the global `bin/` directory and become available system-wide. Subsequent invocations resolve `skalpel` and `skalpeld` from `PATH` without the npm overhead. Recommended for users who want the binaries co-located with their other CLI tools.
34
+ - **GitHub Releases tarballs** — the air-gapped path. Each release attaches per-platform tarballs containing both binaries plus their cosign signatures and checksums (per `INFRASTRUCTURE.md`'s CLI Distribution section, which mandates keyless Sigstore signing for every release artifact). Recommended for users on a machine that cannot reach the public npm registry, or for environments where supply-chain verification is performed manually before placing binaries on `PATH`.
35
+
36
+ All three paths produce identical binaries — same SHAs, same cosign signatures, same version metadata. The choice between them is operational, not functional.
37
+
38
+ ## First-run flow
39
+
40
+ The first-run flow assumes the user has obtained an `sk-skalpel-*` API key on Web (per the Auth handoff section of `../../design-dockets/cross-surface-contract.md`). The flow is:
41
+
42
+ 1. The user runs `npx skalpel` (or `skalpel` after a global install). The npm package is materialized; both binaries are present.
43
+ 2. The TUI detects the absence of `auth.json` and enters the install wizard. The wizard prompts the user to paste the API key copied from Web. The plaintext value is shown on Web exactly once at creation time; the user pastes it here.
44
+ 3. The wizard writes `auth.json` to the per-OS configuration directory (per `SPEC.md` §7). The file is owned by the user with `0600` permissions.
45
+ 4. The wizard invokes `skalpeld` to start the daemon. The TUI shows the `Starting skalpeld…` splash for up to three seconds (per spec §8.5).
46
+ 5. Once the daemon is reachable, the TUI lands the user on the Engines tab. The matrix renders for whatever agents the daemon has detected so far. If no agents have been opened since installation, the empty-state message from spec §3.2 is shown.
47
+
48
+ This flow corresponds to Journey 1 — First launch, fresh authentication — in `SPEC.md`. That narrative describes what the user feels at each step; this document describes what the install machinery actually does.
49
+
50
+ If the user runs `skalpel` without first obtaining an API key, the TUI exits per spec §8.4 with a stderr pointer at `skalpel login`. The wizard above is the path for users who arrived through the post-signup install hub on Web; users with broken or missing auth state are returned to the shell.
51
+
52
+ An alternative first-run flow uses `skalpel login` from the shell directly. That command runs a device-code flow against Cognito (per the Auth handoff section of the cross-surface contract) and writes `auth.json` without the user having to paste an API key. The two flows produce equivalent on-disk state; the API-key-paste flow is the one a user lands in when arriving from the Web post-signup install hub, and the device-code flow is the one a user runs when reauthenticating an account that has already been signed in on this machine before.
53
+
54
+ ## Daemon lifecycle on subsequent launches
55
+
56
+ On every launch after the first, the TUI checks whether `skalpeld` is reachable. If it is, the TUI proceeds to the Engines tab without further interaction. If it is not, the TUI attempts to start it (per spec §8.5) and shows the `Starting skalpeld…` splash for up to three seconds. If the daemon does not come up in that window, the TUI proceeds with the daemon-unreachable banner and the user is offered a `[r]` retry affordance.
57
+
58
+ The TUI is not a process supervisor. Per `SPEC.md` §01: the TUI tries to start the daemon at launch and surfaces the daemon's state via the banner, but there is no "stop daemon," "restart daemon," or "view daemon logs" control in the TUI; those are shell-level concerns. The install machinery makes both binaries available; the runtime relationship between them is the TUI's start-on-launch attempt and nothing more.
59
+
60
+ Per-OS service registration is performed by the npm `postinstall` script (`postinstall/lib/service-register.js`). On macOS the script renders and loads a launchd agent (`com.skalpel.skalpeld.plist`) and kickstarts it via `launchctl`; on Linux the script writes a systemd user unit (`skalpeld.service`) and starts it via `systemctl --user`; on Windows the script registers a Task Scheduler entry (`Task.xml`) and runs it via `schtasks /Run`. The `postinstall` script also starts the daemon immediately on first install so the user does not have to wait for the next TUI launch to bring `skalpeld` online; subsequent boots rely on the registered service entry, with the TUI's start-on-launch attempt as a defence-in-depth fallback. Both the bundling commitment (atomic install of TUI + daemon) and the TUI's runtime behaviour on launch are independent of the service registration mechanism.
61
+
62
+ ## Updates
63
+
64
+ `npx skalpel@latest` and `npm update -g skalpel` are the two update paths. Both update both binaries atomically: the new `skalpel` and the new `skalpeld` arrive together, and the old `skalpel` and old `skalpeld` are replaced together. There is no window during which the binaries are at different versions on disk.
65
+
66
+ The CLI auto-update polling described in `INFRASTRUCTURE.md` (CLI Distribution, the `cli/latest` endpoint) surfaces a non-blocking notice when a newer version is available. The user runs the update command themselves; the TUI does not perform an in-place upgrade. After an update, the next `skalpel` invocation launches the new TUI, which in turn starts the new `skalpeld` if needed.
67
+
68
+ GitHub Releases tarball users update by downloading the new tarball, verifying signatures and checksums, and replacing the binaries on `PATH`. Both replacements happen as a single user-initiated operation; partial updates are not a supported state.
69
+
70
+ A user who has rolled back to a previous version (by running `npm install -g skalpel@<older>` or by replacing tarball binaries with archived ones) lands at a coherent older bundle: the older `skalpel` and the older `skalpeld` arrive together. There is no roll-back-the-TUI-only or roll-back-the-daemon-only operation. The same atomicity that protects forward updates protects rollbacks.
71
+
72
+ ## Uninstall
73
+
74
+ `npm uninstall -g skalpel` removes both binaries. There is no separate uninstall command for `skalpeld`; the package is the unit of removal. Before npm removes the binaries it fires the package's `preuninstall` hook, which invokes `node postinstall/index.js --uninstall`; that pass removes the rc-file managed-block injected on install (so the user's shell stops pointing at the now-defunct local proxy port) and unregisters the per-OS service entry (so `launchctl`, `systemctl --user`, or `schtasks` stops trying to start a daemon whose binary is about to vanish). The shim and registration cleanup happen before the binaries themselves are removed; an interrupted uninstall leaves a coherent intermediate state.
75
+
76
+ `npx skalpel` users have no global install to uninstall; the npx cache is cleaned by npm on its own schedule. For an `npx`-only user who wants to clean up shell rc-file and service registration without waiting on cache eviction, running `node postinstall/index.js --uninstall` from the package directory performs the same cleanup the `preuninstall` hook would.
77
+
78
+ User data is **not** removed by uninstall. The configuration directory (`config.toml` and `auth.json`) persists on disk after the binaries are gone. This is deliberate: a user reinstalling Skalpel on the same machine should find their engine toggles and active organization preserved. To remove user data manually, delete the per-OS configuration directory named in `SPEC.md` §7.
79
+
80
+ ## Version coupling
81
+
82
+ `skalpel` and `skalpeld` carry the same version string at all times. The release workflow produces both from the same git tag; the npm package's `version` field, the binaries' embedded version metadata, and the cosign signatures all reference the same value. There is no path by which the two could diverge on a machine that received either via a supported install path.
83
+
84
+ When the TUI connects to the daemon at launch, the handshake includes a version exchange. If the version reported by `skalpeld` does not match the version embedded in `skalpel` — a state that should be unreachable through the supported install paths — the TUI enters a degraded state per `SPEC.md` §8 and surfaces a banner instructing the user to reinstall the bundle. The handshake is a defence in depth; the install paths are designed so that the handshake should never fire on a mismatch.
85
+
86
+ The handshake is also where the TUI reads the daemon's engine list and the daemon's per-agent detection results (per `SPEC.md` §6 and §9). A version-coupled handshake is also a guarantee that the TUI is reading those results from a daemon whose schema it understands. When the bundle promises versions match, the TUI does not need a defensive parse-and-recover path for the daemon's responses; the schema is whatever the bundle's joint version says it is.
87
+
88
+ ## Open questions
89
+
90
+ A small set of bundling questions are recorded here for the build phase. Each will be resolved before v1 ships; none affect the design commitments above.
91
+
92
+ - **`npx` cache eviction and version-pinning UX.** `npx skalpel` caches per-version; a user who runs `npx skalpel@1.2.3` after `1.2.4` has shipped continues to execute `1.2.3` until npm's cache resolves. The auto-update notice surfaces in the TUI, but the underlying npx semantics are an open ergonomic question.
93
+ - **Signed-link pre-population of the API key.** Whether the post-signup install path emits a signed link that pre-populates the `npx skalpel` wizard with the user's API key, or whether the user pastes the key by hand, is recorded in `../../design-dockets/cross-surface-contract.md` as an open question. The latter is the safer default; the former would shorten the first-run flow by one step.
94
+ - **Bundle size budget.** The two binaries together set a download-size budget for first-time `npx` users; whether to ship a slim TUI front-end and a separately-downloaded `skalpeld` payload via a `postinstall` fetch (still in the same npm transaction) or to ship both in the package tarball directly is a build-phase decision. Either approach preserves the bundling commitment because both binaries are still resolved and authenticated within the same install operation.
95
+ - **Install-time telemetry.** Whether the install path emits any telemetry event (e.g., "first install completed") is open. The TUI itself does not phone home in v1 (per the privacy stance in `SPEC.md` §05); whether the install wizard shares that posture or whether anonymous install counts are acceptable for release-quality measurement is a build-phase decision.
96
+ - **Windows install ergonomics.** Whether `npx skalpel` on Windows requires Windows Terminal or a recent PowerShell to render the Bubble Tea TUI's adaptive colours and key bindings cleanly, and whether a fallback message should explain the requirement, is open. The bundling commitment is platform-agnostic; the first-run experience may not be.
97
+
98
+ ## References
99
+
100
+ - `SPEC.md` — TUI specification: §1 (goals and non-goals; Install/uninstall flow is named as a non-goal there with a pointer here), §7 (configuration directory and file layout), §8 (degraded states and banners, including the version-mismatch banner), §16 (Install and distribution; cross-links here as the canonical source).
101
+ - `SPEC.md` — Skalpel TUI design dockets: §01 (the daemon non-supervisor stance), §03 Journey 1 (first-launch fresh-authentication flow that this document's first-run flow corresponds to), §05 (privacy stance referenced in the install-time telemetry open question).
102
+ - `../../design-dockets/cross-surface-contract.md` — Cross-surface contract: the Auth handoff section (machine-client identity, the `npx skalpel` install wizard arriving in the same transaction as the daemon), the ownership matrix's Post-signup install row.
103
+ - `../../Skalpel_Infrastructure/INFRASTRUCTURE.md` — CLI Distribution section (npm, GitHub Releases, Sigstore signing, the `cli/latest` auto-update endpoint, emergency-release fallback path).
package/LICENSE CHANGED
@@ -1,21 +1,201 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Skalpel AI
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for describing the origin of the Work and
141
+ reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Support. While redistributing the Work or
166
+ Derivative Works thereof, You may choose to offer, and charge a
167
+ fee for, acceptance of support, warranty, indemnity, or other
168
+ liability obligations and/or rights consistent with this License.
169
+ However, in accepting such obligations, You may act only on Your
170
+ own behalf and on Your sole responsibility, not on behalf of any
171
+ other Contributor, and only if You agree to indemnify, defend,
172
+ and hold each Contributor harmless for any liability incurred by,
173
+ or claims asserted against, such Contributor by reason of your
174
+ accepting any such warranty or support.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 SkalpelAI Inc.
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md CHANGED
@@ -1,188 +1,26 @@
1
- # Skalpel
1
+ # skalpel
2
2
 
3
- Optimize Claude Code prompts to reduce credit usage. Skalpel sits between Claude Code and the Anthropic API, optimizing prompts before they reach the provider saving you money without changing how you work.
3
+ Skalpel is the local proxy and terminal UI for coding agents — Cursor, Claude Code, Codex, and others. It runs as two binaries on your machine: `skalpel`, a Bubble Tea TUI configurator, and `skalpeld`, the local daemon that intercepts agent traffic, applies engines, and forwards to upstream providers. The two ship as a single npm package and are always installed together.
4
4
 
5
- ## How It Works
5
+ ## Install and first run
6
6
 
7
- ```
8
- Claude Code --> Skalpel Proxy (local) --> Skalpel Backend (AWS) --> Anthropic API
9
- Intercepts requests Optimizes prompts Returns response
10
- Adds tracking headers Reduces token usage
11
- ```
12
-
13
- 1. A local proxy runs on your machine (port 18100)
14
- 2. Claude Code is configured to send API requests to the proxy instead of `api.anthropic.com`
15
- 3. The proxy forwards requests to the Skalpel backend, which optimizes prompts for lower token usage
16
- 4. The optimized request is sent to Anthropic, and the response streams back to Claude Code
17
-
18
- Your Anthropic API key stays in the request chain — Skalpel never stores it.
7
+ After signing up at [skalpel.ai](https://skalpel.ai) and copying your `sk-skalpel-*` API key:
19
8
 
20
- ## Quick Start
21
-
22
- One command to install, detect Claude Code, and start optimizing:
23
-
24
- ```bash
25
- npx skalpel --api-key sk-skalpel-YOUR_KEY --auto
26
9
  ```
27
-
28
- This will:
29
- - Start the local proxy on ports 18100 (Anthropic) and 18101 (OpenAI)
30
- - Detect coding agents on your machine
31
- - Configure Claude Code and Codex agents automatically
32
- - Set shell environment variables in your `.bashrc`/`.zshrc`
33
- - Begin optimizing API traffic immediately
34
-
35
- ### Interactive Setup
36
-
37
- For a guided setup with prompts:
38
-
39
- ```bash
40
10
  npx skalpel
41
11
  ```
42
12
 
43
- The wizard walks you through API key entry, agent detection, and proxy configuration.
44
-
45
- ### Manual Setup
46
-
47
- ```bash
48
- # 1. Start the proxy
49
- npx skalpel start
50
-
51
- # 2. Run the setup wizard to configure Claude Code
52
- npx skalpel setup
53
-
54
- # 3. Verify everything is working
55
- npx skalpel doctor
56
- ```
57
-
58
- ## What Gets Configured
59
-
60
- ### Claude Code
61
-
62
- Claude Code is auto-configured during setup. `ANTHROPIC_BASE_URL` is set in `~/.claude/settings.json` to route API calls through the proxy. Only API endpoints (`/v1/messages`, `/v1/complete`) are routed through Skalpel for optimization; auth endpoints pass directly to Anthropic.
63
-
64
- ### Shell Environment (`~/.bashrc`, `~/.zshrc`)
65
-
66
- Environment variables are added for tools that read them directly:
67
-
68
- ```bash
69
- # BEGIN SKALPEL PROXY - do not edit manually
70
- export ANTHROPIC_BASE_URL="http://localhost:18100"
71
- export OPENAI_BASE_URL="http://localhost:18101"
72
- # END SKALPEL PROXY
73
- ```
74
-
75
- ### Proxy Config (`~/.skalpel/config.json`)
76
-
77
- ```json
78
- {
79
- "apiKey": "sk-skalpel-YOUR_KEY",
80
- "remoteBaseUrl": "http://skalpel-production-554359744.us-west-2.elb.amazonaws.com",
81
- "anthropicPort": 18100,
82
- "openaiPort": 18101
83
- }
84
- ```
85
-
86
- ## CLI Commands
87
-
88
- | Command | Description |
89
- |---|---|
90
- | `npx skalpel` | Run the setup wizard |
91
- | `npx skalpel start` | Start the proxy |
92
- | `npx skalpel stop` | Stop the proxy |
93
- | `npx skalpel status` | Show proxy status and uptime |
94
- | `npx skalpel doctor` | Verify configuration and connectivity |
95
- | `npx skalpel logs` | View proxy logs |
96
- | `npx skalpel logs -f` | Follow proxy logs in real time |
97
- | `npx skalpel uninstall` | Remove proxy, configs, and shell modifications |
13
+ `npx` materializes both binaries, walks you through pasting the API key, starts `skalpeld`, and lands you on the Engines tab. To install persistently:
98
14
 
99
- ### Flags
100
-
101
- | Flag | Description |
102
- |---|---|
103
- | `--api-key <key>` | Provide Skalpel API key (skips interactive prompt) |
104
- | `--auto` | Non-interactive mode (requires `--api-key`) |
105
-
106
- ## Streaming Support
107
-
108
- Skalpel fully supports Anthropic's SSE streaming protocol. When Claude Code sends a streaming request (`"stream": true`), the proxy:
109
-
110
- - Detects the streaming flag in the request body
111
- - Forwards to the backend with all original headers
112
- - Pipes SSE events (`message_start`, `content_block_delta`, `message_stop`) directly back to Claude Code
113
- - Preserves upstream headers like `anthropic-request-id`
114
-
115
- No buffering, no modification of the stream — chunks flow through in real time.
116
-
117
- ## Headers
118
-
119
- The proxy adds these headers to every request forwarded to the Skalpel backend:
120
-
121
- | Header | Value | Purpose |
122
- |---|---|---|
123
- | `X-Skalpel-API-Key` | Your Skalpel key | Backend authentication |
124
- | `X-Skalpel-Source` | `claude-code` | Traffic source identification |
125
- | `X-Skalpel-Agent-Type` | `claude-code` | Agent type for optimization routing |
126
- | `X-Skalpel-SDK-Version` | `proxy-1.0.0` | SDK version tracking |
127
-
128
- The original `x-api-key` header (your Anthropic key) is forwarded as-is.
129
-
130
- ## Codex Support
131
-
132
- Skalpel also supports OpenAI Codex on port 18101. The same `--auto` flow detects and configures both agents if present.
133
-
134
- ## SDK Integration
135
-
136
- For programmatic use in your own applications:
137
-
138
- ```typescript
139
- import { createSkalpelClient } from 'skalpel';
140
- import Anthropic from '@anthropic-ai/sdk';
141
-
142
- const client = createSkalpelClient(new Anthropic(), {
143
- apiKey: process.env.SKALPEL_API_KEY!,
144
- });
145
-
146
- const response = await client.messages.create({
147
- model: 'claude-sonnet-4-20250514',
148
- max_tokens: 1024,
149
- messages: [{ role: 'user', content: 'Hello' }],
150
- });
151
15
  ```
152
-
153
- See the [API Reference](#api-reference) for all SDK options.
154
-
155
- ## API Reference
156
-
157
- ### `createSkalpelClient<T>(client: T, options: SkalpelClientOptions): T`
158
-
159
- Wraps an existing OpenAI or Anthropic client. All API calls route through the Skalpel proxy with automatic fallback on errors.
160
-
161
- ### `createSkalpelAnthropic(options): Promise<Anthropic>`
162
-
163
- Creates a pre-configured Anthropic client pointing at the Skalpel proxy.
164
-
165
- ### `createSkalpelOpenAI(options): Promise<OpenAI>`
166
-
167
- Creates a pre-configured OpenAI client pointing at the Skalpel proxy.
168
-
169
- ### Configuration Options
170
-
171
- ```typescript
172
- interface SkalpelClientOptions {
173
- apiKey: string; // Skalpel API key (sk-skalpel-*)
174
- workspace?: string; // Workspace ID
175
- baseURL?: string; // Proxy URL (default: production ALB)
176
- fallbackOnError?: boolean; // Fall back to direct provider (default: true)
177
- timeout?: number; // Request timeout in ms (default: 30000)
178
- retries?: number; // Max retries (default: 2)
179
- }
16
+ npm install -g skalpel
180
17
  ```
181
18
 
182
- ## Uninstall
19
+ Both `skalpel` and `skalpeld` are placed on your `PATH`. For details on what gets installed where, per-OS service registration, updates, and uninstall, see [INSTALL.md](./INSTALL.md).
183
20
 
184
- ```bash
185
- npx skalpel uninstall
186
- ```
21
+ ## Links
187
22
 
188
- This removes the proxy and cleans up shell environment variables. If a previous version of Skalpel modified `~/.claude/settings.json`, uninstall will also clean up those changes.
23
+ - Homepage: https://skalpel.ai
24
+ - Documentation: see `INSTALL.md` and `SPEC.md` in this repo
25
+ - Issues: https://github.com/skalpelai/Skalpelai_Client/issues
26
+ - License: Apache-2.0 (see [LICENSE](./LICENSE))
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "design-tokens.schema.json",
3
+ "version": 1,
4
+ "themes": {
5
+ "tokyo-night-storm": {
6
+ "base": "#1a1b26",
7
+ "mantle": "#16161e",
8
+ "crust": "#16161e",
9
+ "surface0": "#16161e",
10
+ "surface1": "#1f2335",
11
+ "surface2": "#24283b",
12
+ "overlay0": "#3b4261",
13
+ "overlay1": "#565f89",
14
+ "overlay2": "#737aa2",
15
+ "text": "#c0caf5",
16
+ "subtext0": "#a9b1d6",
17
+ "subtext1": "#a9b1d6",
18
+ "lilac": "#bb9af7",
19
+ "pink": "#f7768e",
20
+ "red": "#f7768e",
21
+ "maroon": "#f7768e",
22
+ "peach": "#ff9e64",
23
+ "lemon": "#e0af68",
24
+ "mint": "#9ece6a",
25
+ "teal": "#73daca",
26
+ "sky": "#7aa2f7",
27
+ "sapphire": "#7aa2f7",
28
+ "blue": "#7aa2f7",
29
+ "lavender": "#bb9af7"
30
+ }
31
+ },
32
+ "semantic": {
33
+ "tab.dashboard": "tokyo-night-storm.lilac",
34
+ "tab.engines": "tokyo-night-storm.sky",
35
+ "tab.sessions": "tokyo-night-storm.pink",
36
+ "tab.account": "tokyo-night-storm.mint",
37
+ "tab.logs": "tokyo-night-storm.lemon",
38
+ "selection.bg": "tokyo-night-storm.lilac",
39
+ "selection.fg": "tokyo-night-storm.crust",
40
+ "border.dim": "tokyo-night-storm.overlay0",
41
+ "footer.text": "tokyo-night-storm.overlay1",
42
+ "section.cost": "tokyo-night-storm.pink",
43
+ "section.engine": "tokyo-night-storm.lilac",
44
+ "section.quality": "tokyo-night-storm.mint",
45
+ "level.error": "tokyo-night-storm.red",
46
+ "level.warn": "tokyo-night-storm.lemon",
47
+ "level.info": "tokyo-night-storm.sky",
48
+ "level.success": "tokyo-night-storm.mint",
49
+ "level.debug": "tokyo-night-storm.overlay0"
50
+ }
51
+ }