From terse
Create a new Terse SDK job. Use when the user wants to build a new automation, agent, or job that reacts to events (GitHub PRs, Slack messages, Linear issues, cron schedules, etc.) and takes actions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/terse:create <job-description><job-description>The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create a new Terse SDK job based on: **$ARGUMENTS**
Create a new Terse SDK job based on: $ARGUMENTS
The bundled sdk-reference.md is a quick offline cheat sheet, but Terse evolves fast. Always pull the live docs before writing non-trivial code:
terse init, terse generate, terse test, terse deploy, and friends.If anything in the bundled reference disagrees with the live docs, trust the live docs.
Do not search or read node_modules/. Everything you need is in src/terse.jobs.ts, src/terse.generated.ts, the bundled sdk-reference.md, and live Terse docs — not inside dependency install dirs.
src/terse.generated.ts is the source of truth for connected integrations, available triggers, skills, resources, and deterministic wrappers. Read it before choosing triggers or skills. Do not run terse integrate list — the generated file already reflects what terse integrate connected.
If src/terse.generated.ts is missing in an existing project, run terse generate before inventing helpers. If it exists but does not expose the helper you need, rerun terse generate. Never edit the generated file directly.
Open src/terse.jobs.ts (the canonical job entry file). The CLI can still load src/index.ts as a legacy fallback, and custom layouts can override the entry file with --entry-file.
If the repo already uses a custom entry file, follow that layout and pass --entry-file on later terse commands.
If src/terse.jobs.ts exists, add the new job below the existing jobs.
If the repo only has src/index.ts, treat that as a legacy fallback instead of creating a second competing entry file.
If no runtime entry exists yet, create one:
import { createJob, TerseAgent } from "terse-sdk"
Choose triggers based on what events the job should respond to. Import trigger factories and resource constants from ./terse.generated.
Only use triggers and resources that actually exist in src/terse.generated.ts. Do not invent constants that are not defined there.
Skills are only for agentic steps. Add skill configs only for integrations the model needs during run() or runAndWait(). If every action is deterministic via toolbox or agent.tools, you may need few or no skills.
Do not add skills for integrations you only call deterministically. toolbox and agent.tools.* are direct code paths — not model-selected tools.
If a required integration is missing from src/terse.generated.ts:
terse integrate connect <type> --field key=value --fields-stdin--fields-stdin, not --fieldterse integrate connect <type> --json. The CLI opens the user's browser automatically and exits 2 with a handoff payload that includes a waitCommand. Run that waitCommand (e.g. terse integrate wait gmail) to block until the user finishes authorization — it exits 0 when the connection is live. Only then continue. Do not dump the URL back to the user; the browser is already open.connect <a> --json → wait <a> → connect <b> --json → wait <b>. Do not batch the connect calls; the user can only authorize one browser tab at a time anyway.terse generate and reopen src/terse.generated.tsAdd a filter function if the job should skip certain events:
event.sender.login.includes("[bot]"))Filters prevent unnecessary agent runs and save cost.
Use the appropriate event type from terse-sdk. Plan the handler as a pipeline: filters and deterministic steps first, agent last (if at all).
Deterministic steps — map each known action to toolbox or agent.tools:
import { toolbox, SlackChannel } from "./terse.generated"
// No agent required for a fixed Slack post
await toolbox.slack.sendMessage({
channelId: SlackChannel.Engineering.channelId,
message: `New PR: ${event.pullRequest.title}`,
thread_ts: "",
blocks: "",
})
Agentic steps — use TerseAgent only where judgment is required. Include full event context via event.formatForAgentRunner(). Write clear, specific prompts; avoid vague instructions like "handle this event."
Combined pattern — deterministic setup, then a narrow agent task:
const message = await toolbox.slack.sendMessage({ ... })
await agent.runAndWait(
`Summarize this PR and reply in thread (thread_ts: ${message.message_ts}). ` +
`Context: ${event.formatForAgentRunner()}`
)
If the user's request is fully deterministic (e.g. "post X to Slack when Y happens"), do not create an agent at all.
Do not assume bare terse test is available. It needs an interactive terminal.
In non-interactive contexts, prefer:
terse test list "<job-name>" --json
terse test show <id> "<job-name>" --json
terse test run "<job-name>" --id <id>
Use terse test show when you need to inspect the selected event before running it.
Use terse test run --event-file <path> or --event <json> when you already have the exact serialized trigger payload.
If multiple jobs exist, pass the job name explicitly because non-interactive job loading cannot prompt.
Reserve bare terse test for manual sessions with a TTY.
Verify:
terse-sdk and ./terse.generatedsrc/terse.jobs.ts unless the repo intentionally uses a custom or legacy entry filename is unique and descriptivetoolbox or agent.tools, not runAndWait promptsskills only lists integrations used in agentic stepsonTrigger matches the trigger typesrc/terse.generated.tsevent.formatForAgentRunner()terse test list/show/run when the agent is not in an interactive terminalDo not run terse deploy automatically. After the job is written and verified, ask the user whether to deploy it now.
Example prompt:
The job is ready locally. Deploy it to production with
terse deploy? (This syncs all jobs in the project — removed jobs are deleted remotely.)
terse deploy and report the outcome.terse deploy when ready.import { createJob, TerseAgent, type GithubPRTrigger } from "terse-sdk"
import { GitHub, Slack, Repos, SlackChannel, toolbox } from "./terse.generated"
createJob({
name: "Summarize PR and notify Slack",
triggers: [GitHub.onPROpened({ repo: Repos.MyOrg.MyRepo })],
filter: async (event: GithubPRTrigger) => {
return !event.sender.login.includes("[bot]")
},
onTrigger: async (event: GithubPRTrigger) => {
// Deterministic: fixed channel, fixed opener — no agent needed
const message = await toolbox.slack.sendMessage({
channelId: SlackChannel.Engineering.channelId,
message: `New PR from ${event.sender.login}: ${event.pullRequest.title}`,
thread_ts: "",
blocks: "",
})
// Agentic: only the summary needs judgment
const agent = TerseAgent.create({
prompt: "You summarize pull requests concisely.",
skills: [GitHub.skill({ repos: [Repos.MyOrg.MyRepo] })],
})
await agent.runAndWait(
`Summarize the changes in this PR and post as a thread reply ` +
`(thread_ts: ${message.message_ts}). ` +
`Focus on what changed, why it matters, and what reviewers should look at first. ` +
`Keep it concise. Context: ${event.formatForAgentRunner()}`
)
},
})
npx claudepluginhub terseai/terse --plugin terseGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.