@rendotdev/rig 0.0.22 → 0.0.23

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 CHANGED
@@ -62,23 +62,19 @@ Do not implement anything yet. Ask the user which workflow they want to implemen
62
62
 
63
63
  > Are you an AI agent looking for how to use rig? Assume the following:
64
64
 
65
- The `rig` CLI is installed on this machine. It allows you to write, run and own local tools and scripts in a typed runtime.
66
-
67
- - To sync all tools to AGENTS.md and CLAUDE.md, run `rig` (or `rig init`).
68
- - To discover available tools, run `rig list`.
69
- - To learn about a tool's usage, run `rig help <tool>`.
70
- - To run a tool, use `rig run <tool>.<command> [args]`.
71
- - Tools run under Bun with fallback auto-install enabled, so tool files can import npm packages; add explicit package versions when reproducibility matters.
72
- - To schedule a tool command, use `rig cron add <name> <tool>.<command> <schedule> --input '<json>'`; use `rig cron list`, `rig cron run <name>`, and `rig cron remove <name>` to manage scheduled runs.
73
- - If a tool needs local secrets or settings, put them in the tool folder's `.env`, add an `env` Zod schema to the tool definition, and read validated values from `context.env`.
74
- - To create a new tool, run `rig create <tool>`.
75
- - To edit an existing tool, run `rig edit <tool>` and open the printed file path.
76
- - To remove an existing tool, run `rig remove <tool>`.
77
- - To list tool registries, run `rig registry list`.
78
- - To add a registry, run `rig registry create [path]` (defaults to current directory).
79
- - Use `context.log` for structured Pino logs with a default tool command prefix; Rig writes logs to `~/rig/.logs`, rolls files by size, and keeps seven days.
80
- - Use `context.kv.set(key, value)` and `context.kv.get(key)` for lightweight JSON state in `kv.sqlite` beside the tool entry file.
81
- - If a tool needs relational persistent state, define `setupDb` and use `context.db`; Rig stores that SQLite database beside the tool entry file as `index.sqlite`.
65
+ The `rig` CLI is installed on this machine. It lets agents discover, run, and create local typed tools.
66
+
67
+ - Run `rig` (or `rig init`) to set up or sync rig. This also updates detected AGENTS.md and CLAUDE.md files with available rig tools.
68
+ - Run `rig create <tool>` when the user asks you to turn a repeatable workflow into a reusable tool.
69
+ - Run `rig edit <tool>` to print the tool file path for editing.
70
+ - Run `rig remove <tool>` to remove a local tool.
71
+ - Run `rig cron --help` to schedule and manage tool commands.
72
+ - Run `rig typecheck <tool>` to validate a tool's TypeScript and runtime types.
73
+ - Run `rig env <tool> KEY=VALUE` to configure tool secrets/settings; run `rig env <tool> remove KEY` to remove them.
74
+ - Run `rig list` to discover tools and available `rig run ...` commands.
75
+ - Run `rig help <tool>` or `rig help <tool>.<command>` for usage, inputs, and outputs.
76
+ - Run `rig run <tool>.<command> [args]` to execute a tool command.
77
+ - Run `rig --help` for other Rig CLI commands.
82
78
 
83
79
  When rig runs, it keeps detected `AGENTS.md` and `CLAUDE.md` files updated with these instructions and the current `rig list` output.
84
80
 
@@ -236,7 +236,7 @@ class RigCommandRunnerRuntime {
236
236
  }
