Skip to content

jigs ​

Factory and workflow definitions, harness and model descriptors, types and pure helpers.

Durable steps and routines come from the factory-generated #jigs/steps and #jigs/routines.

Example ​

ts
import { defineWorkflow, harnesses } from "@jigs-ai/jigs";
import { runAgent } from "#jigs/routines";

Factory and workflows ​

EventTrigger ​

A trigger that starts one run per occurrence its source reports, at most once per occurrence. Each run gets the reference the source hands it, merged over the fixed inputs.

Remarks ​

A new trigger starts from the moment the service first runs it, with no backfill. After the service was down, it starts runs only for occurrences within lookbackMinutes and records older ones as skipped.

Properties ​

PropertyTypeDescription
activebooleanAn inactive trigger is not armed: its source's occurrences start no runs.
inputs?Record<string, unknown>-
lookbackMinutes?numberHow far back to catch up after the service was down. Defaults to 60.
maxActive?numberRuns of this trigger active at once. Defaults to 20; further occurrences wait, oldest first.
sourceSourceDescriptor-
workflowstring-

Factory ​

What a factory repo hands the service: its workflows, keyed by name, and the schedules and event triggers that start them. A schedule is keyed by its own name rather than nested under a workflow. The name is what runs, status and jigs doctor refer to, and one workflow can carry several.

Properties ​

PropertyType
schedules?Record<string, Schedule>
triggers?Record<string, EventTrigger>
workflowsRecord<string, AnyWorkflowDefinition>

LinearDelegationInputs ​

The inputs a linear.delegations source hands each run it starts.

Extended by ​

Properties ​

PropertyTypeDescription
creatorobjectThe person who delegated the issue, or mentioned the app.
creator.emailstring-
creator.idstring-
creator.namestring-
installationNamestringThe Linear installation, as named on the hub, the session is in.
issueobject-
issue.idstring-
issue.identifierstring-
issue.titlestring-
issue.urlstring-
promptContextstring | nullLinear's formatted context for the session: the issue, its description and the comments around it, or null if Linear sent none.
sessionstringThe Linear agent session's id.

LinearMentionInputs ​

The inputs a linear.mentions source hands each run it starts.

Extends ​

Properties ​

PropertyTypeDescription
commentstringThe body of the comment that mentioned the app.
creatorobjectThe person who delegated the issue, or mentioned the app.
creator.emailstring-
creator.idstring-
creator.namestring-
installationNamestringThe Linear installation, as named on the hub, the session is in.
issueobject-
issue.idstring-
issue.identifierstring-
issue.titlestring-
issue.urlstring-
promptContextstring | nullLinear's formatted context for the session: the issue, its description and the comments around it, or null if Linear sent none.
sessionstringThe Linear agent session's id.

Schedule ​

One recurring trigger: a workflow, when to fire it, and the inputs to fire it with. *

Properties ​

PropertyTypeDescription
activebooleanAn inactive schedule never fires.
cronstringFive fields, evaluated in the service host's local time zone.
inputsRecord<string, unknown>-
workflowstring-

SourceDescriptor ​

What an event trigger watches: a source kind and the provider's own query parameters for it. Plain data, so it can sit in jigs.config.ts; a source's constructor builds it.

Properties ​

PropertyType
kindstring
paramsRecord<string, unknown>

WorkflowDefinition ​

A workflow: its function, its input schema, and what a run needs before it may start.

Type Parameters ​

Type ParameterDefault type
S extends z.ZodTypez.ZodType

Properties ​

PropertyTypeDescription
inputsS-
release?object-
release.onFailure"release" | "keep"What to do with eligible resources after a failed or cancelled run.
release.onSuccess"release" | "keep"What to do with eligible resources after a completed run.
requires?WorkflowRequiresWhat the workflow needs before a run can start: the agents it runs, the integrations, bindings and API model sources it uses, and the names of the environment variables its steps read as secrets. The service checks the CLI of every agent's harness when it starts, and preflight checks everything listed before every run. List only what the workflow uses. Remarks A secret is set in the factory's environment and read in a step from the process environment. The variables an agent's MCP servers name count as secrets without being listed. Listing a secret does not pass it to agents. Example Pass this value as requires when calling defineWorkflow. import { harnesses, type WorkflowDefinition } from "@jigs-ai/jigs"; const agents = { builder: harnesses.claude({ model: "opus" }), reviewer: harnesses.codex({ model: "gpt-5.6-sol" }), }; const requires = { agents, integrations: ["linear", "github"], bindings: ["app"], secrets: ["SNOWFLAKE_TOKEN"], } satisfies WorkflowDefinition["requires"];
workflow(inputs) => Promise<unknown>-

AgentsDefinition ​

ts
type AgentsDefinition = z.input<typeof agentsSchema>;

Settings for the agent harnesses this factory runs.


BindingDefinition ​

ts
type BindingDefinition = z.input<typeof bindingSchema>;

A repository this factory works in: its remote, the GitHub installation that reaches it, and how a worktree cut from it is provisioned.

Remarks ​

installationName is the name an admin gave the GitHub App installation on the hub. Pushes, pull requests and their events go through it.

Example ​

Use this value for bindings.api in jigs.config.ts.

ts
import type { BindingDefinition } from "@jigs-ai/jigs";

const api = {
  remote: "git@github.com:acme/api.git",
  installationName: "github-acme",
  postCreate: ["pnpm install"],
} satisfies BindingDefinition;

FactoryDefinition ​

ts
type FactoryDefinition = z.input<typeof factoryConfigSchema> & object;

Operating settings and deferred workflow modules declared by a factory.

Type Declaration ​

NameType
workflowsRecord<string, WorkflowImport>

GitHubDefinition ​

ts
type GitHubDefinition = z.input<typeof githubSchema>;

Who the operator is on GitHub.

Remarks ​

jigs acts on GitHub as the GitHub App the hub assigns this factory, so its pull requests come from <app-slug>[bot] and the operator approves them with a review.

Example ​

Use this value for github in jigs.config.ts.

ts
import type { GitHubDefinition } from "@jigs-ai/jigs";

const github = {
  operator: "octocat",
  coAuthor: "Octo Cat <octocat@example.com>",
} satisfies GitHubDefinition;

GitHubIssueInputs ​

ts
type GitHubIssueInputs = RepositoryRef & object;

The inputs a github.issues source hands each run it starts.

Type Declaration ​

NameTypeDescription
numbernumberThe repository-local issue number.

GitHubIssuesParams ​

ts
type GitHubIssuesParams = z.input<typeof gitHubIssuesParamsSchema>;

Which issues a github.issues source starts runs for. Each list matches any of its values; leaving one out does not filter on it.

  • installationName: the GitHub App installation, as named on the hub, whose repositories it watches.
  • repositories: owner/repo names, such as acme/api, in any case.
  • authors: GitHub logins of who opened the issue.
  • labels: label names; an issue with any of them matches.

GitHubPullRequestsParams ​

ts
type GitHubPullRequestsParams = z.input<typeof gitHubPullRequestsParamsSchema>;

Which pull requests a github.pullRequests source starts runs for. Each list matches any of its values; leaving one out does not filter on it.

  • installationName: the GitHub App installation, as named on the hub, whose repositories it watches.
  • repositories: owner/repo names, such as acme/api, in any case.
  • authors: GitHub logins of who opened the pull request, such as dependabot[bot].
  • labels: label names; a pull request with any of them matches.
  • baseBranches: the branches the pull request merges into, such as main.

GitHubPushesParams ​

ts
type GitHubPushesParams = z.input<typeof gitHubPushesParamsSchema>;

Which pushes a github.pushes source starts runs for. Each list matches any of its values; leaving one out does not filter on it.

  • installationName: the GitHub App installation, as named on the hub, whose repositories it watches.
  • repositories: owner/repo names, such as acme/api, in any case.
  • branches: branch names, such as main.

GitHubPushInputs ​

ts
type GitHubPushInputs = RepositoryRef & object;

The inputs a github.pushes source hands each run it starts.

Type Declaration ​

NameTypeDescription
afterstringThe commit the branch points at after the push.
beforestringThe commit the branch pointed at before the push, all zeros for a new branch.
branchstringThe branch pushed to, such as main.

GitHubReleaseInputs ​

ts
type GitHubReleaseInputs = RepositoryRef & object;

The inputs a github.releases source hands each run it starts.

Type Declaration ​

NameTypeDescription
tagstringThe release's tag, such as v1.2.0.

GitHubReleasesParams ​

ts
type GitHubReleasesParams = z.input<typeof gitHubReleasesParamsSchema>;

Which releases a github.releases source starts runs for.

  • installationName: the GitHub App installation, as named on the hub, whose repositories it watches.
  • repositories: owner/repo names, such as acme/api, in any case; leaving it out watches them all.

LinearAgentSessionsParams ​

ts
type LinearAgentSessionsParams = z.input<typeof linearAgentSessionsParamsSchema>;

Which Linear agent sessions a linear.delegations or linear.mentions source starts runs for. Each list matches any of its values; leaving one out does not filter on it.

  • installationName: the Linear installation, as named on the hub, whose sessions it watches.
  • teams: team keys, such as ENG, or team ids.
  • projects: project ids, or the id at the end of a project's URL.
  • labels: label names, as Linear shows them.
  • creators: emails of the people who delegated the issue or mentioned the app, in any case.

