claude-use 7.4.0 → 7.6.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.
- package/README.md +3 -2
- package/dist/cli.cjs +198 -90
- package/dist/index.cjs +316 -126
- package/dist/index.mjs +291 -126
- package/dist/types/config/schema.d.ts +1 -1
- package/dist/types/frontdoor/capture.d.ts +9 -0
- package/dist/types/frontdoor/connect.d.ts +14 -6
- package/dist/types/frontdoor/connectEffects.d.ts +3 -0
- package/dist/types/frontdoor/tap.d.ts +8 -0
- package/dist/types/index.d.ts +7 -2
- package/package.json +1 -1
|
@@ -427,7 +427,7 @@ export declare const POOL_SELECTOR_PREFIX = "pool:";
|
|
|
427
427
|
/** A pool's own name: the identity alphabet minus `@`, since a pool is never an email address. */
|
|
428
428
|
export declare const PoolNameSchema: z.ZodString;
|
|
429
429
|
/** A named, explicit set of identities to choose among at launch. Never implicit: a pool lists its members, so an identity that bills a client is only ever picked when someone put it there. */
|
|
430
|
-
declare const PoolSchema: z.ZodObject<{
|
|
430
|
+
export declare const PoolSchema: z.ZodObject<{
|
|
431
431
|
identities: z.ZodArray<z.ZodString>;
|
|
432
432
|
}, z.core.$strict>;
|
|
433
433
|
export type Pool = z.infer<typeof PoolSchema>;
|
|
@@ -20,8 +20,17 @@ export interface PassthroughObserver {
|
|
|
20
20
|
readonly onResponseChunk: (chunk: Buffer) => void;
|
|
21
21
|
readonly onEnd: () => void;
|
|
22
22
|
}
|
|
23
|
+
/** The direction one tapped byte chunk flowed, named from the session's point of view. */
|
|
24
|
+
type StreamDirection = "client-to-server" | "server-to-client";
|
|
25
|
+
/** The byte-level tap for one terminated stream whose protocol the surface does not parse: every chunk both directions, then the end. */
|
|
26
|
+
export interface StreamTap {
|
|
27
|
+
readonly onChunk: (direction: StreamDirection, chunk: Readonly<Buffer>) => void;
|
|
28
|
+
readonly onEnd: () => void;
|
|
29
|
+
}
|
|
23
30
|
/** The tap the connect surface drives. `undefined` everywhere means "not capturing"; one object covers the whole door process. */
|
|
24
31
|
export interface ConnectCapture {
|
|
32
|
+
/** Opens the byte-level tap for one host's terminated stream, whose chunks are recorded verbatim (text, or base64 when not valid UTF-8) under the same caps as piped bodies. Optional because a capture can be stream-silent by construction. */
|
|
33
|
+
readonly tapStream?: (host: string) => StreamTap;
|
|
25
34
|
/** Records one authenticated CONNECT target: the host and port only, since a blind tunnel's bytes are unreadable by construction. */
|
|
26
35
|
readonly connect: (target: {
|
|
27
36
|
readonly host: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
-
import * as net from "node:net";
|
|
2
|
+
import type * as net from "node:net";
|
|
3
3
|
import type { ConnectCapture, PassthroughObserver } from "./capture";
|
|
4
4
|
/**
|
|
5
5
|
* The front door's CONNECT surface, so an OAuth session can have agent-shim's routing AND Claude Code's Remote Control at once: Remote Control refuses any `ANTHROPIC_BASE_URL` other than the real API, but happily honours `HTTPS_PROXY`, so OAuth launches route at the proxy layer instead.
|
|
@@ -14,10 +14,16 @@ export declare const CONNECT_INTERCEPT_HOST = "api.anthropic.com";
|
|
|
14
14
|
* Every CONNECT host whose TLS this surface terminates, each with its own leaf and its own HTTP parser: the API host above, and `platform.claude.com`, the claude.ai control plane where Remote Control's long-lived channel and its handshake live. Terminating the second one is what makes a Remote Control login rejection observable at all: its bytes cross this surface either way, and blind-tunnelling them hides exactly the exchange that failed. Only the API host's `/v1/` paths ever reach the routed pipeline; everything else on either session is piped to that session's own real upstream, so the pipeline's identification and authorisation are never asked to serve another host's traffic.
|
|
15
15
|
*/
|
|
16
16
|
export declare const CONNECT_INTERCEPT_HOSTS: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* The intercept hosts the surface never parses as HTTP: terminated with ALPN for HTTP/2 and HTTP/1.1 both offered, pumped byte for byte to the real host over TLS (offering upstream only the protocol the client negotiated), and teed into the capture's stream tap when capturing is on. The claude.ai control plane's channel mixes an HTTP/1.1-shaped request with binary HTTP/2 frames, so parsing it as either protocol would destroy or distort it; tapping preserves the channel exactly as a blind tunnel served it while making its bytes observable.
|
|
19
|
+
*/
|
|
20
|
+
export declare const CONNECT_TAP_HOSTS: readonly string[];
|
|
17
21
|
/** Paths under this prefix are what the routed pipeline serves; everything else on the terminated session goes to the real upstream. */
|
|
18
22
|
export declare const ROUTED_PATH_PREFIX = "/v1/";
|
|
19
23
|
/** The port HTTPS is served on, both the default when a CONNECT authority names none and the port non-headroom paths are piped to on the real upstream. */
|
|
20
24
|
export declare const HTTPS_PORT = 443;
|
|
25
|
+
/** What the forwarding effect answers with when the upstream is unreachable. */
|
|
26
|
+
export declare const HTTP_BAD_GATEWAY = 502;
|
|
21
27
|
/** Largest CONNECT request head accepted before the connection is refused: a real head is a request line and a few short headers (Host, the proxy credential, a User-Agent), so anything this size is a confused or hostile client. 8 KiB is also the per-header-line limit common HTTP servers apply by default (nginx's `large_client_header_buffers` buffer, Apache's `LimitRequestFieldSize` of 8190 bytes), so no client is built to need a longer line, and a CONNECT head is a few such lines at most. */
|
|
22
28
|
export declare const MAX_CONNECT_HEAD_BYTES = 8192;
|
|
23
29
|
/**
|
|
@@ -112,7 +118,7 @@ interface ConnectForwardTarget {
|
|
|
112
118
|
/** Handles one parsed HTTP request on a terminated TLS session. */
|
|
113
119
|
type ConnectRequestHandler = (request: IncomingMessage, response: ServerResponse) => void;
|
|
114
120
|
/** A bound loopback listener and how to stop it. */
|
|
115
|
-
interface ConnectListenerHandle {
|
|
121
|
+
export interface ConnectListenerHandle {
|
|
116
122
|
readonly port: number;
|
|
117
123
|
/** Stops accepting, ends every live connection, and resolves once the port is released. */
|
|
118
124
|
readonly close: () => Promise<void>;
|
|
@@ -135,8 +141,10 @@ interface HttpParserSession {
|
|
|
135
141
|
export interface ConnectEffects {
|
|
136
142
|
/** Binds a loopback TCP listener; `preferredPort` is tried first and any free port used when it is taken (bind, do not probe: check-then-bind races). Resolves with the bound port and a close handle. */
|
|
137
143
|
readonly listenLoopback: (preferredPort: number | undefined, onSocket: (socket: net.Socket) => void) => Promise<ConnectListenerHandle>;
|
|
138
|
-
/** Builds the TLS terminator for one leaf, handing each successfully handshaked session to `onSecure`. */
|
|
139
|
-
readonly createTlsAcceptor: (leaf: LeafCert, onSecure: (secure: net.Socket) => void) => TlsAcceptor;
|
|
144
|
+
/** Builds the TLS terminator for one leaf, handing each successfully handshaked session to `onSecure`. `alpnProtocols`, when given, is advertised during the handshake, which is how a tap host's session can offer HTTP/2 the way its real server does. */
|
|
145
|
+
readonly createTlsAcceptor: (leaf: LeafCert, onSecure: (secure: net.Socket) => void, alpnProtocols?: readonly string[]) => TlsAcceptor;
|
|
146
|
+
/** Opens a TLS connection to a real host, presenting its name as SNI, for a tap session's upstream half. `clientAlpn`, when given, is the protocol the client negotiated with the surface and the only one offered upstream, so the tap never changes the channel's protocol. */
|
|
147
|
+
readonly connectTlsUpstream: (host: string, port: number, clientAlpn: string | undefined) => Promise<net.Socket>;
|
|
140
148
|
/** Builds the HTTP parser bound to one request handler. `onUpgrade`, when given, sees every HTTP upgrade request arriving on a terminated session; the session destroys the socket afterwards either way, with or without one, matching Node's own no-listener behaviour. */
|
|
141
149
|
readonly createHttpSession: (handler: ConnectRequestHandler, onUpgrade?: (request: IncomingMessage) => void) => HttpParserSession;
|
|
142
150
|
/** Opens a raw TCP connection for a blind tunnel. */
|
|
@@ -162,6 +170,8 @@ export interface ConnectServerConfig {
|
|
|
162
170
|
readonly upstreamFor: (host: string) => ConnectForwardTarget;
|
|
163
171
|
/** Whether a capability presented as a CONNECT request's proxy credential belongs to a live launch: the same constant-time check against the same registry the routed pipeline's admission makes, read fresh on every call because launches come and go. */
|
|
164
172
|
readonly isLiveCapability: (token: string) => boolean;
|
|
173
|
+
/** The intercept hosts that are never HTTP-parsed: terminated, tapped at the byte level, and pumped to their real host. */
|
|
174
|
+
readonly tapHosts: readonly string[];
|
|
165
175
|
/** The connection deadlines and caps; production passes `CONNECT_LIMITS`. */
|
|
166
176
|
readonly limits: ConnectLimits;
|
|
167
177
|
/** The diagnostic tap, when capturing is enabled; absent means nothing is recorded. */
|
|
@@ -179,8 +189,6 @@ export interface ConnectServerHandle {
|
|
|
179
189
|
* The connection flow: read the CONNECT head within the deadline (never more of the stream than that, so an early ClientHello glued to the head is pushed back with `unshift` and still seen by whatever consumes the socket next), authenticate it, then either blind-tunnel the target or terminate its TLS and parse HTTP on the session. Every network effect flows through `effects`; nothing here touches the network or filesystem itself.
|
|
180
190
|
*/
|
|
181
191
|
export declare function startConnectServer(config: ConnectServerConfig, effects: ConnectEffects, preferredPort: number | undefined): Promise<ConnectServerHandle>;
|
|
182
|
-
/** The real `ConnectEffects` over node's own net, tls, and http. `connectTcp` opens real connections to the CONNECTed host, so tests that want a blind tunnel redirect it. */
|
|
183
|
-
export declare function realConnectEffects(): ConnectEffects;
|
|
184
192
|
/** The real `ConnectCertStore` on the filesystem: `ca.pem` world-readable (it is public material), `ca.key` mode 0600 exactly, chmod'ed after the write because a create's mode bits pass through the process umask. */
|
|
185
193
|
export declare function realConnectCertStore(paths: {
|
|
186
194
|
readonly frontdoorCaDir: string;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type ConnectEffects } from "./connect";
|
|
2
|
+
/** The real `ConnectEffects` over node's own net, tls, and http. `connectTcp` opens real connections to the CONNECTed host, so tests that want a blind tunnel redirect it. */
|
|
3
|
+
export declare function realConnectEffects(): ConnectEffects;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as net from "node:net";
|
|
2
|
+
import type { StreamTap } from "./capture";
|
|
3
|
+
/**
|
|
4
|
+
* Pumps one already-TLS-terminated stream byte for byte to its real host over a fresh TLS connection, teeing every chunk in both directions into `tap` when one is given. This is the instrumentation for a host whose protocol the surface does not parse: the claude.ai control plane carries Remote Control on a channel that mixes shapes (observed under capture: an HTTP/1.1-shaped token request first, then binary HTTP/2 frames around it), so parsing it as either protocol would destroy or distort it. Pass everything through unchanged and record, never interpret: the frames are decoded offline, and a protocol the door does not understand keeps working exactly as the blind tunnel served it.
|
|
5
|
+
*
|
|
6
|
+
* Lifecycle mirrors `blindTunnel`: whoever goes away first takes the other side with it, so neither half of a tap session ever outlives its peer. The tap's listeners ride beside the pipes, additive like every other observer in this surface, so a recording failure fails loudly rather than silently stopping a diagnostic.
|
|
7
|
+
*/
|
|
8
|
+
export declare function pumpTapSession(secure: net.Socket, openUpstream: (clientAlpn: string | undefined) => Promise<net.Socket>, tap: StreamTap | undefined): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
* - identity and configuration-profile resolution and farm sync (`resolveDecisions`, `resyncFarm`, `buildEntryFacts`, ...), pure over facts and ports passed in;
|
|
5
5
|
* - routing: the front door's Remote-Control-preserving, capability-authenticated CONNECT surface and its certificate authority, the front-door supervisor and ensure lifecycle, and the headroom supervisor and ensure lifecycle, each pure over its injected ports;
|
|
6
6
|
* - the ambient-credential guard;
|
|
7
|
-
* - the per-identity usage snapshot a statusline or launcher reads: its schema and the reader over an injected filesystem
|
|
7
|
+
* - the per-identity usage snapshot a statusline or launcher reads: its schema and the reader over an injected filesystem;
|
|
8
|
+
* - the state root's layout (`resolveAgentShimHome`, `resolveLayoutPaths`, `buildLayoutPaths`), which includes adopting an existing `~/.claude-use` in place, and the Zod schema and inferred type of every configuration file (identity, configuration profile, provider, pool, directory rules, global config, credential), so a tool can validate or generate them with the same definitions the CLI uses.
|
|
8
9
|
*
|
|
9
10
|
* Everything the CLI alone needs (commander wiring, prompts, `doctor`, `check`) is deliberately not exported here.
|
|
10
11
|
*/
|
|
11
12
|
export { resolveDecisions, topLevelNames, type ResolveDecisionsInput, type ResolvedState } from "./resolve/pipeline";
|
|
12
13
|
export type { CompiledRule, Decision, Diagnostic, EliminatedRule, EntryFact, EntryFacts, FlattenedCascade, Layer, LayerId } from "./resolve/types";
|
|
13
14
|
export { buildEntryFacts, carryOver, FARM_MANIFEST_FILENAME, readFarmManifest, recoverFarm, recoveryDiagnostics, resyncFarm, type BuildEntryFactsParams, type CarryOverParams, type CarryOverResult, type RecoverFarmParams, type RecoveryResult, type ResyncFarmParams, type ResyncFarmResult, } from "./launcher/farm";
|
|
14
|
-
export { CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, createLeafCache, ensureCa, forwardableHeaders, generateCa, isInterceptedHost, mintLeaf, parseConnectTarget, realConnectCertStore,
|
|
15
|
+
export { CONNECT_INTERCEPT_HOST, CONNECT_INTERCEPT_HOSTS, CONNECT_LIMITS, createLeafCache, ensureCa, forwardableHeaders, generateCa, isInterceptedHost, mintLeaf, parseConnectTarget, realConnectCertStore, ROUTED_PATH_PREFIX, servedByPipeline, startConnectServer, type CaMaterial, type ConnectCertStore, type ConnectEffects, type ConnectLimits, type ConnectServerConfig, type ConnectServerHandle, type ConnectTarget, type LeafCert, } from "./frontdoor/connect";
|
|
16
|
+
export { realConnectEffects } from "./frontdoor/connectEffects";
|
|
15
17
|
export { ensureFrontDoor, FrontDoorStartError, type EnsureFrontDoorPorts } from "./frontdoor/ensure";
|
|
16
18
|
export { runFrontDoorSupervisor, type FrontDoorSupervisorPorts, type RunFrontDoorSupervisorOptions } from "./frontdoor/supervisor";
|
|
17
19
|
export { listUsageSnapshots, readUsageSnapshot, snapshotPath, UsageSnapshotError, type UsageReadFs } from "./usage/read";
|
|
@@ -19,3 +21,6 @@ export { UsageSnapshotSchema, type UsageSnapshot } from "./usage/schema";
|
|
|
19
21
|
export { ensureHeadroom, HeadroomStartError, type EnsureHeadroomPorts } from "./headroom/ensure";
|
|
20
22
|
export { resolveSupervisorConfig, runSupervisor, type HeadroomSupervisorConfig, type RunSupervisorOptions, type SupervisorPorts } from "./headroom/supervisor";
|
|
21
23
|
export { AMBIENT_CREDENTIAL_VARS, detectAmbientCredential, evaluateAmbientCredentialGuard, formatAmbientCredentialGuardMessage, type AmbientCredentialDetection, type AmbientCredentialGuardResult, type AmbientCredentialVar, type EvaluateAmbientCredentialGuardParams, type InjectedCredential, } from "./launcher/guard";
|
|
24
|
+
export { buildLayoutPaths, resolveAgentShimHome, resolveClaudeHome, resolveLayoutPaths, type LayoutPaths } from "./paths";
|
|
25
|
+
export { CliError, EXIT_FAILURE, EXIT_USAGE, UsageError } from "./cliError";
|
|
26
|
+
export { CategoryClassificationOverlaySchema, CategoryClassificationSchema, CategoryMapSchema, ConfigProfileSchema, CredentialCacheSchema, CredentialSchema, CredentialSourceSchema, DirectoryRuleSchema, DirectoryRulesSchema, EntryValueSchema, GlobalConfigSchema, IdentitySchema, PoolNameSchema, PoolSchema, PortableConfigSchema, ProviderSchema, WhenSchema, type CategoryMap, type ConfigProfile, type Credential, type CredentialSource, type DirectoryRule, type DirectoryRules, type EntryValue, type GlobalConfig, type Identity, type Pool, type PortableConfig, type Provider, type WhenCondition, } from "./config/schema";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-use",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.6.0",
|
|
4
4
|
"description": "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|