237
237
  async run(options) {
238
238
  const target = this.commandTarget(options);
239
- const { ToolRunner } = await import("./run-mvhmkkfe.js");
239
+ const { ToolRunner } = await import("./run-ngbemhx5.js");
240
240
  const result = await new ToolRunner(this.options).run(target.tool, target.command, {
241
241
  ...this.options,
242
242
  args: options.args,
@@ -502,7 +502,10 @@ class ToolLoader {
502
502
  validateCommandName(name) {
503
503
  this.validator.validateCommandName(name);
504
504
  }
505
- async loadDiscovered(tool) {
505
+ async loadDefinition(name) {
506
+ return this.loadDefinitionDiscovered(await this.discovery.find(name));
507
+ }
508
+ async loadDefinitionDiscovered(tool) {
506
509
  const url = `${pathToFileURL(tool.toolPath).href}?rig=${Date.now()}`;
507
510
  let moduleValue;
508
511
  try {
@@ -516,8 +519,12 @@ class ToolLoader {
516
519
  const moduleRecord = moduleValue;
517
520
  const definitionValue = await this.evaluateModuleDefault(moduleRecord.default, tool.name);
518
521
  const definition = this.validator.validateToolDefinition(definitionValue, tool.name);
519
- const env = await this.envLoader.load(tool, definition);
520
- return { name: definition.name, path: tool.toolPath, env, definition };
522
+ return { name: definition.name, path: tool.toolPath, definition };
523
+ }
524
+ async loadDiscovered(tool) {
525
+ const loaded = await this.loadDefinitionDiscovered(tool);
526
+ const env = await this.envLoader.load(tool, loaded.definition);
527
+ return { ...loaded, env };
521
528
  }
522
529
  async evaluateModuleDefault(value, toolName) {
523
530
  const awaitedValue = await Promise.resolve(value);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ToolRunner
3
- } from "./cli-eavzwv49.js";
3
+ } from "./cli-d9b8eefw.js";
4
4
  import {
5
5
  RigConfigStore
6
6
  } from "./cli-043bae8s.js";
@@ -5,7 +5,7 @@ import {
5
5
  CommandIds,
6
6
  ToolLoader,
7
7
  createRigToolKit
8
- } from "./cli-dqz4gvqd.js";
8
+ } from "./cli-4e71j0m0.js";
9
9
  import {
10
10
  RigError,
11
11
  RigErrors
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  CommandIds,
6
6
  ToolLoader
7
- } from "./cli-dqz4gvqd.js";
7
+ } from "./cli-4e71j0m0.js";
8
8
  import {
9
9
  ToolDiscoveryService
10
10
  } from "./cli-ahwyqf1f.js";
@@ -95,9 +95,9 @@ class ToolListPlainRenderer {
95
95
  return `${tool.name} # ${this.formatter.description(tool.description)}`;
96
96
  }
97
97
  renderCommand(command) {
98
- const args = this.formatter.example(command.runExample.replace(`rig run ${command.id}`, ""));
98
+ const runExample = this.formatter.example(command.runExample);
99
99
  const description = this.formatter.description(command.description);
100
- return ` ${command.id}${args ? ` ${args}` : ""} # ${description}`;
100
+ return ` ${runExample} # ${description}`;
101
101
  }
102
102
  }
103
103
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ToolLoader
3
- } from "./cli-dqz4gvqd.js";
3
+ } from "./cli-4e71j0m0.js";
4
4
  import {
5
5
  RigToolEntryFiles,
6
6
  ToolDiscoveryService
@@ -2,10 +2,10 @@ import {
2
2
  RigCronService,
3
3
  RigCronWorker,
4
4
  cronModuleUrl
5
- } from "./cli-1ssn3a04.js";
6
- import"./cli-eavzwv49.js";
5
+ } from "./cli-85va7m21.js";
6
+ import"./cli-d9b8eefw.js";
7
7
  import"./cli-zbp3334x.js";
8
- import"./cli-dqz4gvqd.js";
8
+ import"./cli-4e71j0m0.js";
9
9
  import"./cli-ahwyqf1f.js";
10
10
  import"./cli-043bae8s.js";
11
11
  import"./cli-1c7te5cg.js";
@@ -0,0 +1,190 @@
1
+ import {
2
+ SchemaRenderer
3
+ } from "./cli-zbp3334x.js";
4
+ import {
5
+ ToolLoader
6
+ } from "./cli-4e71j0m0.js";
7
+ import"./cli-ahwyqf1f.js";
8
+ import"./cli-043bae8s.js";
9
+ import {
10
+ RigError
11
+ } from "./cli-1c7te5cg.js";
12
+ import"./cli-32dzwg3p.js";
13
+ import"./cli-b7jgjgy7.js";
14
+
15
+ // src/tools/env.ts
16
+ import { existsSync } from "node:fs";
17
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
18
+ import { dirname, join } from "node:path";
19
+ class ToolEnvTarget {
20
+ tool;
21
+ constructor(tool) {
22
+ this.tool = tool;
23
+ }
24
+ static parse(value) {
25
+ if (value && !value.includes("."))
26
+ return new ToolEnvTarget(value);
27
+ throw new RigError("INPUT_ERROR", `Env target must use <tool>: ${value}`);
28
+ }
29
+ }
30
+
31
+ class EnvKeyParser {
32
+ parse(keys) {
33
+ if (keys.length === 0) {
34
+ throw new RigError("INPUT_ERROR", "Env remove expects at least one KEY.");
35
+ }
36
+ return keys.map((key) => this.parseOne(key));
37
+ }
38
+ parseOne(key) {
39
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
40
+ throw new RigError("INPUT_ERROR", `Env key must be a valid shell variable name: ${key}`);
41
+ }
42
+ return key;
43
+ }
44
+ }
45
+
46
+ class EnvAssignmentParser {
47
+ parse(assignments) {
48
+ return Object.fromEntries(assignments.map((assignment) => this.parseOne(assignment)));
49
+ }
50
+ parseOne(assignment) {
51
+ const separator = assignment.indexOf("=");
52
+ const key = assignment.slice(0, separator);
53
+ if (separator <= 0 || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
54
+ throw new RigError("INPUT_ERROR", `Env assignment must use KEY=VALUE: ${assignment}`);
55
+ }
56
+ return [key, assignment.slice(separator + 1)];
57
+ }
58
+ }
59
+
60
+ class DotEnvDocument {
61
+ parse(source, path) {
62
+ const values = {};
63
+ for (const [index, line] of source.split(/\r?\n/).entries()) {
64
+ const parsed = this.parseLine(line, path, index + 1);
65
+ if (parsed)
66
+ values[parsed.key] = parsed.value;
67
+ }
68
+ return values;
69
+ }
70
+ serialize(values) {
71
+ const lines = Object.entries(values).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}=${this.renderValue(value)}`);
72
+ return `${lines.join(`
73
+ `)}
74
+ `;
75
+ }
76
+ parseLine(line, path, lineNumber) {
77
+ const trimmed = line.trim();
78
+ if (!trimmed || trimmed.startsWith("#"))
79
+ return;
80
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(trimmed);
81
+ if (!match) {
82
+ throw new RigError("TOOL_INVALID", "Invalid .env line.", { path, line: lineNumber });
83
+ }
84
+ return { key: match[1], value: this.parseValue(match[2]) };
85
+ }
86
+ parseValue(value) {
87
+ const trimmed = value.trim();
88
+ if (trimmed.length < 2)
89
+ return trimmed;
90
+ if (trimmed[0] === '"' && trimmed.at(-1) === '"')
91
+ return JSON.parse(trimmed);
92
+ if (trimmed[0] === "'" && trimmed.at(-1) === "'")
93
+ return trimmed.slice(1, -1);
94
+ return trimmed;
95
+ }
96
+ renderValue(value) {
97
+ if (/^[A-Za-z0-9_./:=@%+,-]*$/.test(value))
98
+ return value;
99
+ return JSON.stringify(value);
100
+ }
101
+ }
102
+
103
+ class EnvSchemaSummary {
104
+ entries(schema, values) {
105
+ const jsonSchema = SchemaRenderer.toJsonSchema(schema);
106
+ if (!this.isRecord(jsonSchema) || !this.isRecord(jsonSchema.properties))
107
+ return [];
108
+ const required = Array.isArray(jsonSchema.required) ? jsonSchema.required : [];
109
+ return Object.keys(jsonSchema.properties).toSorted().map((key) => ({
110
+ key,
111
+ required: required.includes(key),
112
+ set: values[key] !== undefined
113
+ }));
114
+ }
115
+ isRecord(value) {
116
+ return typeof value === "object" && value !== null && !Array.isArray(value);
117
+ }
118
+ }
119
+
120
+ class ToolEnvService {
121
+ loader;
122
+ assignments = new EnvAssignmentParser;
123
+ keys = new EnvKeyParser;
124
+ document = new DotEnvDocument;
125
+ summary = new EnvSchemaSummary;
126
+ constructor(options = {}) {
127
+ this.loader = new ToolLoader(options);
128
+ }
129
+ async configure(targetValue, assignments = []) {
130
+ const target = ToolEnvTarget.parse(targetValue);
131
+ const loaded = await this.loader.loadDefinition(target.tool);
132
+ if (!loaded.definition.env) {
133
+ throw new RigError("TOOL_INVALID", `Tool ${target.tool} does not define an env schema.`, {
134
+ tool: target.tool
135
+ });
136
+ }
137
+ const envPath = join(dirname(loaded.path), ".env");
138
+ const existing = await this.readEnv(envPath);
139
+ if (assignments.length === 0) {
140
+ return this.result(target, envPath, false, existing, loaded.definition.env, [], []);
141
+ }
142
+ if (assignments[0] === "remove") {
143
+ const keys = this.keys.parse(assignments.slice(1));
144
+ const nextValues2 = { ...existing };
145
+ const removedKeys = keys.filter((key) => (key in nextValues2));
146
+ for (const key of keys)
147
+ delete nextValues2[key];
148
+ this.validateEnv(target, envPath, loaded.definition.env, nextValues2);
149
+ if (removedKeys.length > 0)
150
+ await this.writeEnv(envPath, nextValues2);
151
+ return this.result(target, envPath, removedKeys.length > 0, nextValues2, loaded.definition.env, [], removedKeys);
152
+ }
153
+ const updates = this.assignments.parse(assignments);
154
+ const nextValues = { ...existing, ...updates };
155
+ this.validateEnv(target, envPath, loaded.definition.env, nextValues);
156
+ await this.writeEnv(envPath, nextValues);
157
+ return this.result(target, envPath, true, nextValues, loaded.definition.env, Object.keys(updates), []);
158
+ }
159
+ validateEnv(target, envPath, schema, values) {
160
+ const validation = schema.safeParse(values);
161
+ if (validation.success)
162
+ return;
163
+ throw new RigError("TOOL_INVALID", `Tool ${target.tool} env would be invalid.`, {
164
+ path: envPath,
165
+ errors: validation.error?.flatten()
166
+ });
167
+ }
168
+ result(target, envPath, updated, values, schema, updatedKeys, removedKeys) {
169
+ return {
170
+ tool: target.tool,
171
+ envPath,
172
+ updated,
173
+ entries: this.summary.entries(schema, values),
174
+ updatedKeys: updatedKeys.toSorted(),
175
+ removedKeys: removedKeys.toSorted()
176
+ };
177
+ }
178
+ async readEnv(path) {
179
+ if (!existsSync(path))
180
+ return {};
181
+ return this.document.parse(await readFile(path, "utf8"), path);
182
+ }
183
+ async writeEnv(path, values) {
184
+ await mkdir(dirname(path), { recursive: true });
185
+ await writeFile(path, this.document.serialize(values), "utf8");
186
+ }
187
+ }
188
+ export {
189
+ ToolEnvService
190
+ };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  CommandIds,
6
6
  ToolLoader
7
- } from "./cli-dqz4gvqd.js";
7
+ } from "./cli-4e71j0m0.js";
8
8
  import"./cli-ahwyqf1f.js";
9
9
  import"./cli-043bae8s.js";
10
10
  import {
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  CommandIds,
6
6
  ToolLoader
7
- } from "./cli-dqz4gvqd.js";
7
+ } from "./cli-4e71j0m0.js";
8
8
  import"./cli-ahwyqf1f.js";
9
9
  import"./cli-043bae8s.js";
10
10
  import {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ToolListService
3
- } from "./cli-q2ajq5qe.js";
3
+ } from "./cli-exxbjsry.js";
4
4
  import"./cli-zbp3334x.js";
5
- import"./cli-dqz4gvqd.js";
5
+ import"./cli-4e71j0m0.js";
6
6
  import"./cli-ahwyqf1f.js";
7
7
  import"./cli-043bae8s.js";
8
8
  import"./cli-1c7te5cg.js";
package/dist/rig.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RigCronWorker
4
- } from "./cli-1ssn3a04.js";
4
+ } from "./cli-85va7m21.js";
5
5
  import {
6
6
  RigLoggerFactory
7
- } from "./cli-eavzwv49.js";
7
+ } from "./cli-d9b8eefw.js";
8
8
  import"./cli-zbp3334x.js";
9
- import"./cli-dqz4gvqd.js";
9
+ import"./cli-4e71j0m0.js";
10
10
  import"./cli-ahwyqf1f.js";
11
11
  import {
12
12
  RigPackageRoot
@@ -96,6 +96,7 @@ class CliApplication {
96
96
  this.configureCreateCommand();
97
97
  this.configureEditCommand();
98
98
  this.configureRemoveCommand();
99
+ this.configureEnvCommand();
99
100
  this.configureRunCommand();
100
101
  this.configureCronCommands();
101
102
  this.configureTypecheckCommand();
@@ -112,7 +113,7 @@ class CliApplication {
112
113
  return;
113
114
  }
114
115
  this.requestGeneratedSync();
115
- const { ToolHelpService } = await import("./help-kg1zhj6n.js");
116
+ const { ToolHelpService } = await import("./help-24c9vwxh.js");
116
117
  console.log(await new ToolHelpService(this.pathOptions()).render(target));
117
118
  });
118
119
  }
@@ -159,7 +160,7 @@ class CliApplication {
159
160
  configureListCommand() {
160
161
  this.program.command("list").alias("ls").description("List discovered tools and commands.").option("--json", "Print full JSON metadata.").option("--plain", "Print a compact plain text command list.").option("--for-path <path>", "Only list tools from registries visible from a path.").action(async (commandOptions) => {
161
162
  this.requestGeneratedSync();
162
- const { ToolListService } = await import("./list-2n0p40dn.js");
163
+ const { ToolListService } = await import("./list-jfcspwm7.js");
163
164
  const service = new ToolListService(this.pathOptions());
164
165
  const data = await service.list({ visibleFromPath: commandOptions.forPath });
165
166
  if (commandOptions.json)
@@ -171,7 +172,7 @@ class CliApplication {
171
172
  configureInspectCommand() {
172
173
  this.program.command("inspect").argument("<target>", "Tool name or command id (<tool>.<command>.)").description("Print tool or command metadata as JSON.").action(async (target) => {
173
174
  this.requestGeneratedSync();
174
- const { ToolInspector } = await import("./inspect-vqtm5htv.js");
175
+ const { ToolInspector } = await import("./inspect-mb0n7sjg.js");
175
176
  this.printJson(await new ToolInspector(this.pathOptions()).inspect(target));
176
177
  });
177
178
  }
@@ -184,7 +185,7 @@ class CliApplication {
184
185
  configureEditCommand() {
185
186
  this.program.command("edit").argument("<tool>").description("Print the TypeScript file path for a tool.").action(async (name) => {
186
187
  this.requestGeneratedSync();
187
- const { ToolFileService } = await import("./create-pnsj60ym.js");
188
+ const { ToolFileService } = await import("./create-bvzszsyt.js");
188
189
  const result = await new ToolFileService(this.pathOptions()).path(name);
189
190
  console.log(result.toolPath);
190
191
  });
@@ -192,12 +193,19 @@ class CliApplication {
192
193
  configureRemoveCommand() {
193
194
  this.program.command("remove").argument("<tool>").description("Remove a local tool directory.").action(async (name) => {
194
195
  this.requestGeneratedSync();
195
- const { ToolRemover } = await import("./create-pnsj60ym.js");
196
+ const { ToolRemover } = await import("./create-bvzszsyt.js");
196
197
  const result = await new ToolRemover(this.pathOptions()).remove(name);
197
198
  console.log(`Removed tool ${result.name}`);
198
199
  console.log(`Tool directory: ${result.toolDir}`);
199
200
  });
200
201
  }
202
+ configureEnvCommand() {
203
+ this.program.command("env").argument("<tool>", "Tool name.").argument("[assignments...]", "Use KEY=VALUE to set values, or remove KEY [KEY...] to remove values.").description("Show, write, or remove tool .env values using its env schema.").action(async (target, assignments) => {
204
+ this.requestGeneratedSync();
205
+ const { ToolEnvService } = await import("./env-9kd3dqkx.js");
206
+ this.printJson(await new ToolEnvService(this.pathOptions()).configure(target, assignments));
207
+ });
208
+ }
201
209
  configureRunCommand() {
202
210
  this.program.command("run").argument("<command>", "Command id, formatted as <tool>.<command>.").argument("[args...]", "Command arguments.").description("Run a tool command.").option("--input <json>", "JSON input string.").option("--input-file <path>", "Read JSON input from a file.").option("--dry-run", "Validate input and show what would run without executing.").action(async (commandId, args, commandOptions) => {
203
211
  this.requestGeneratedSync();
@@ -207,11 +215,11 @@ class CliApplication {
207
215
  configureCronCommands() {
208
216
  const cronCommand = this.program.command("cron").description("Manage scheduled Rig tool commands.");
209
217
  cronCommand.command("list").description("List scheduled Rig tool commands as JSON.").action(async () => {
210
- const { RigCronService } = await import("./cron-zhb9hpbs.js");
218
+ const { RigCronService } = await import("./cron-n15qfj8m.js");
211
219
  this.printJson(await new RigCronService(this.pathOptions()).list());
212
220
  });
213
221
  cronCommand.command("add").argument("<name>", "Unique job name, using letters, numbers, hyphens, or underscores.").argument("<command>", "Command id, formatted as <tool>.<command>.").argument("<schedule>", "Cron expression or nickname, such as @weekly.").description("Schedule a Rig tool command with fixed JSON input.").option("--input <json>", "JSON input string.").option("--input-file <path>", "Read JSON input from a file.").action(async (name, commandId, schedule, commandOptions) => {
214
- const { cronModuleUrl, RigCronService } = await import("./cron-zhb9hpbs.js");
222
+ const { cronModuleUrl, RigCronService } = await import("./cron-n15qfj8m.js");
215
223
  const result = await new RigCronService(this.pathOptions()).add({
216
224
  name,
217
225
  command: commandId,
@@ -223,11 +231,11 @@ class CliApplication {
223
231
  this.printJson(result);
224
232
  });
225
233
  cronCommand.command("remove").argument("<name>", "Cron job name.").description("Remove a scheduled Rig tool command.").action(async (name) => {
226
- const { RigCronService } = await import("./cron-zhb9hpbs.js");
234
+ const { RigCronService } = await import("./cron-n15qfj8m.js");
227
235
  this.printJson(await new RigCronService(this.pathOptions()).remove(name));
228
236
  });
229
237
  cronCommand.command("run").argument("<name>", "Cron job name.").description("Run a scheduled Rig tool command now.").action(async (name) => {
230
- const { RigCronService } = await import("./cron-zhb9hpbs.js");
238
+ const { RigCronService } = await import("./cron-n15qfj8m.js");
231
239
  const result = await new RigCronService(this.pathOptions()).run(name);
232
240
  this.printJson(result.envelope);
233
241
  process.exitCode = result.exitCode;
@@ -236,7 +244,7 @@ class CliApplication {
236
244
  configureTypecheckCommand() {
237
245
  this.program.command("typecheck").argument("[tool]").description("Type-check local tool files with the injected Rig tool runtime types.").action(async (tool) => {
238
246
  this.requestGeneratedSync();
239
- const { ToolTypecheckService } = await import("./typecheck-c944bvz2.js");
247
+ const { ToolTypecheckService } = await import("./typecheck-6q579sqn.js");
240
248
  const result = await new ToolTypecheckService(this.pathOptions()).typecheck(tool);
241
249
  this.printJson(result);
242
250
  process.exitCode = result.exitCode;
@@ -289,7 +297,7 @@ class CliApplication {
289
297
  });
290
298
  }
291
299
  async runToolCommand(commandId, args, commandOptions) {
292
- const { ToolRunner } = await import("./run-mvhmkkfe.js");
300
+ const { ToolRunner } = await import("./run-ngbemhx5.js");
293
301
  const commandTarget = this.commandTarget(commandId);
294
302
  const result = await new ToolRunner(this.pathOptions()).run(commandTarget.tool, commandTarget.command, {
295
303
  ...this.pathOptions(),
@@ -332,7 +340,7 @@ Run "rig doctor" if you want to verify your setup.`);
332
340
  await this.printUpdateNotice(currentVersion);