LinearDefinition ​

ts
type LinearDefinition = z.input<typeof linearSchema>;

Who a ticket run's Linear questions and notes mention.

Remarks ​

operator is the email of the Linear user who runs the factory. With it, every question and note a ticket run posts mentions the operator and the ticket's assignee; without it, the ticket's creator and assignee. jigs doctor fails when no Linear user has the email. Steps read it from the built factory, so a change takes effect after a rebuild, which jigs up does.

Example ​

Use this value for linear in jigs.config.ts.

ts
import type { LinearDefinition } from "@jigs-ai/jigs";

const linear = {
  operator: "salim@example.com",
} satisfies LinearDefinition;

PagerDutyIncidentsParams ​

ts
type PagerDutyIncidentsParams = z.input<typeof pagerDutyIncidentsParamsSchema>;

Which incidents a pagerduty.incidents source starts runs for. Each list matches any of its values; leaving one out does not filter on it.

  • installationName: the PagerDuty installation, as named on the hub, whose incidents it watches.
  • services: PagerDuty service IDs, such as P48FPG2.
  • teams: PagerDuty team IDs.
  • urgencies: high, low or both.

TicketWorkflowInputs ​

ts
type TicketWorkflowInputs<S> = WorkflowInputs<S>;

Ticket references are ordinary inputs; resolve them explicitly in a step.

Type Parameters ​

Type Parameter
S extends z.ZodType<{ ticket: string; }>

WorkflowInputs ​

ts
type WorkflowInputs<S> = z.output<S> & Injected;

Parsed workflow inputs with the trigger that started the run.

Type Parameters ​

Type Parameter
S extends z.ZodType

github ​

ts
const github: object;

Event-trigger sources on GitHub.

Type Declaration ​

NameTypeDescription
issues()(params) => SourceDescriptorStart a run for each issue, with GitHubIssueInputs as its inputs. An issue starts at most one run, ever: the first time any of its events shows it open and matching the filters, such as when it is opened or labeled. An issue reopened after its run ended starts no new one; rerun it with jigs run. Remarks The GitHub App must subscribe to the Issues event. Events the factory's own GitHub App caused start no run, so an issue the App opens starts one only once a person acts on it, such as by adding a label the trigger filters on. Example import { github } from "@jigs-ai/jigs"; const source = github.issues({ installationName: "github-acme", repositories: ["acme/api"], labels: ["agent"], });
pullRequests()(params) => SourceDescriptorStart a run for each pull request, with its PullRequestRef as the inputs. A pull request starts at most one run, ever: the first time any of its events shows it open, not a draft and matching the filters, such as when it is opened, labeled or marked ready for review. A pull request reopened after its run ended starts no new one; rerun it with jigs run. Remarks Events the factory's own GitHub App caused start no run, so a pull request the App opens starts one only once a person acts on it, such as by adding a label the trigger filters on. Example import { github } from "@jigs-ai/jigs"; const source = github.pullRequests({ installationName: "github-acme", repositories: ["acme/api"], authors: ["dependabot[bot]"], });
pushes()(params) => SourceDescriptorStart a run for each push to a branch, with GitHubPushInputs as its inputs. Each push starts at most one run, ever. Tag pushes and branch deletions start none. A push the factory's own GitHub App made, such as merging a person's pull request, starts runs like any other. Remarks The GitHub App must subscribe to the Push event. Example import { github } from "@jigs-ai/jigs"; const source = github.pushes({ installationName: "github-acme", repositories: ["acme/api"], branches: ["main"], });
releases()(params) => SourceDescriptorStart a run for each published release, with GitHubReleaseInputs as its inputs. A release starts at most one run, ever, once it is published and not a prerelease: a prerelease starts its run when it becomes a release. Drafts start none. Remarks The GitHub App must subscribe to the Release event and needs Contents: read. Example import { github } from "@jigs-ai/jigs"; const source = github.releases({ installationName: "github-acme", repositories: ["acme/api"], });

installationNameSchema ​

ts
const installationNameSchema: ZodString;

An installation's name, as an admin set it on the hub: lowercase letters, digits and hyphens, starting with a letter. Use it for a workflow input that names an installation.


linear ​

ts
const linear: object;

Event-trigger sources on Linear.

Type Declaration ​

NameTypeDescription
delegations()(params) => SourceDescriptorStart a run whenever someone delegates an issue to the factory's Linear app, with LinearDelegationInputs as its inputs. Example import { linear } from "@jigs-ai/jigs"; const source = linear.delegations({ installationName: "acme", teams: ["ENG"] });
mentions()(params) => SourceDescriptorStart a run whenever someone mentions the factory's Linear app in a comment on an issue, with LinearMentionInputs as its inputs. Example import { linear } from "@jigs-ai/jigs"; const source = linear.mentions({ installationName: "acme", labels: ["agent"] });

Remarks ​

Delegating an issue to the factory's Linear app, or mentioning the app in a comment, opens a Linear agent session. Each session starts at most one run per trigger, ever. The hub posts the session's first reply, so Linear shows the app at work while the run starts. That reply appears even when no trigger matches, so make the filters match what the app is for. Every factory assigned the app hears every session, and each matching trigger starts its own run. Sessions not on an issue, and sessions the app opened itself, start no run.


pagerduty ​

ts
const pagerduty: object;

Event-trigger sources on PagerDuty.

Type Declaration ​

NameTypeDescription
incidents()(params) => SourceDescriptorWatch for new incidents. Every new incident starts at most one run, ever, with { installationName, incident: "<id>" } as its inputs, even one acknowledged or resolved before the service saw it; the workflow can check the status and skip one that is already handled. The run starts as soon as the hub passes on PagerDuty's incident.triggered event. Example import { pagerduty } from "@jigs-ai/jigs"; const source = pagerduty.incidents({ installationName: "acme", services: ["P48FPG2"], urgencies: ["high"], });

slack ​

ts
const slack: object;

Event-trigger sources for Slack, one per trigger in jigs.config.ts.

Type Declaration ​

NameTypeDescription
mentions()(__namedParameters) => SourceDescriptorOnly the top-level messages that mention the factory's bot.
messages()(__namedParameters) => SourceDescriptorEvery top-level message in the channels.

Remarks ​

Both read top-level messages in the listed channels of one Slack installation, named as on the hub, whose bot must be a member of them, and start one run per message with the inputs { installationName, channel, ts }. Posts from people, other bots and apps count, including posts with files. The factory's own posts never count, and neither do thread replies, edits, deletes, joins or other channel events. Direct messages are never read. Channels are listed by ID, such as C0123ABCD, not by name.

Example ​

Start a run for every message that mentions the bot in one channel.

ts
import { slack } from "@jigs-ai/jigs";

const triggers = {
  "answer-questions": {
    active: process.env.ANSWER_QUESTIONS_ACTIVE === "true",
    workflow: "answer",
    source: slack.mentions({ installationName: "acme", channels: ["C0123ABCD"] }),
  },
};

ticketInputSchema ​

ts
const ticketInputSchema: ZodUnion<readonly [ZodUUID, ZodString]>;

Accept a Linear issue UUID or an uppercase team-and-number ticket identifier.


defineFactory() ​

ts
function defineFactory<T>(factory): T;

Check the declaration against what jigs accepts and preserve its inferred keys, without loading its workflows.

Type Parameters ​

Type Parameter
T extends FactoryDefinition

Parameters ​

ParameterType
factoryT & Record<Exclude<keyof T, | "github" | "linear" | "hub" | "release" | "bindings" | "agents" | "workflows" | "schedules" | "triggers">, never>

Returns ​

T


defineWorkflow() ​

ts
function defineWorkflow<S>(definition): WorkflowDefinition<S>;

Declare a workflow as the default export of its file. It returns the definition unchanged; it exists so TypeScript checks the workflow's parameter against the input schema.

Type Parameters ​

Type Parameter
S extends ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>

Parameters ​

ParameterType
definitionWorkflowDefinition<S>

Returns ​

WorkflowDefinition<S>

Example ​

ts
import { defineWorkflow, type WorkflowInputs } from "@jigs-ai/jigs";
import { z } from "zod";

const inputs = z.object({ name: z.string() });

export async function hello(input: WorkflowInputs<typeof inputs>) {
  "use workflow";
  return `Hello, ${input.name}!`;
}

export default defineWorkflow({ inputs, workflow: hello });

Harnesses and models ​

AgentInstallation ​

ts
type AgentInstallation = object;

Names the installation, as an admin named it on the hub, an agent acts through.

Remarks ​

On github, the agent gets a fresh token of that GitHub App installation in GH_TOKEN, so gh works as the App's bot, and git reaches the installation account's repositories over HTTPS with that token. Its commits are authored by the bot, while your own git configuration stays the committer and signer. On linear, the workspace's token goes in JIGS_LINEAR_TOKEN; on pagerduty, the account's token goes in JIGS_PAGERDUTY_TOKEN.

Example ​

ts
import { harnesses } from "@jigs-ai/jigs";

