Skip to content

Quickstart

Start here when you want a new Junior app that follows the supported Hono, Nitro, and Vercel shape.

Use the same baseline that the scaffolded CI workflow uses:

  • Node.js 24
  • pnpm
  • A Redis URL for queue and state storage

Slack credentials are needed before the bot can reply in Slack. You can scaffold and verify the local health route first, then finish Slack App Setup.

Run the initializer in an empty target directory:

Terminal window
pnpm dlx @sentry/junior init my-bot
cd my-bot
pnpm install

junior init creates the app entrypoint, Nitro/Vite config, Vercel config, Vercel queue consumer source, CI workflow, app context files, local plugin and skill directories, and .env.example.

The generated app/ files have separate jobs:

FilePurpose
app/SOUL.mdAssistant voice and behavior.
app/WORLD.mdOperational context and domain knowledge.
app/DESCRIPTION.mdUser-facing app description.
app/skills/Local skills that are not owned by a plugin.
app/plugins/App-local plugin manifests and bundled plugin skills.

Do not recreate the old ABOUT.md; use WORLD.md and DESCRIPTION.md.

Copy .env.example to your local environment file, then generate one stable JUNIOR_SECRET:

Terminal window
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"

Set these values before running real turns:

VariableRequiredPurpose
SLACK_SIGNING_SECRETYes, for Slack trafficVerifies Slack requests.
SLACK_BOT_TOKENYes, for Slack repliesPosts thread replies and calls Slack APIs.
REDIS_URLYesQueue and runtime state storage.
JUNIOR_SECRETYesSigns internal resume callbacks and sandbox requester context.
JUNIOR_BOT_NAMENoBot display/config name.
JUNIOR_SLASH_COMMANDNoSlack slash command name. Defaults to /jr.
AI_MODELNoPrimary assistant model override.
AI_FAST_MODELNoLightweight routing/classification model override.
AI_VISION_MODELNoEnables image understanding when set.
AI_WEB_SEARCH_MODELNoSearch model override.
JUNIOR_STATE_KEY_PREFIXNoRedis key namespace for this local app/environment.

See Config & Environment for the full reference.

Start the local dev server:

Terminal window
pnpm dev

The app listens on http://localhost:3000 by default.

Check the health route before wiring Slack:

Terminal window
curl http://localhost:3000/health

The response should include status: "ok".

After you complete Slack App Setup, point Slack at your tunnel URL and mention the bot in a thread. The reply should appear in the same thread.

Packaged plugins must be installed and explicitly listed in the plugin set referenced by juniorNitro so Nitro bundles their manifests, skills, hooks, and runtime dependencies.

Install only the plugins you plan to enable:

Terminal window
pnpm add @sentry/junior-agent-browser @sentry/junior-datadog @sentry/junior-github @sentry/junior-hex @sentry/junior-linear @sentry/junior-notion @sentry/junior-scheduler @sentry/junior-sentry @sentry/junior-vercel

Then create one runtime-safe plugin set:

plugins.ts
import { defineJuniorPlugins } from "@sentry/junior";
import { githubPlugin } from "@sentry/junior-github";
import { schedulerPlugin } from "@sentry/junior-scheduler";
export const plugins = defineJuniorPlugins([
"@sentry/junior-agent-browser",
"@sentry/junior-datadog",
githubPlugin({
botNameEnv: "GITHUB_APP_BOT_NAME",
botEmailEnv: "GITHUB_APP_BOT_EMAIL",
}),
"@sentry/junior-hex",
"@sentry/junior-linear",
"@sentry/junior-notion",
schedulerPlugin(),
"@sentry/junior-sentry",
]);

Point juniorNitro() at that module. createApp() reads the same plugin set from Nitro’s virtual module, so the server entry does not repeat it:

nitro.config.ts
import { defineConfig } from "nitro";
import { juniorNitro } from "@sentry/junior/nitro";
export default defineConfig({
preset: "vercel",
modules: [
juniorNitro({
plugins: "./plugins",
}),
],
routes: {
"/**": { handler: "./server.ts" },
},
});
server.ts
import { createApp } from "@sentry/junior";
const app = await createApp();
export default app;

Run the app check after changing plugins or skills:

Terminal window
pnpm check

The runtime-safe plugin set is also where trusted runtime hooks are registered. schedulerPlugin() enables scheduled task tools and heartbeat behavior, and githubPlugin() enforces Git commit attribution. See Scheduler Plugin and GitHub Plugin for those setups.

When enabled plugins declare sandbox runtime dependencies, the scaffolded build runs snapshot warmup:

package.json
{
"scripts": {
"check": "junior check",
"dev": "vite dev",
"build": "junior snapshot create && vite build"
}
}

Run pnpm check before pnpm build so manifest and skill issues fail early.

Finish Slack App Setup so the bot can receive events, then follow Deploy to Vercel for production.