333
341
  }
334
342
  async createTool(name) {
335
- const { ToolCreator } = await import("./create-pnsj60ym.js");
343
+ const { ToolCreator } = await import("./create-bvzszsyt.js");
336
344
  const result = await new ToolCreator(this.pathOptions()).create(name);
337
345
  console.log(`Created tool ${result.name}`);
338
346
  console.log(`
@@ -414,13 +422,13 @@ ${notice.message}`);
414
422
  }
415
423
  async syncGeneratedFiles() {
416
424
  await this.ignoreSyncErrors(async () => {
417
- const { ToolRuntimeCommentSyncService } = await import("./runtime-comment-n9aft3g5.js");
425
+ const { ToolRuntimeCommentSyncService } = await import("./runtime-comment-gbermtjx.js");
418
426
  await new ToolRuntimeCommentSyncService(this.pathOptions()).sync();
419
427
  });
420
428
  if (process.env.RIG_AGENT_SYNC === "0")
421
429
  return;
422
430
  await this.ignoreSyncErrors(async () => {
423
- const { AgentInstructionSyncService } = await import("./sync-javg558s.js");
431
+ const { AgentInstructionSyncService } = await import("./sync-7x553cky.js");
424
432
  await new AgentInstructionSyncService(this.pathOptions()).sync();
425
433
  });
426
434
  }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ToolRunner