const builder = harnesses.codex({
  model: "gpt-5.6-sol",
  github: { installationName: "github-acme" },
});

Properties ​

PropertyType
installationNamestring

AskableHarness ​

ts
type AskableHarness = 
  | ClaudeHarness & ToolFree
  | PiHarness & ToolFree;

A harness askAgent can run with no tools: Claude Code or Pi, without MCP servers, provider access or a Pi tool allowlist. Codex has no mode without tools.


AskableModelSource ​

ts
type AskableModelSource = Exclude<ModelSource, OpenaiCodexSource>;

A model source accepted by a direct model call.


ClaudeHarness ​

ts
type ClaudeHarness = JsonOnly<Omit<ClaudeAgentOptions, ClaudePolicyKey>> & HarnessSkills & object;

A Claude Code harness descriptor: the Claude Agent SDK's own options that are data, minus each ClaudePolicyKey, plus the model, jigs' MCP server shape and HarnessSkills.

Type Declaration ​

NameTypeDescription
github?AgentInstallationActs on GitHub as the factory's App, through this installation.
kind"claude"-
linear?AgentInstallationActs on Linear as the factory's app, through this installation.
mcpServers?Record<string, McpServerConfig>-
modelstring-
pagerduty?AgentInstallationActs on PagerDuty as the factory's app, through this installation.

ClaudeHarnessSettings ​

ts
type ClaudeHarnessSettings = Omit<ClaudeHarness, "kind">;

The one argument harnesses.claude takes: the model and any Claude Code settings.


ClaudePolicyKey ​

ts
type ClaudePolicyKey = typeof claudePolicyKeys[number];

A Claude Code option a descriptor cannot name, because jigs sets it itself or holds it as policy.

Remarks ​

jigs sets the working directory, environment, executable, session and output format for every step, and holds permissions, setting sources and MCP servers as policy. extraArgs would rewrite any of those. agents, settings, plugins and projectConfigRoot would bring in unprobed MCP servers, environment, permissions and hooks from outside the worktree; they come from the repository's project settings instead. jigs fills plugins itself to load the descriptor's skills, which replace Claude Code's own skills option.


CodexHarness ​

ts
type CodexHarness = JsonOnly<Omit<CodexAppServerSettings, CodexPolicyKey>> & HarnessSkills & object;

A Codex harness descriptor: the provider's own settings that are data, minus each CodexPolicyKey, plus the model, jigs' MCP server shape and HarnessSkills.

Type Declaration ​

NameTypeDescription
github?AgentInstallationActs on GitHub as the factory's App, through this installation.
kind"codex"-
linear?AgentInstallationActs on Linear as the factory's app, through this installation.
mcpServers?Record<string, McpServerConfig>-
modelstring-
pagerduty?AgentInstallationActs on PagerDuty as the factory's app, through this installation.

CodexHarnessSettings ​

ts
type CodexHarnessSettings = Omit<CodexHarness, "kind">;

The one argument harnesses.codex takes: the model and any Codex settings.


CodexPolicyKey ​

ts
type CodexPolicyKey = typeof codexPolicyKeys[number];

A Codex setting a descriptor cannot name, because jigs sets it itself or holds it as policy.

Remarks ​

jigs sets the working directory, environment, executable, thread and session for every step, and holds the approval and sandbox policies and MCP servers. configOverrides would rewrite the sandbox and MCP tables.


GithubMcpOptions ​

ts
type GithubMcpOptions = object;

Options for githubMcp on a Pi harness.

Properties ​

PropertyTypeDescription
toolsstring[]Raw MCP tool names the model may call. jigs adds the probe tool, search_repositories.

Harness ​

ts
type Harness = 
  | ClaudeHarness
  | CodexHarness
  | PiHarness;

A serializable agent-program descriptor.


HarnessForOptions ​

ts
type HarnessForOptions<H, O> = [Extract<keyof O, keyof ToolFree>] extends [never] ? H & ToolFree : H;

The descriptor a harness constructor returns for its options. It is also ToolFree, so askAgent accepts it, when the options name no tools, MCP servers or provider access.

Type Parameters ​

Type Parameter
H
O

HarnessKind ​

ts
type HarnessKind = Harness["kind"];

The stable name of an agent harness.


HarnessSkills ​

ts
type HarnessSkills = object;

Skill folders an agent loads, each holding a SKILL.md and any files it refers to.

Remarks ​

Each path is relative to the factory root, or absolute. jigs copies every folder into a private place for each agent call, so the skills reach the agent whatever its working directory and nothing the agent changes there reaches the factory. Each folder is copied under its own name, so two folders cannot share one; keep it the same as the name in its SKILL.md. A run whose folder is missing or has no SKILL.md fails its checks before the agent starts. Skills apply when an agent runs in a directory, not to askAgent.

Properties ​

PropertyType
skills?string[]

JsonOnly ​

ts
type JsonOnly<T> = { [K in keyof T as false extends IsData<Exclude<T[K], undefined>> ? never : K]: T[K] };

The keys of a settings type whose values are data, so they can cross into a step.

Type Parameters ​

Type Parameter
T

LinearMcpOptions ​

ts
type LinearMcpOptions = object;

Options for linearMcp on a Pi harness.

Properties ​

PropertyTypeDescription
toolsstring[]Raw MCP tool names the model may call. jigs adds the probe tool, list_teams.

McpHttpServerConfig ​

ts
type McpHttpServerConfig = object;

Configuration for an MCP server reached over HTTP.

Remarks ​

Credentials never appear in workflow code: each headers value and bearerTokenEnv name an environment variable of the service, read when the step starts the agent. A step whose named variable is not set fails before the agent starts.

Properties ​

PropertyTypeDescription
bearerTokenEnv?stringNames the service variable holding a token sent as Authorization: Bearer <token>.
disabledTools?string[]Raw MCP tool names the model may not call. Pi takes its tools allowlist instead.
headers?Record<string, string>Maps HTTP header names to the names of the service variables holding their values.
probeMcpToolProbe-
urlstring-

McpServerConfig ​

ts
type McpServerConfig = 
  | McpStdioServerConfig
  | McpHttpServerConfig;

An MCP server an agent harness can expose to the model.


McpStdioServerConfig ​

ts
type McpStdioServerConfig = object;

Configuration for an MCP server launched as a child process.

Remarks ​

Credentials never appear in workflow code: each env value names an environment variable of the service, read when the step starts the agent. A step whose named variable is not set fails before the agent starts.

Example ​

ts
import { harnesses } from "@jigs-ai/jigs";

// The server reads BRAVE_API_KEY; its value comes from the service's SEARCH_API_KEY.
const researcher = harnesses.claude({
  model: "opus",
  mcpServers: {
    search: {
      command: "npx",
      args: ["-y", "@brave/brave-search-mcp-server"],
      env: { BRAVE_API_KEY: "SEARCH_API_KEY" },
      probe: { tool: "brave_web_search", arguments: { query: "jigs", count: 1 } },
    },
  },
});

Properties ​

PropertyTypeDescription
args?string[]-
commandstring-
disabledTools?string[]Raw MCP tool names the model may not call. Pi takes its tools allowlist instead.
env?Record<string, string>Maps the server's variable names to the names of the service variables holding their values.
probeMcpToolProbe-

McpToolProbe ​

ts
type McpToolProbe = object;

A harmless MCP tool call used to prove that a configured server is available.

Properties ​

PropertyType
arguments?Record<string, unknown>
toolstring

ModelKind ​

ts
type ModelKind = ModelSource["kind"];

The stable name of a model source.


ModelSource ​

ts
type ModelSource = 
  | OpenrouterSource
  | OpenaiCompatibleSource
  | OpenaiCodexSource;

Any configured source from which a model can answer.


OpenaiCodexSource ​

ts
type OpenaiCodexSource = object;

The Codex subscription model source used only by the Pi harness.

Properties ​

PropertyType
kind"openai-codex"
modelstring

OpenaiCompatibleSource ​

ts
type OpenaiCompatibleSource = object;

An OpenAI-compatible API model source.

Properties ​

PropertyType
apiKeyEnv?string
baseUrlstring
kind"openai-compatible"
modelstring
namestring

OpenrouterSource ​

ts
type OpenrouterSource = object;

An OpenRouter API model source.

Properties ​

PropertyType
apiKeyEnvstring
kind"openrouter"
modelstring

PagerdutyMcpOptions ​

ts
type PagerdutyMcpOptions = object;

Options for pagerdutyMcp on a Pi harness.

Properties ​

PropertyTypeDescription
toolsstring[]Raw MCP tool names the model may call. jigs adds the probe tool, list_incidents.

PiHarness ​

ts
type PiHarness = 
  | PiOpenaiCompatibleHarness
  | PiOtherHarness;

A Pi harness descriptor backed by a nested model source.


PiHarnessOptions ​

ts
type PiHarnessOptions = Pick<PiHarness, 
  | "thinking"
  | "tools"
  | "mcpServers"
  | "github"
  | "linear"
  | "pagerduty"
  | "skills"> & object;

Options for harnesses.pi. compat applies only to an OpenAI-compatible model source.

Type Declaration ​

NameType
compat?Partial<PiOpenaiCompatibleOptions>

