@whittlelabs/sifter 0.30.15 → 0.30.16

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 (4) hide show
  1. package/README.md +19 -1
  2. package/bin.js +26 -14
  3. package/bin.js.map +2 -2
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@ It needs three things on the machine first:
12
12
  |---|---|---|
13
13
  | Node.js | 20 or newer | [nodejs.org](https://nodejs.org), or a version manager such as [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm) |
14
14
  | git | 2.20 or newer | macOS: `xcode-select --install` (or Homebrew). Linux and WSL: your package manager, e.g. `sudo apt install git` |
15
- | Claude Code | 2.0 or newer, signed in | `npm install -g @anthropic-ai/claude-code`, then run `claude` once and sign in |
15
+ | Claude Code | 2.0.45 or newer, signed in | `npm install -g @anthropic-ai/claude-code`, then run `claude` once and sign in |
16
16
 
17
17
  On a Mac without the Command Line Tools, `/usr/bin/git` is only a placeholder that asks for them. The Sifter treats that as git not working, so install them first.
18
18
 
@@ -77,6 +77,24 @@ whittle-sifter run
77
77
 
78
78
  The Sifter subscribes to your job pool and waits for review jobs. Leave it running in a terminal or wrap it in your favorite process supervisor.
79
79
 
80
+ ### What a review can do
81
+
82
+ A review checks out the pull request and runs Claude Code on it. The pull request is someone else's code, so the review is held to reading:
83
+
84
+ - It is offered three tools, Read, Grep and Glob, and nothing else: no shell, no edits, no network tools, no subagents.
85
+ - It loads no Claude Code settings file, neither the repository's nor yours. Your allow rules, permission mode, hooks and plugins do not apply to reviews, and no MCP server starts.
86
+
87
+ Your login still works: Claude Code keeps it in your keychain or credentials file, or reads `ANTHROPIC_API_KEY`. If instead your login or provider is configured in your Claude Code settings (an `apiKeyHelper`, or an `env` block naming Bedrock, Vertex or a custom base URL), reviews will fail as signed out. Tell the Sifter to load your user settings in its `sifter.yaml` (`~/.sifter/sifter.yaml`, or `~/.sifter/<profile>/sifter.yaml` for a named profile):
88
+
89
+ ```yaml
90
+ executors:
91
+ claude-code:
92
+ type: claude-code
93
+ claudeSettings: user
94
+ ```
95
+
96
+ With it, your allow rules apply to reviews too, so a review can read whatever they let it read. The three tools, the default permission mode and the hooks staying off still hold.
97
+
80
98
  ### When something goes away
81
99
 
82
100
  A running Sifter deals with Sift or `claude` going away on its own, and says what it is doing:
package/bin.js CHANGED
@@ -10048,17 +10048,19 @@ var require_claude_code = __commonJS({
10048
10048
  var apply_1 = require_apply();
10049
10049
  var DEFAULT_TIMEOUT = 6e5;
10050
10050
  var REVIEW_TOOLS = ["Read", "Grep", "Glob"];
10051
- var REVIEW_RUN_ARGS = [
10052
- "--setting-sources",
10053
- "user",
10054
- "--strict-mcp-config",
10055
- "--tools",
10056
- REVIEW_TOOLS.join(","),
10057
- "--permission-mode",
10058
- "default",
10059
- "--settings",
10060
- JSON.stringify({ disableAllHooks: true })
10061
- ];
10051
+ function reviewRunArgs(settingSources) {
10052
+ return [
10053
+ "--setting-sources",
10054
+ settingSources,
10055
+ "--strict-mcp-config",
10056
+ "--tools",
10057
+ REVIEW_TOOLS.join(","),
10058
+ "--permission-mode",
10059
+ "default",
10060
+ "--settings",
10061
+ JSON.stringify({ disableAllHooks: true })
10062
+ ];
10063
+ }
10062
10064
  var RETIRED_READ_TOOLS = ["LS"];
10063
10065
  var HOSTED_ENV_PASSTHROUGH = [
10064
10066
  "PATH",
@@ -10091,7 +10093,7 @@ var require_claude_code = __commonJS({
10091
10093
  var READINESS_TIMEOUT_MS = 12e4;
10092
10094
  var STDERR_LIMIT = 4e3;
10093
10095
  var INSTALL_REMEDY = "install Claude Code (npm install -g @anthropic-ai/claude-code) where this process can find it on PATH";
10094
- var LOGIN_REMEDY = "run `claude` once and sign in (or set a valid ANTHROPIC_API_KEY)";
10096
+ var LOGIN_REMEDY = "run `claude` once and sign in (or set a valid ANTHROPIC_API_KEY); if your login or provider is configured in Claude Code settings (apiKeyHelper, or an env block), set `claudeSettings: user` on the claude-code executor, since a review loads no settings file without it";
10095
10097
  var LIMIT_REMEDY = "wait for the plan's usage limit to reset, or raise it";
10096
10098
  var SIGNED_OUT = /invalid api key|please run \/login|not (?:logged|signed) in|oauth token (?:has )?expired|authentication_error|invalid x-api-key/i;
10097
10099
  var OUT_OF_USAGE = /usage limit|credit balance is too low|out of (?:extra )?usage|hit your (?:\w+ )?(?:usage |spend )?limit|5-hour limit/i;
@@ -10341,8 +10343,12 @@ var require_claude_code = __commonJS({
10341
10343
  const outputLabel = spec.outputLabel;
10342
10344
  const model = modelOverride ?? this.config.model;
10343
10345
  const allowedTools = local ? this.config.allowedTools : checkoutScopedTools(this.config.allowedTools);
10346
+ if (!local && this.config.claudeSettings === "user") {
10347
+ throw new Error("claude-code: `claudeSettings: user` is for an installed Sifter whose login lives in Claude Code settings; a hosted run authenticates with the key it is handed and loads no settings");
10348
+ }
10349
+ const settingSources = local && this.config.claudeSettings === "user" ? "user" : "";
10344
10350
  return new Promise((resolve, reject) => {
10345
- const args = ["--print", "--output-format", "stream-json", "--verbose", ...REVIEW_RUN_ARGS];
10351
+ const args = ["--print", "--output-format", "stream-json", "--verbose", ...reviewRunArgs(settingSources)];
10346
10352
  if (resumeSessionId)
10347
10353
  args.push("--resume", resumeSessionId);
10348
10354
  if (spec.outputSchema && typeof spec.outputSchema === "object" && Object.keys(spec.outputSchema).length > 0) {
@@ -10542,6 +10548,12 @@ var require_claude_code = __commonJS({
10542
10548
  }
10543
10549
  validated.keepTranscripts = config.keepTranscripts;
10544
10550
  }
10551
+ if (config.claudeSettings !== void 0) {
10552
+ if (config.claudeSettings !== "user") {
10553
+ throw new Error('"claudeSettings" may only be "user" (leave it unset to load no settings file)');
10554
+ }
10555
+ validated.claudeSettings = "user";
10556
+ }
10545
10557
  if (config.overlayAllowedHosts !== void 0) {
10546
10558
  if (!Array.isArray(config.overlayAllowedHosts) || !config.overlayAllowedHosts.every((h) => typeof h === "string")) {
10547
10559
  throw new Error('"overlayAllowedHosts" must be an array of strings');
@@ -26922,7 +26934,7 @@ var import_path = require("path");
26922
26934
  var import_promises = require("fs/promises");
26923
26935
  var import_yaml = __toESM(require_dist3());
26924
26936
  var import_shuttle = __toESM(require_dist5());
26925
- var buildVersion = true ? "0.30.15" : pkg.version;
26937
+ var buildVersion = true ? "0.30.16" : pkg.version;
26926
26938
  var sifterBrand = {
26927
26939
  product: {
26928
26940
  id: "sifter",