3
- } from "./cli-eavzwv49.js";
3
+ } from "./cli-d9b8eefw.js";
4
4
  import"./cli-zbp3334x.js";
5
- import"./cli-dqz4gvqd.js";
5
+ import"./cli-4e71j0m0.js";
6
6
  import"./cli-ahwyqf1f.js";
7
7
  import"./cli-043bae8s.js";
8
8
  import"./cli-1c7te5cg.js";
@@ -18,11 +18,14 @@ Rig tool runtime:
18
18
  - \`rig.defineTool(definition)\` defines the tool.
19
19
  - \`rig.defineCommand(definition)\` defines one command with \`{ description, input, output, run }\`.
20
20
  - Use \`rig.z.object({ ... })\` for input/output schemas.
21
+ - Tools run under Bun with fallback auto-install enabled, so tool files can import npm packages; add explicit package versions when reproducibility matters.
21
22
  - \`rig.run({ command: "tool.command", input })\` runs another registered Rig command and returns its data.
22
23
  - \`rig.$\` runs a Bun Shell tagged template command with escaped interpolations. Docs: https://bun.com/docs/runtime/shell
23
24
  - \`rig.args()\` builds argv arrays with \`.raw()\`, \`.flag()\`, \`.value()\`, \`.values()\`, and \`.toArray()\`.
24
25
  - \`rig.paths.home()\`, \`rig.paths.resolve(cwd, path)\`, \`rig.paths.ensureParent(path)\`, and \`rig.paths.size(path)\` cover common path work.
25
- - Add \`env: rig.z.object({ KEY: rig.z.string() })\` to validate a \`.env\` file beside the tool entry file and receive parsed values on \`context.env\`.
26
+ - Add \`env: rig.z.object({ KEY: rig.z.string() })\` to validate local secrets or settings and receive parsed values on \`context.env\`.
27
+ - Run \`rig env <tool> KEY=VALUE\` to write the tool \`.env\` file; run \`rig env <tool> remove KEY\` to remove a value.
28
+ - To add another registry for tool files, run \`rig registry create [path]\` (defaults to current directory).
26
29
 
27
30
  Tool logging and key-value state:
28
31
  - Use \`context.log.info(...)\`, \`context.log.warn(...)\`, or another Pino-style method for structured logs with a default \`tool:<tool>.<command>\` prefix.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ToolListService
3
- } from "./cli-q2ajq5qe.js";
3
+ } from "./cli-exxbjsry.js";
4
4
  import"./cli-zbp3334x.js";
5
- import"./cli-dqz4gvqd.js";
5
+ import"./cli-4e71j0m0.js";
6
6
  import"./cli-ahwyqf1f.js";
7
7
  import"./cli-043bae8s.js";
8
8
  import"./cli-1c7te5cg.js";
@@ -17,28 +17,25 @@ import { readFile, realpath, stat, writeFile } from "node:fs/promises";
17
17
  import { dirname, isAbsolute, join, resolve } from "node:path";
18
18
 
19
19
  // src/agents/instructions.ts
20
- var RigAgentInstructions = `The \`rig\` CLI is installed on this machine. It allows you to write, run and own local tools and scripts in a typed runtime.
20
+ var RigAgentInstructions = `The \`rig\` CLI is installed on this machine. It lets agents discover, run, and create local typed tools.
21
21
 
22
- - To sync all tools to AGENTS.md and CLAUDE.md, run \`rig\` (or \`rig init\`).
23
- - To discover available tools, run \`rig list\`.
24
- - To learn about a tool's usage, run \`rig help <tool>\`.
25
- - To run a tool, use \`rig run <tool>.<command> [args]\`.
26
- - Tools run under Bun with fallback auto-install enabled, so tool files can import npm packages; add explicit package versions when reproducibility matters.
27
- - To schedule a tool command, use \`rig cron add <name> <tool>.<command> <schedule> --input '<json>'\`; use \`rig cron list\`, \`rig cron run <name>\`, and \`rig cron remove <name>\` to manage scheduled runs.
28
- - If a tool needs local secrets or settings, put them in the tool folder's \`.env\`, add an \`env\` Zod schema to the tool definition, and read validated values from \`context.env\`.
29
- - To create a new tool, run \`rig create <tool>\`.
30
- - To edit an existing tool, run \`rig edit <tool>\` and open the printed file path.
31
- - To remove an existing tool, run \`rig remove <tool>\`.
32
- - To list tool registries, run \`rig registry list\`.
33
- - To add a registry, run \`rig registry create [path]\` (defaults to current directory).
34
- - Use \`context.log\` for structured Pino logs with a default tool command prefix; Rig writes logs to \`~/rig/.logs\`, rolls files by size, and keeps seven days.
35
- - Use \`context.kv.set(key, value)\` and \`context.kv.get(key)\` for lightweight JSON state in \`kv.sqlite\` beside the tool entry file.
36
- - If a tool needs relational persistent state, define \`setupDb\` and use \`context.db\`; Rig stores that SQLite database beside the tool entry file as \`index.sqlite\`.
22
+ - Run \`rig\` (or \`rig init\`) to set up or sync rig. This also updates detected AGENTS.md and CLAUDE.md files with available rig tools.
23
+ - Run \`rig create <tool>\` when the user asks you to turn a repeatable workflow into a reusable tool.
24
+ - Run \`rig edit <tool>\` to print the tool file path for editing.
25
+ - Run \`rig remove <tool>\` to remove a local tool.
26
+ - Run \`rig cron --help\` to schedule and manage tool commands.
27
+ - Run \`rig typecheck <tool>\` to validate a tool's TypeScript and runtime types.
28
+ - Run \`rig env <tool> KEY=VALUE\` to configure tool secrets/settings; run \`rig env <tool> remove KEY\` to remove them.
29
+ - Run \`rig list\` to discover tools and available \`rig run ...\` commands.
30
+ - Run \`rig help <tool>\` or \`rig help <tool>.<command>\` for usage, inputs, and outputs.
31
+ - Run \`rig run <tool>.<command> [args]\` to execute a tool command.
32
+ - Run \`rig --help\` for other Rig CLI commands.
37
33
  `;