PiMcpHttpServerConfig ​

ts
type PiMcpHttpServerConfig = Omit<McpHttpServerConfig, "bearerTokenEnv" | "disabledTools"> & object & 
  | {
  auth: "oauth";
  bearerTokenEnv?: never;
}
  | {
  auth?: false;
  bearerTokenEnv?: never;
}
  | {
  auth?: never;
  bearerTokenEnv: string;
};

An HTTP MCP server Pi exposes through an explicit direct-tool allowlist.

Type Declaration ​

NameTypeDescription
toolsstring[]Raw MCP tool names the model may call. This must include the probe tool.

PiMcpServerConfig ​

ts
type PiMcpServerConfig = 
  | PiMcpStdioServerConfig
  | PiMcpHttpServerConfig;

An explicitly configured MCP server accepted by the Pi harness.


PiMcpStdioServerConfig ​

ts
type PiMcpStdioServerConfig = Omit<McpStdioServerConfig, "disabledTools"> & object;

A stdio MCP server Pi exposes through an explicit direct-tool allowlist.

Type Declaration ​

NameTypeDescription
toolsstring[]Raw MCP tool names the model may call. This must include the probe tool.

PiOpenaiCompatibleHarness ​

ts
type PiOpenaiCompatibleHarness = SharedPiHarness & object;

A Pi harness descriptor backed by an OpenAI-compatible source, with its compatibility hints.

Type Declaration ​

NameType
compatPiOpenaiCompatibleOptions
modelOpenaiCompatibleSource

PiOpenaiCompatibleOptions ​

ts
type PiOpenaiCompatibleOptions = object;

Pi-specific compatibility hints for an OpenAI-compatible model.

Properties ​

PropertyType
supportsDeveloperRoleboolean
supportsReasoningEffortboolean

PiOtherHarness ​

ts
type PiOtherHarness = SharedPiHarness & object;

A Pi harness descriptor backed by any source other than an OpenAI-compatible one.

Type Declaration ​

NameType
compat?never
modelExclude<ModelSource, OpenaiCompatibleSource>

ToolFree ​

ts
type ToolFree = object;

Marks a descriptor that names no tools, MCP servers or provider access.

Properties ​

PropertyType
github?never
linear?never
mcpServers?never
pagerduty?never
tools?never

harnesses ​

ts
const harnesses: object;

Constructors for agent-harness descriptors.

Type Declaration ​

NameTypeDefault value
claude()<O>(settings) => HarnessForOptions<ClaudeHarness, O>claudeHarness
codex()<O>(settings) => CodexHarnesscodexHarness
pi(){ <O> (model, options?): HarnessForOptions<PiOpenaiCompatibleHarness, O>; <O> (model, options?): HarnessForOptions<PiOtherHarness, O>; <M, O> (model, options?): HarnessForOptions<PiHarness, O>; }piHarness

harnessKinds ​

ts
const harnessKinds: ["claude" | "codex" | "pi", ...("claude" | "codex" | "pi")[]];

Every harness kind this release of jigs can build, taken from the keys of harnesses. Use it for a workflow input that names a harness, so a new kind appears without editing the input.

Example ​

ts
import { harnessKinds } from "@jigs-ai/jigs";
import { z } from "zod";

const inputs = z.object({ harness: z.enum(harnessKinds) });

models ​

ts
const models: object;

Constructors for model-source descriptors.

Type Declaration ​

NameTypeDescription
openaiCodex()(model) => OpenaiCodexSourceBuild a source that runs through the Codex subscription Pi is logged in to. Only harnesses.pi accepts it.
openaiCompatible()(options) => OpenaiCompatibleSourceBuild a source for an OpenAI-compatible server.
openrouter()(model, options) => OpenrouterSourceBuild an OpenRouter source. Its key is read from OPENROUTER_API_KEY unless apiKeyEnv names another variable.

githubMcp() ​

Call Signature ​

ts
function githubMcp(): McpStdioServerConfig;

An MCP server that gives an agent GitHub's own tools, acting as the factory's GitHub App.

Returns ​

McpStdioServerConfig

Remarks ​

It runs github-mcp-server, which must be installed on the machine, with the token of an agent whose harness sets github; a harness without github cannot use it. Tools that need a user, such as get_me, are left out, since an App's token cannot answer them. Pi needs the list of tools the model may call.

Example ​
ts
import { githubMcp, harnesses } from "@jigs-ai/jigs";

const builder = harnesses.claude({
  model: "opus",
  github: { installationName: "github-acme" },
  mcpServers: { github: githubMcp() },
});

Call Signature ​

ts
function githubMcp(options): PiMcpStdioServerConfig;

An MCP server that gives an agent GitHub's own tools, acting as the factory's GitHub App.

Parameters ​
ParameterType
optionsGithubMcpOptions
Returns ​

PiMcpStdioServerConfig

Remarks ​

It runs github-mcp-server, which must be installed on the machine, with the token of an agent whose harness sets github; a harness without github cannot use it. Tools that need a user, such as get_me, are left out, since an App's token cannot answer them. Pi needs the list of tools the model may call.

Example ​
ts
import { githubMcp, harnesses } from "@jigs-ai/jigs";

const builder = harnesses.claude({
  model: "opus",
  github: { installationName: "github-acme" },
  mcpServers: { github: githubMcp() },
});

linearMcp() ​

Call Signature ​

ts
function linearMcp(): McpHttpServerConfig;

An MCP server that gives an agent Linear's own tools, acting as the factory on Linear.

Returns ​

McpHttpServerConfig

Remarks ​

It reaches Linear's hosted server at https://mcp.linear.app/mcp with the token of an agent whose harness sets linear; a harness without linear cannot use it. In app mode the agent acts as the factory's Linear app, in key mode as the API key's user. Pi needs the list of tools the model may call. The result is plain data, so spread it to change a field, such as url to https://mcp.linear.app/mcp/readonly for read tools only.

Example ​
ts
import { harnesses, linearMcp } from "@jigs-ai/jigs";

const triager = harnesses.claude({
  model: "opus",
  linear: { installationName: "linear-acme" },
  mcpServers: { linear: linearMcp() },
});

Call Signature ​

ts
function linearMcp(options): PiMcpHttpServerConfig;

An MCP server that gives an agent Linear's own tools, acting as the factory on Linear.

Parameters ​
ParameterType
optionsLinearMcpOptions
Returns ​

PiMcpHttpServerConfig

Remarks ​

It reaches Linear's hosted server at https://mcp.linear.app/mcp with the token of an agent whose harness sets linear; a harness without linear cannot use it. In app mode the agent acts as the factory's Linear app, in key mode as the API key's user. Pi needs the list of tools the model may call. The result is plain data, so spread it to change a field, such as url to https://mcp.linear.app/mcp/readonly for read tools only.

Example ​
ts
import { harnesses, linearMcp } from "@jigs-ai/jigs";

const triager = harnesses.claude({
  model: "opus",
  linear: { installationName: "linear-acme" },
  mcpServers: { linear: linearMcp() },
});

pagerdutyMcp() ​

Call Signature ​

ts
function pagerdutyMcp(): McpHttpServerConfig;

An MCP server that gives an agent PagerDuty's own tools, acting as the factory's PagerDuty app.

Returns ​

McpHttpServerConfig

Remarks ​

It reaches PagerDuty's hosted server with the token of an agent whose harness sets pagerduty; a harness without pagerduty cannot use it. The token carries the scopes jigs itself uses, so the agent can read and update incidents and read users; other tools fail for lack of a scope. The token belongs to an app, not a user, so get_user_data is disabled and list_incidents cannot filter by the assigned or teams request scope. Pi needs the list of tools the model may call; leave get_user_data out of it. The result is plain data: for an account in the EU service region, spread it with url: "https://mcp.eu.pagerduty.com/mcp".

Example ​
ts
import { harnesses, pagerdutyMcp } from "@jigs-ai/jigs";

const triager = harnesses.claude({
  model: "opus",
  pagerduty: { installationName: "pagerduty-acme" },
  mcpServers: { pagerduty: pagerdutyMcp() },
});

Call Signature ​

ts
function pagerdutyMcp(options): PiMcpHttpServerConfig;

An MCP server that gives an agent PagerDuty's own tools, acting as the factory's PagerDuty app.

Parameters ​
ParameterType
optionsPagerdutyMcpOptions
Returns ​

PiMcpHttpServerConfig

Remarks ​

It reaches PagerDuty's hosted server with the token of an agent whose harness sets pagerduty; a harness without pagerduty cannot use it. The token carries the scopes jigs itself uses, so the agent can read and update incidents and read users; other tools fail for lack of a scope. The token belongs to an app, not a user, so get_user_data is disabled and list_incidents cannot filter by the assigned or teams request scope. Pi needs the list of tools the model may call; leave get_user_data out of it. The result is plain data: for an account in the EU service region, spread it with url: "https://mcp.eu.pagerduty.com/mcp".

Example ​
ts
import { harnesses, pagerdutyMcp } from "@jigs-ai/jigs";

const triager = harnesses.claude({
  model: "opus",
  pagerduty: { installationName: "pagerduty-acme" },
  mcpServers: { pagerduty: pagerdutyMcp() },
});

Agent and model requests/results ​

AgentResult ​

ts
type AgentResult<T> = ModelResult<T> & object;

A model result with the session reference an agent harness returned, when it returned one.

Type Declaration ​

NameType
session?AgentSessionRef

Type Parameters ​

Type ParameterDefault type
Tunknown

AgentSessionRef ​

ts
type AgentSessionRef = object;

A session reference: the small piece of data that lets a later runAgent call resume the same harness session. Pass it back as resume.

Properties ​

PropertyTypeDescription
descriptorstringThe harness descriptor the session was recorded on, as describeHarness renders it.
harnessHarness["kind"]-
idstring-

AskAgentOptions ​

ts
type AskAgentOptions<T> = object;

Options for one harness turn without tools or a worktree.

Type Parameters ​

Type ParameterDefault type
Tundefined

Properties ​

PropertyType
harnessAskableHarness
output?z.ZodType<T>
promptstring
system?string

AskModelOptions ​

ts
type AskModelOptions<T> = object;

Options for one API model call.

Type Parameters ​

Type ParameterDefault type
Tundefined

Properties ​

PropertyType
modelAskableModelSource
output?z.ZodType<T>
promptstring
system?string

ModelResult ​

ts
type ModelResult<T> = object;

Text and structured output returned by a model call.

Type Parameters ​

Type ParameterDefault type
Tunknown

Properties ​

PropertyType
outputT
textstring

OutputJsonSchema ​

ts
type OutputJsonSchema = Record<string, unknown>;

The serializable JSON Schema sent across the workflow-step boundary.


RunAgentOptions ​

ts
type RunAgentOptions<T> = object;

Options for an agent that works inside a directory.

Type Parameters ​

Type ParameterDefault type
Tundefined

Properties ​

PropertyTypeDescription
cwdstring-
harnessHarness-
output?z.ZodType<T>-
promptstring-
resume?AgentSessionRefThe session reference of an earlier run to continue.

describeHarness() ​

ts
function describeHarness(harness): string;

A harness descriptor as a string that ignores field order: two descriptors that list the same settings in another order render the same.

Parameters ​

ParameterType
harnessHarness

Returns ​

string


unwrapAgentStep() ​

ts
function unwrapAgentStep(result): AgentResult;

Convert returned execution failure markers into errors the workflow throws.

Parameters ​

ParameterType
result| AgentResult | { jitFailure: object & object[]; } | { resumeFailed: string; }

Returns ​

AgentResult

Decision models ​

AskJevOptions ​

ts
type AskJevOptions<QUESTIONS> = object;

A decision request in workflow and durable wire form.

Type Parameters ​

Type Parameter
QUESTIONS extends JevQuestions

Properties ​

PropertyType
modelOpenrouterSource
questionsQUESTIONS
stateJevState

ChoiceQuestion ​

ts
type ChoiceQuestion<OPTIONS> = object;

A question answered with one named option.

Type Parameters ​

Type ParameterDefault type
OPTIONS extends Record<string, string>Record<string, string>

Properties ​

PropertyType
instructionsstring
optionsOPTIONS
type"choice"

JevAnswer ​

ts
type JevAnswer<QUESTION> = QUESTION extends ChoiceQuestion<infer OPTIONS> ? object : QUESTION extends ScoreQuestion ? object : object;

The calibrated answer shape selected by one question descriptor.

Type Parameters ​

Type Parameter
QUESTION extends JevQuestion

JevAnswers ​

ts
type JevAnswers<QUESTIONS> = { [KEY in keyof QUESTIONS]: JevAnswer<QUESTIONS[KEY]> };

Answers narrowed independently for every named question.

Type Parameters ​

Type Parameter
QUESTIONS extends JevQuestions

JevQuestion ​

ts
type JevQuestion = 
  | YesNoQuestion
  | ChoiceQuestion
  | ScoreQuestion;

Any question accepted by askJev.


JevQuestions ​

ts
type JevQuestions = Record<string, JevQuestion>;

Named decision questions evaluated against one shared state.


JevResult ​

ts
type JevResult<QUESTIONS> = object;

A typed decision result.

Type Parameters ​

Type Parameter
QUESTIONS extends JevQuestions

Properties ​

PropertyType
answersJevAnswers<QUESTIONS>

JevState ​

ts
type JevState = string | JevJsonObject | JevJsonValue[];

JSON-compatible evidence evaluated by a decision model.


ScoreQuestion ​

ts
type ScoreQuestion = object;

A question scored over ordered levels, from lowest to highest.

Properties ​

PropertyType
instructionsstring
levelsstring[]
type"score"

YesNoQuestion ​

ts
type YesNoQuestion = object;

A calibrated yes-or-no question.

Properties ​

PropertyType
instructionsstring
type"yes-no"

choice() ​

ts
function choice<OPTIONS>(instructions, options): ChoiceQuestion<OPTIONS>;

Build a question answered with one named option. It throws unless every option has a description.

Type Parameters ​

Type Parameter
OPTIONS extends Record<string, string>

Parameters ​

ParameterType
instructionsstring
optionsOPTIONS

Returns ​

ChoiceQuestion<OPTIONS>


score() ​

ts
function score(instructions, levels): ScoreQuestion;

Build a question scored over ordered levels, from lowest to highest. It throws unless there are at least two levels, each described.

Parameters ​

ParameterType
instructionsstring
levelsstring[]

Returns ​

ScoreQuestion


yesNo() ​

ts
function yesNo(instructions): YesNoQuestion;

Build a calibrated yes-or-no question.

Parameters ​

ParameterType
instructionsstring

Returns ​

YesNoQuestion

Human input ​

HumanReply ​

What people answered in the run's Linear agent session.

Remarks ​

Every message sent since the run last read the session counts, including any sent before the question. body holds every message oldest first, each after its author's name; author and createdAt are the newest message's.

Properties ​

PropertyType
authorobject
author.idstring
author.namestring
bodystring
createdAtstring

Halt ​

ts
type Halt = object;

What the question says, in the words a stranger to the repo reads. headline is one plain sentence naming what paused and why, where names the routine it paused in so the footer can say so, about restates the ticket itself, notes are plain bullet lines, and onReply decides what the question asks the human to do: choose between the questions ("continue") or repair something and let the step run again ("retry"). mention adds people, by Linear email, to the operator (or the creator) and the assignee the question already mentions; an email no Linear user has is skipped.

Properties ​

PropertyType
about?string
headlinestring
mention?string[]
notes?string[]
onReply"continue" | "retry"
questions?HaltQuestion[]
wherestring

HaltOption ​

ts
type HaltOption = z.infer<typeof haltOptionSchema>;

One answer choice for a question shown to a human.


HaltQuestion ​

ts
type HaltQuestion = z.infer<typeof haltQuestionSchema>;

A question shown to a human while a run waits for their reply.


JsonValue ​

ts
type JsonValue = 
  | string
  | number
  | boolean
  | null
  | JsonValue[]
  | {
[key: string]: JsonValue;
};

A value that can be serialized as JSON and embedded in a prompt or comment.


haltOptionSchema ​

ts
const haltOptionSchema: ZodObject<{
  label: ZodString;
  recommended: ZodOptional<ZodBoolean>;
}, $strict>;

Validates an answer choice with a nonempty label and an optional recommendation marker.


haltQuestionSchema ​

ts
const haltQuestionSchema: ZodObject<{
  context: ZodOptional<ZodString>;
  options: ZodOptional<ZodArray<ZodObject<{
     label: ZodString;
     recommended: ZodOptional<ZodBoolean>;
  }, $strict>>>;
  question: ZodString;
}, $strict>;

Validates a question with nonempty text, optional context and optional suggested answers.

Linear tickets ​

TicketClaim ​

A ticket held exclusively by the current workflow run, with the Linear agent session the run talks to people in.

Properties ​

PropertyTypeDescription
consumedPromptIdsstring[]The messages in the session this run has already read. A later question skips them.
identifierstring-
installationNamestringThe Linear installation, as named on the hub, the ticket is reached through.
issueIdstring-
sessionIdstringThe Linear agent session this run asks its questions and posts its notes in.
tokenstring-

TicketComment ​

ts
type TicketComment = object;

A Linear ticket comment captured in a workflow snapshot.

Properties ​

PropertyType
authorstring | null
bodystring
createdAtstring
idstring

ts
type TicketLink = object;

A named external link attached to a Linear ticket.

Properties ​

PropertyType
titlestring
urlstring

TicketNote ​

ts
type TicketNote = object;

A note a ticket run posts in its Linear agent session that asks for nothing and suspends nothing. It carries its own words, the way a halt does, so the renderer owns the layout and every caller owns what it says.

Remarks ​

Linear marks a session stale after about 30 minutes with no activity, and a stale session hides its Stop button. Before a long quiet wait on people, such as a pull request waiting for review, post a note with run: "waiting".

Properties ​