38
34
 
39
35
  // src/agents/sync.ts
40
36
  var StartMarker = "<!-- rig:agent-instructions:start -->";
41
37
  var EndMarker = "<!-- rig:agent-instructions:end -->";
38
+ var IgnoreMarker = "<!-- rig:ignore -->";
42
39
  var AgentInstructionSyncLocations = {
43
40
  projectFiles: ["AGENTS.md", "CLAUDE.md"],
44
41
  projectClaudeDirectories: [".claude"],
@@ -109,12 +106,15 @@ ${EndMarker}`;
109
106
  return this.listService.renderPlain(await this.listService.list(options));
110
107
  }
111
108
  async addExistingFile(targets, path, scope) {
112
- if (await this.isFile(path))
109
+ if (await this.isFile(path) && !await this.isIgnored(path)) {
113
110
  await this.setTarget(targets, path, true, scope);
111
+ }
114
112
  }
115
113
  async addClaudeDirectoryTarget(targets, directory, scope) {
116
114
  const path = join(directory, "CLAUDE.md");
117
115
  const fileExists = await this.isFile(path);
116
+ if (fileExists && await this.isIgnored(path))
117
+ return;
118
118
  const directoryExists = fileExists ? false : await this.isDirectory(directory);
119
119
  if (fileExists || directoryExists)
120
120
  await this.setTarget(targets, path, fileExists, scope);
@@ -164,7 +164,7 @@ ${EndMarker}`;
164
164
  async setTarget(targets, path, existed, scope) {
165
165
  const key = existed ? await this.realPath(path) : path;
166
166
  const current = targets.get(key);
167
- const nextScope = current?.scope === "visible" || scope === "visible" ? "visible" : "all";
167
+ const nextScope = current?.scope === "all" || scope === "all" ? "all" : "visible";
168
168
  if (!current || path < current.path)
169
169
  targets.set(key, { path, existed, scope: nextScope });
170
170
  else
@@ -211,6 +211,13 @@ ${EndMarker}`;
211
211
  escapeRegExp(value) {
212
212
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
213
213
  }
214
+ async isIgnored(path) {
215
+ try {
216
+ return (await this.readText(path)).includes(IgnoreMarker);
217
+ } catch {
218
+ return false;
219
+ }
220
+ }
214
221
  async realPath(path) {
215
222
  try {
216
223
  return await realpath(path);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ToolLoader
3
- } from "./cli-dqz4gvqd.js";
3
+ } from "./cli-4e71j0m0.js";
4
4
  import {
5
5
  ToolDiscoveryService
6
6
  } from "./cli-ahwyqf1f.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rendotdev/rig",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "Local typed command runtime for agents.",
5
5
  "homepage": "https://github.com/rendotdev/rig#readme",
6
6
  "bugs": {