PropertyTypeDescription
closingstringWhat the reader should do with it.
headlinestringOne plain sentence naming what jigs is about to do, or has stopped doing.
mention?string[]More people to mention, by Linear email, beyond the operator (or the creator) and the assignee. Each person is named once; an email no Linear user has is skipped with a warning.
notesstring[]The bullet lines under it.
run?"waiting" | "ended"What the run does after this note; omitted, it keeps working. Remarks "ended" is the run's final message, success or not; Linear shows the session as finished. Set it on every way out of the run. "waiting" shows the session as awaiting input, which never goes stale but shows no Stop button. The run does not read replies to a waiting note, so say in it where people act and how to stop the run.

TicketRef ​

ts
type TicketRef = object;

A compact reference to a related Linear ticket.

Properties ​

PropertyType
idstring
identifierstring
titlestring

TicketReviewPrompt() ​

ts
type TicketReviewPrompt = (input) => string;

Renders instructions for an agent to turn a ticket into an actionable handoff.

Parameters ​

ParameterType
inputTicketReviewPromptInput

Returns ​

string


TicketReviewPromptInput ​

ts
type TicketReviewPromptInput = object;

The rendered ticket supplied to a ticket-review prompt.

Properties ​

PropertyType
ticketstring

TicketSnapshot ​

ts
type TicketSnapshot = object;

The fixed ticket state shared by every step in one workflow activation.

Properties ​

PropertyType
blockedByTicketRef[]
blocksTicketRef[]
branchNamestring
commentsTicketComment[]
descriptionstring
fetchedAtstring
idstring
identifierstring
labelsstring[]
linksTicketLink[]
statestring
subIssuesTicketRef[]
titlestring
urlstring

ticketReviewPrompt ​

ts
const ticketReviewPrompt: TicketReviewPrompt;

The default prompt for reviewing a Linear ticket before implementation begins.


ticketReviewVerdictSchema ​

ts
const ticketReviewVerdictSchema: ZodObject<{
  about: ZodString;
  assumptions: ZodArray<ZodString>;
  brief: ZodString;
  questions: ZodArray<ZodObject<{
     context: ZodOptional<ZodString>;
     options: ZodOptional<ZodArray<ZodObject<{
        label: ZodString;
        recommended: ZodOptional<ZodBoolean>;
     }, $strict>>>;
     question: ZodString;
  }, $strict>>;
  verdict: ZodEnum<{
     needs-human: "needs-human";
     proceed: "proceed";
  }>;
}, $strict>;

Structured verdict returned by the agent that reviews a ticket before work starts.


renderTicketSnapshot() ​

ts
function renderTicketSnapshot(snapshot): string;

Render a ticket snapshot as Markdown for an agent prompt.

Parameters ​

ParameterType
snapshotTicketSnapshot

Returns ​

string

PagerDuty incidents ​

IncidentRef ​

ts
type IncidentRef = object;

A PagerDuty object an incident points at, such as its service or an assignee.

Properties ​

PropertyType
idstring
namestring
urlstring | null

IncidentSnapshot ​

ts
type IncidentSnapshot = object;

The incident as one workflow activation read it.

Properties ​

PropertyType
assigneesIncidentRef[]
createdAtstring
escalationPolicyIncidentRef
fetchedAtstring
idstring
numbernumber
serviceIncidentRef
status"triggered" | "acknowledged" | "resolved"
titlestring
urgency"high" | "low"
urlstring

Pull requests ​

CheckRun ​

A check or commit status reported on a pull request head.

Properties ​

PropertyType
conclusionstring | null
namestring
urlstring

MergeOptions ​

How workflow code asks for a pull request to be merged.

Extends ​

Properties ​

PropertyTypeDescription
approvalCovers?ApprovalCoverageWhich commits an approving review covers. Default "latest-commit".
consent?MergeConsentWhose consent the merge needs. Default "operator".

PullRequestComment ​

A comment on the pull request conversation, which hangs off no thread.

Properties ​

PropertyType
bodystring
createdAtstring
idnumber
updatedAtstring
userstring
userTypestring

PullRequestMarker ​

Hidden progress metadata stored in a pull request comment.

Properties ​

PropertyTypeDescription
kindMarkerKindreply answers the thing named by source, and status is a note about a commit, such as a stand-down after a refused merge, a CI failure jigs could not repair, or a merge refused for a state that will pass.
reason?StatusReasonRequired on a status marker, meaningless on any other.
runstringThe run that wrote it. Provenance for a reader; never matched on.
scopestringNames this workflow's work on the pull request. Keep it stable across replacement runs to recognize earlier notes and replies.
source?stringWhat this answers: a comment as id@updatedAt, or a commit sha.

PullRequestReadOptions ​

How workflow code asks for a pull request's approval to be read.

Extended by ​

Properties ​

PropertyTypeDescription
approvalCovers?ApprovalCoverageWhich commits an approving review covers. Default "latest-commit".

PullRequestReview ​

A submitted GitHub review of a pull request.

Properties ​

PropertyType
bodystring
commitSha?string
idnumber
statestring
submittedAtstring
userstring

PullRequestSnapshot ​

GitHub facts about a pull request, without a judgment about outstanding work.

Properties ​

PropertyTypeDescription
appBotstringThe login of the factory's GitHub App, <slug>[bot]: the account jigs posts as, and so do agents whose harness sets github.
approvalApprovalStateThe operator's consent: how the people's approving reviews read on this head.
ci"none" | "pending" | "red" | "green"none: no check or status has reported on this head yet. It is never green.
conversationCommentsPullRequestComment[]-
draftboolean-
failingChecksCheckRun[]-
headShastring-
labelsstring[]Label names on the pull request.
mergeCommitShastring | nullThe merge commit, once GitHub has made one.
mergedboolean-
mergeStatestringGitHub's own verdict on whether the pull request can merge right now, folding in conflicts, required checks and required reviews. "clean" is the only value that permits a merge; "unknown" means GitHub has not finished computing it, so the answer is "not yet, ask again".
reviewsPullRequestReview[]-
reviewThreadsReviewThread[]-
state"open" | "closed"-

ReviewComment ​

A comment anchored to a file in a pull request review.

Properties ​

PropertyType
bodystring
createdAtstring
idnumber
linenumber | null
pathstring
rootIdnumber
updatedAtstring
userstring

ReviewThread ​

A pull request review conversation, with its optional file location.

Properties ​

PropertyType
commentsReviewComment[]
linenumber | null
origin?"conversation"
pathstring
rootIdnumber

ApprovalState ​

ts
type ApprovalState = "approved" | "changes-requested" | "stale" | "none";

How the operator's consent reads right now. stale is an approval that named an earlier commit. This differs from a pull request nobody has approved.


PullRequestRef ​

ts
type PullRequestRef = RepositoryRef & object;

Identifies a pull request by its repository, the installation jigs reaches it through, and its number.

Type Declaration ​

NameTypeDescription
numbernumberThe repository-local pull request number.

RepositoryRef ​

ts
type RepositoryRef = object;

Identifies a repository, and the GitHub installation jigs reaches it through.

Properties ​

PropertyTypeDescription
installationNamestringThe name of the GitHub App installation, as named on the hub, that jigs acts through.
ownerstringThe GitHub organization or account that owns the repository.
repostringThe repository name.

StatusReason ​

ts
type StatusReason = "merge" | "ci" | "merge-retry";

Label a status note as a merge refusal, CI failure or temporary merge refusal. Distinct reasons keep notes for the same commit independent. They do not change merge readiness or schedule more work.


blockedMergeNote() ​

ts
function blockedMergeNote(snapshot): string | null;

The note to leave on a pull request that is approved and green but that GitHub blocks from merging, or null when that is not why it waits.

Parameters ​

ParameterType
snapshotPullRequestSnapshot

Returns ​

string | null

Remarks ​

GitHub does not say which branch rule blocks the merge, so without a note jigs would wait in silence.


defaultPullRequestScope() ​

ts
function defaultPullRequestScope(subject): string;

The scope a caller gets when it names none: this workflow's function name and the subject it was given: a ticket key or the pull request itself. Pass an explicit scope to continue another workflow's work, or to review a pull request independently of the run delivering it.

Parameters ​

ParameterType
subjectstring

Returns ​

string


isPullRequestMergeReady() ​

ts
function isPullRequestMergeReady(snapshot): boolean;

Whether current GitHub facts satisfy the configured approval and merge requirements.

Parameters ​

ParameterType
snapshotPullRequestSnapshot

Returns ​

boolean


parseMarkers() ​

ts
function parseMarkers(body): PullRequestMarker[];

Every marker in one comment body, in the order they appear.

Parameters ​

ParameterType
bodystring

Returns ​

PullRequestMarker[]


pullRequestSnapshotKey() ​

ts
function pullRequestSnapshotKey(snapshot): string;

A comparison key for the facts in a pull request snapshot.

Parameters ​

ParameterType
snapshotPullRequestSnapshot

Returns ​

string

Remarks ​

Collection ordering and incidental fields do not change the key. Compare keys for equality; the key format is opaque and is not a durable identifier.


renderChecks() ​

ts
function renderChecks(failing): string;

Render failed checks as a Markdown list for a pull request note.

Parameters ​

ParameterType
failingCheckRun[]

Returns ​

string

Pull request delivery ​

BuildAndReviewOptions ​

What buildAndReview needs besides the delivery.

Properties ​

PropertyTypeDescription
roundsnumberOne round is one build plus one review of what it committed.

BuildApproved ​

A change the reviewer approved.

Properties ​

PropertyTypeDescription
ledgerReviewRound[]-
notesstring[]The non-blocking findings of the approving round, for a person to read.
outcome"approved"-
reviewedCommitstringThe commit the reviewer approved. Publish exactly this one.

BuildFacts ​

What a fresh build prompt is given: the open findings and the diff so far.

Type Parameters ​

Type Parameter
W

Properties ​

PropertyTypeDescription
diffstringEmpty before the first commit.
findingsobject[]-
workW-
worktreeWorktree-

BuildStopped ​

Why buildAndReview stopped without an approved change. Nothing is pushed: committed work stays in the worktree for the workflow to push or leave.

Remarks ​

rounds-exhausted carries the blocking findings still open. uncommitted and no-commits mean the builder left uncommitted changes, or committed nothing new, so there was nothing to review.

Properties ​

PropertyTypeDescription
findingsstring[]-
outcome"stopped"-
reason"rounds-exhausted" | "uncommitted" | "no-commits"-
roundnumberThe round it stopped in; for rounds-exhausted, the last round.

Delivery ​

One piece of work taken to a pull request: what to build, where, and the agents that build, review and describe it.

Remarks ​

work is yours: only your prompts read it. Give each delivery its own agent session objects: a session holds its agent's conversation, and its name only labels log lines. writer describes the pull request and defaults to builder. Each routine reads only some of these fields, so a full delivery can be passed to all of them.

Type Parameters ​

Type Parameter
W

Properties ​

PropertyTypeDescription
builderAgentSession-
keystringOne key per pull request: it scopes the hidden markers on that pull request's notes.
promptsDeliveryPrompts<W>-
reviewerAgentSession-
workW-
worktreeWorktree-
writer?AgentSession-

DeliveryPrompts ​

The prompts a delivery sends, written by the workflow. jigs adds only the line that tells each agent the shape of its answer.

Remarks ​

A turn with two forms goes to an agent session: resume is sent to an agent that holds the earlier turns, so it says only what is new, and fresh to one starting from nothing, so it says everything. describe is sent either way.

Type Parameters ​

Type Parameter
W

Properties ​

PropertyType
buildobject
build.fresh(facts) => string
build.resume(facts) => string
describe(facts) => string
maintainobject
maintain.fresh(facts) => string
maintain.resume(facts) => string
reviewobject
review.fresh(facts) => string
review.resume(facts) => string

Described ​

A pull request title and body.

Properties ​

PropertyType
bodystring
titlestring

DescribeOptions ​

What describePullRequest needs besides the delivery.

Properties ​

PropertyTypeDescription
check?(described) => string[]The problems with a title and body, such as a title that breaks your naming convention; none means they are fine. The writer is sent back once with the problems, and problems in its second answer throw.

FollowOptions ​

What followPullRequestToOutcome needs besides the delivery and the pull request.

Properties ​

PropertyTypeDescription
approvalCoversApprovalCoverageWhich commits a person's approving review covers.
attemptsPerUpdatenumberBuilder turns allowed for each change to the pull request, including recovery.
mergeWhen(snapshot) => booleanWhether you consent to merging this snapshot now. jigs still merges only when GitHub reports the pull request approved, green and clean, so this can only make merging stricter. Return false to leave every merge to a person, or check the snapshot, such as for a label.
onNeedsHuman(facts) => Promise<void>Tell a person the pull request needs them. Watching goes on: the next change to the pull request picks the work back up. The same facts are never sent twice in a row.
wake(snapshot, scope) => string[]The facts in a snapshot that wake the builder, one string each; it is woken for one it has not been shown. scope is the delivery's marker scope. Pass builderWakeFacts for the default rules, or your own function, for example to ignore another bot's comments.

MaintainFacts ​

What a maintenance prompt is given: the pull request as GitHub reports it, and any local work the builder has to recover first.

Properties ​

PropertyTypeDescription
newsstring[]The wake facts in snapshot the builder has not been shown, as the wake rule wrote them. Empty when the turn only recovers local work.
prPullRequestRef-
recovery?UnpublishedWork-
snapshotPullRequestSnapshot-

PublishOptions ​

What publishPullRequest needs besides the delivery.

Properties ​

PropertyTypeDescription
bodystring-
commitstringThe commit to publish. It must be the worktree's HEAD, with nothing uncommitted.
draft?boolean-
titlestring-

ReviewFacts ​

What a fresh review prompt is given: the commit under review and every earlier round.

Type Parameters ​

Type Parameter
W

Properties ​

PropertyType
diffstring
headShastring
ledgerReviewRound[]
workW
worktreeWorktree

ReviewRound ​

One build and the review of what it committed.

Properties ​

PropertyTypeDescription
findingsobject[]-
responsesobject[]The builder's answers to the previous round's findings; empty on the first round.
roundnumber-
verdict"approved" | "changes-requested"changes-requested when any finding is blocking.

UnpublishedWork ​

Local work the pull request has never had: uncommitted changes, or a local commit that was not pushed. It holds back a merge until it is published.

Properties ​

PropertyType
dirtyboolean
localHeadstring
pullRequestHeadstring

BuildDelivery ​

ts
type BuildDelivery<W> = Pick<Delivery<W>, "work" | "worktree" | "builder" | "reviewer"> & object;

The parts of a delivery buildAndReview reads.

Type Declaration ​

NameType
promptsPick<DeliveryPrompts<W>, "build" | "review">

Type Parameters ​

Type Parameter
W

BuildResult ​

ts
type BuildResult = BuildApproved | BuildStopped;

What buildAndReview returns: an approved change, or a stop.


DescribeDelivery ​

ts
type DescribeDelivery<W> = Pick<Delivery<W>, "work" | "worktree" | "builder" | "writer"> & object;

The parts of a delivery describePullRequest reads.

Type Declaration ​

NameType
promptsPick<DeliveryPrompts<W>, "describe">

Type Parameters ​

Type Parameter
W

FindingResponse ​

ts
type FindingResponse = z.output<typeof findingResponse>;

The builder's answer to one finding: what it changed, or why it changed nothing.


FollowDelivery ​

ts
type FollowDelivery<W> = Pick<Delivery<W>, "work" | "key" | "worktree" | "builder"> & object;

The parts of a delivery followPullRequestToOutcome reads.

Type Declaration ​

NameType
promptsPick<DeliveryPrompts<W>, "maintain">

Type Parameters ​

Type Parameter
W

FollowResult ​

ts
type FollowResult = 
  | {
  outcome: "merged";
}
  | {
  outcome: "closed";
};

How followPullRequestToOutcome ended: the pull request merged, or closed unmerged.


NeedsHuman ​

ts
type NeedsHuman = 
  | {
  detail: string;
  reason: "builder-asked" | "attempts-exhausted";
  unpublished?: UnpublishedWork;
}
  | {
  detail: string;
  reason: "merge-refused";
  tries: number;
}
  | {
  detail: string;
  headSha: string;
  reason: "merge-blocked";
};

Why a pull request needs a person, as facts for the workflow to word and send.

Remarks ​

  • builder-asked: the builder said it needs a person; detail is its summary.
  • attempts-exhausted: the builder's attempts for one pull request update ran out with local work still unpublished; detail is its last summary.
  • merge-refused: GitHub refused the merge; detail is the last refusal and tries how often jigs tried. A transient refusal is retried up to ten times before it is reported.
  • merge-blocked: GitHub blocks an approved, green pull request from merging, usually because of a branch rule; detail says so in a sentence. Sent once per head. Mark a note posted about it with headSha and the delivery's scope, so it does not wake the builder and a later run does not post it again.

unpublished is set when local work the pull request has never had holds back the merge. The local worktree path never appears in detail.


PublishDelivery ​

ts
type PublishDelivery = Pick<Delivery<unknown>, "worktree">;

The parts of a delivery publishPullRequest reads.


ReviewFinding ​

ts
type ReviewFinding = z.output<typeof reviewFinding>;

One finding from a review of the change.


builderWakeFacts() ​

ts
function builderWakeFacts(snapshot, scope): string[];

The default wake rule for followPullRequestToOutcome: the facts in a snapshot a builder can act on, one string each.

Parameters ​

ParameterType
snapshotPullRequestSnapshot
scopestring

Returns ​

string[]

Remarks ​

A review with a body or one requesting changes, a new comment or a person's edit of one, a check failing on the current head, and a conflict with the base each wake the builder. Checks that queue, run or pass, a bare approval, label changes, a bot editing its own comment, the App bot's unmarked comments (the builder's own replies) and notes marked with the delivery's scope wake nothing. To change the rules, wrap it or pass your own function as wake.

Example ​

ts
import { builderWakeFacts, type PullRequestSnapshot } from "@jigs-ai/jigs";

// Also ignore a coverage bot's comments.
const wake = (snapshot: PullRequestSnapshot, scope: string) =>
  builderWakeFacts(
    {
      ...snapshot,
      conversationComments: snapshot.conversationComments.filter(
        (comment) => comment.user !== "codecov[bot]",
      ),
    },
    scope,
  );

Slack messages ​

SlackAuthor ​

Someone who posted in Slack.

Remarks ​

id is the Slack user ID, or the bot ID for an integration that posts without a user. email is missing for bots. isOwnBot marks the factory's own bot, which is what posts every message jigs sends.

Properties ​

PropertyType
botboolean
email?string
idstring
isOwnBotboolean
namestring

SlackPost ​

One Slack message: its timestamp, which is also its ID in the channel, its mrkdwn text and who wrote it.

Properties ​

PropertyType
authorSlackAuthor
textstring
tsstring

SlackQuestion ​

The thread a wait reads, named by the ts of its top-level message (never a reply's). lastRead is the ts of the newest post the workflow has read, never its own question; only human replies after it count. until, an ISO 8601 timestamp, is when to stop waiting.

Properties ​

PropertyTypeDescription
channelstring-
installationNamestringThe Slack installation, as named on the hub, the thread is read through; only its events wake the wait.
lastReadstring-
threadTsstring-
until?string-

SlackMessageSnapshot ​

ts
type SlackMessageSnapshot = 
  | {
  channel: string;
  gone: true;
  ts: string;
}
  | SlackPost & object;

A Slack message and its thread, as fetchSlackMessage read them, or gone when the message was deleted.

Remarks ​

replies are the thread's replies, oldest first, without the message itself.


SlackReplyResult ​

ts
type SlackReplyResult = 
  | {
  outcome: "replied";
  replies: SlackPost[];
}
  | {
  outcome: "timed-out";
}
  | {
  outcome: "gone";
};

How waitForSlackReply ended: replied with the new human replies (oldest first, never empty), timed-out at until, or gone when the thread's top-level message was deleted.

Git/change data ​

ChangePatch ​

Patches for selected paths between two resolved commits.

Properties ​

PropertyTypeDescription
patchesobject[]Patch text for each selected path, in first-requested order.
truncatedbooleanWhether the shared text limit cut off any patch text.

ChangeSummary ​

A bounded description of the committed changes between two Git refs.

Properties ​

PropertyTypeDescription
basestringThe resolved base commit.
commitsobject[]Commits reachable from head but not base, newest first.
filesFileChange[]Files that differ directly between the base and head trees.
headstringThe resolved head commit.
truncatedbooleanWhether file or commit limits caused results to be omitted.

FileChange ​

One file changed between the base and head trees.

Properties ​

PropertyTypeDescription
additionsnumberThe number of added lines, or zero for a binary file.
deletionsnumberThe number of deleted lines, or zero for a binary file.
pathstringThe changed path. Renames use the path in the head tree.
statusChangeStatusHow the path differs between the two trees.

ChangeStatus ​

ts
type ChangeStatus = "added" | "modified" | "deleted" | "renamed" | "other";

How a file differs between the base and head trees.


renderChangeSummary() ​

ts
function renderChangeSummary(summary): string;

Render a Markdown review summary with commits, totals and up to 60 changed-file rows.

Parameters ​

ParameterType
summaryChangeSummary

Returns ​

string

Runtime and resources ​

PullRequestWorktree ​

A worktree checked out at a pull request's head commit, with no branch of its own.

Remarks ​

It is for checking the pull request as it stands, so it cannot be pushed. Pass headSha to mergePullRequest to merge exactly the commit that was checked. Commits made in it are not kept when the run's resources are released.

Properties ​

PropertyTypeDescription
bindingstringThe named repository binding in the factory configuration.
headShastringThe pull request's head commit, which the worktree is checked out at.
installationNamestringThe binding's GitHub installation, as named on the hub, that reaches its repository.
pathstring-

ReleaseReport ​

The result of applying a release policy to one run's resources.

Properties ​

PropertyTypeDescription
policyobjectThe policy applied by this release attempt.
policy.onFailure"release" | "keep"What to do with eligible resources after a failed or cancelled run.
policy.onSuccess"release" | "keep"What to do with eligible resources after a completed run.
resourcesResourceRecord[]Every resource the run recorded, with its state and reason after this attempt.

ResourceRecord ​

One recorded resource and what has happened to it. Records stay after release as history.

Extends ​

Properties ​

PropertyTypeDescription
identitystringThe stable name that distinguishes this resource from others of the same kind.
kindstringThe resource category, such as worktree or run-directory.
reasonstring | nullWhy the resource is in its state, or null while it is live and untouched.
runIdstringThe run that owns the resource.
stateResourceState-
updatedAtstringWhen the state last changed, as an ISO timestamp.
urlstringAn absolute URL where a human can inspect the resource.

RunResource ​

A durable thing that a run created or otherwise owns a reference to.

Extended by ​

Properties ​

PropertyTypeDescription
identitystringThe stable name that distinguishes this resource from others of the same kind.
kindstringThe resource category, such as worktree or run-directory.
urlstringAn absolute URL where a human can inspect the resource.

Worktree ​

A provisioned repository worktree and the commit it was cut from.

Properties ​

PropertyTypeDescription
baseShastring-
bindingstringThe named repository binding in the factory configuration.
branchstring-
defaultBranchstring-
installationNamestringThe binding's GitHub installation, as named on the hub, that reaches its repository.
pathstring-

ReleasePolicy ​

ts
type ReleasePolicy = z.input<typeof releaseSchema>;

Selects whether eligible run resources are released for each terminal outcome.


ResourceState ​

ts
type ResourceState = "live" | "kept" | "released" | "failed";

Where a recorded resource stands: live until release decides, then kept by policy or a safety check, released, or failed when the release attempt errored and will be retried.

Errors and utilities ​

ClaimConflictError ​

A ticket-claim failure that identifies the run already holding the ticket.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new ClaimConflictError(resource, owningRunId): ClaimConflictError;
Parameters ​
ParameterType
resourcestring
owningRunIdstring
Returns ​

ClaimConflictError

Overrides ​
ts
Error.constructor

Properties ​

PropertyType
owningRunIdstring
resourcestring

JigsError ​

An operator-readable failure that is safe to construct inside a workflow.

Extends ​

  • Error

Extended by ​

Constructors ​

Constructor ​
ts
new JigsError(message, hint?): JigsError;
Parameters ​
ParameterType
messagestring
hint?string
Returns ​

JigsError

Overrides ​
ts
Error.constructor

Properties ​

PropertyTypeDescription
hint?stringWhat the reader can do about it. Quote each command to run in backticks, as in stop the service first: `pnpm exec jigs service stop` : the CLI prints it on its own line.

JitCheckError ​

A failed just-in-time tool check, with repair details for each failure.

Extends ​

  • Error

Constructors ​

Constructor ​
ts
new JitCheckError(failures): JitCheckError;
Parameters ​
ParameterType
failuresobject & object[]
Returns ​

JitCheckError

Overrides ​
ts
Error.constructor

Properties ​

PropertyType
failuresobject & object[]

interpolate() ​

ts
function interpolate(template, values): string;

Replace named once, leaving unknown names unchanged.

Parameters ​

ParameterType
templatestring
valuesRecord<string, string>

Returns ​

string


unreachable() ​

ts
function unreachable(value): never;

Fail an exhaustive branch if an unexpected value reaches it at runtime.

Parameters ​

ParameterType
valuenever

Returns ​

never

Factory plumbing ​

AgentRequest ​

ts
type AgentRequest = 
  | Omit<RunAgentOptions, "output"> & object
  | Omit<AskAgentOptions, "output"> & object;

Serializable agent request passed to a durable step.


ModelRequest ​

ts
type ModelRequest = Omit<AskModelOptions, "output"> & object;

Serializable API model request passed to a durable step.

Type Declaration ​

NameType
outputSchema?OutputJsonSchema

Linear agent sessions ​

LinearAgentConversationOptions ​

How a Linear agent conversation runs: the Claude harness and the worktree it works in.

Remarks ​

instructions lead the first message Claude reads, which carries Linear's context for the session when Linear sends one. The conversation ends once no one has replied for idleFor, a duration such as "30m" or milliseconds; four hours by default.

Properties ​

PropertyType
cwdstring
harnessHarness
idleFor?| number | `${number}s` | `${number}d` | `${number}h` | `${number}m`
instructions?string

LinearAgentConversationResult ​

ts
type LinearAgentConversationResult = 
  | {
  outcome: "idle" | "stopped";
  turns: number;
}
  | {
  error: string;
  outcome: "failed";
  turns: number;
};

How a Linear agent conversation ended, and how many turns it ran.

Type Aliases ​

ApprovalCoverage ​

ts
type ApprovalCoverage = "latest-commit" | "any-commit";

Which commits an approving review covers, chosen in workflow code.

Remarks ​

latest-commit, the default, counts an approval only on the commit it names, so a push withdraws it. any-commit keeps a person's approval counting through later pushes until a later review requests changes or the approval is dismissed; approvals by a bot, such as an agent acting as the factory's GitHub App, never count.


MergeConsent ​

ts
type MergeConsent = "operator" | "workflow";

Whose consent a merge needs, chosen in workflow code for each merge.

Remarks ​

operator, the default, needs a person's approving review. workflow lets the workflow's own checks stand in for it, for a workflow that judges a pull request itself, such as one that tests a dependency update before merging it. Every other merge requirement still holds, and a review requesting changes still stops the merge.