thepopebot 1.2.76-beta.2 → 1.2.76-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +3 -3
  2. package/api/CLAUDE.md +11 -4
  3. package/api/index.js +56 -18
  4. package/bin/CLAUDE.md +7 -4
  5. package/bin/cli.js +25 -45
  6. package/config/CLAUDE.md +23 -4
  7. package/drizzle/0021_coding_agent_workspace.sql +1 -0
  8. package/drizzle/0022_organic_apocalypse.sql +16 -0
  9. package/drizzle/0023_needy_ender_wiggin.sql +1 -0
  10. package/drizzle/meta/0021_snapshot.json +639 -0
  11. package/drizzle/meta/0022_snapshot.json +743 -0
  12. package/drizzle/meta/0023_snapshot.json +750 -0
  13. package/drizzle/meta/_journal.json +21 -0
  14. package/lib/CLAUDE.md +2 -2
  15. package/lib/actions.js +9 -1
  16. package/lib/ai/CLAUDE.md +72 -57
  17. package/lib/ai/helper-llm.js +108 -0
  18. package/lib/ai/index.js +308 -438
  19. package/lib/ai/line-mappers.js +42 -24
  20. package/lib/ai/scope.js +26 -0
  21. package/lib/ai/sdk-adapters/CLAUDE.md +114 -0
  22. package/lib/ai/sdk-adapters/claude-code.js +120 -8
  23. package/lib/ai/system-prompt.js +34 -0
  24. package/lib/ai/workspace-setup.js +19 -35
  25. package/lib/channels/CLAUDE.md +14 -4
  26. package/lib/channels/base.js +6 -2
  27. package/lib/channels/commands/index.js +42 -0
  28. package/lib/channels/commands/session.js +53 -0
  29. package/lib/channels/commands/verify.js +18 -0
  30. package/lib/channels/telegram.js +79 -28
  31. package/lib/chat/CLAUDE.md +4 -4
  32. package/lib/chat/actions.js +270 -49
  33. package/lib/chat/api.js +185 -31
  34. package/lib/chat/components/CLAUDE.md +6 -2
  35. package/lib/chat/components/chat-input.js +77 -47
  36. package/lib/chat/components/chat-input.jsx +77 -40
  37. package/lib/chat/components/chat-page.js +2 -0
  38. package/lib/chat/components/chat-page.jsx +3 -0
  39. package/lib/chat/components/chat.js +62 -14
  40. package/lib/chat/components/chat.jsx +68 -10
  41. package/lib/chat/components/code-mode-toggle.js +141 -22
  42. package/lib/chat/components/code-mode-toggle.jsx +129 -20
  43. package/lib/chat/components/containers-page.js +58 -40
  44. package/lib/chat/components/containers-page.jsx +64 -25
  45. package/lib/chat/components/crons-page.js +17 -3
  46. package/lib/chat/components/crons-page.jsx +34 -6
  47. package/lib/chat/components/index.js +2 -2
  48. package/lib/chat/components/message.js +18 -3
  49. package/lib/chat/components/message.jsx +18 -3
  50. package/lib/chat/components/profile-page.js +182 -4
  51. package/lib/chat/components/profile-page.jsx +196 -1
  52. package/lib/chat/components/scope-picker.js +21 -0
  53. package/lib/chat/components/scope-picker.jsx +27 -0
  54. package/lib/chat/components/settings-chat-page.js +11 -11
  55. package/lib/chat/components/settings-chat-page.jsx +14 -18
  56. package/lib/chat/components/settings-coding-agents-page.js +110 -16
  57. package/lib/chat/components/settings-coding-agents-page.jsx +87 -3
  58. package/lib/chat/components/settings-github-page.js +5 -0
  59. package/lib/chat/components/settings-github-page.jsx +5 -0
  60. package/lib/chat/components/settings-layout.js +3 -3
  61. package/lib/chat/components/settings-layout.jsx +3 -3
  62. package/lib/chat/components/settings-secrets-layout.js +1 -2
  63. package/lib/chat/components/settings-secrets-layout.jsx +1 -2
  64. package/lib/chat/components/settings-secrets-page.js +180 -75
  65. package/lib/chat/components/settings-secrets-page.jsx +212 -66
  66. package/lib/chat/components/triggers-page.js +17 -3
  67. package/lib/chat/components/triggers-page.jsx +34 -6
  68. package/lib/chat/components/ui/combobox.js +18 -2
  69. package/lib/chat/components/ui/combobox.jsx +17 -1
  70. package/lib/chat/components/ui/dropdown-menu.js +23 -2
  71. package/lib/chat/components/ui/dropdown-menu.jsx +27 -2
  72. package/lib/chat/telegram-profile.js +33 -0
  73. package/lib/cluster/CLAUDE.md +9 -3
  74. package/lib/code/CLAUDE.md +11 -3
  75. package/lib/code/actions.js +47 -8
  76. package/lib/code/terminal-view.js +31 -21
  77. package/lib/code/terminal-view.jsx +32 -23
  78. package/lib/config.js +15 -4
  79. package/lib/containers/CLAUDE.md +16 -6
  80. package/lib/db/CLAUDE.md +5 -2
  81. package/lib/db/chats.js +9 -17
  82. package/lib/db/code-workspaces.js +8 -3
  83. package/lib/db/config.js +0 -1
  84. package/lib/db/index.js +12 -0
  85. package/lib/db/schema.js +24 -1
  86. package/lib/db/user-channels.js +129 -0
  87. package/lib/llm-providers.js +8 -0
  88. package/lib/maintenance.js +31 -21
  89. package/lib/tools/CLAUDE.md +12 -3
  90. package/lib/tools/assemblyai.js +17 -0
  91. package/lib/tools/create-agent-job.js +12 -8
  92. package/lib/tools/docker.js +34 -10
  93. package/lib/tools/github.js +34 -0
  94. package/lib/tools/telegram.js +106 -0
  95. package/lib/utils/render-md.js +44 -18
  96. package/package.json +8 -8
  97. package/setup/CLAUDE.md +11 -5
  98. package/setup/lib/providers.mjs +2 -1
  99. package/setup/lib/targets.mjs +13 -16
  100. package/setup/lib/telegram.mjs +8 -69
  101. package/templates/.env.example +0 -7
  102. package/templates/.github/workflows/rebuild-event-handler.yml +1 -1
  103. package/templates/.gitignore.template +1 -3
  104. package/templates/CLAUDE.md +1 -1
  105. package/templates/CLAUDE.md.template +29 -7
  106. package/templates/agent-job/CLAUDE.md.template +5 -3
  107. package/templates/agent-job/CRONS.json +16 -0
  108. package/templates/agent-job/SYSTEM.md +16 -11
  109. package/templates/agents/CLAUDE.md.template +17 -17
  110. package/templates/coding-workspace/CLAUDE.md.template +7 -0
  111. package/templates/data/CLAUDE.md.template +1 -1
  112. package/templates/docker-compose.custom.yml +1 -0
  113. package/templates/docker-compose.yml +1 -0
  114. package/templates/event-handler/CLAUDE.md.template +79 -0
  115. package/templates/event-handler/TRIGGERS.json +18 -2
  116. package/templates/skills/CLAUDE.md.template +20 -22
  117. package/templates/skills/{library/agent-job-secrets → agent-job-secrets}/SKILL.md +2 -2
  118. package/lib/ai/agent.js +0 -65
  119. package/lib/ai/async-channel.js +0 -51
  120. package/lib/ai/model.js +0 -130
  121. package/lib/ai/tools.js +0 -164
  122. package/lib/tools/openai.js +0 -37
  123. package/setup/lib/telegram-verify.mjs +0 -63
  124. package/setup/setup-telegram.mjs +0 -260
  125. package/templates/agent-job/SOUL.md +0 -17
  126. /package/templates/{skills/active/.gitkeep → coding-workspace/SYSTEM.md} +0 -0
  127. /package/templates/skills/{library/agent-job-secrets → agent-job-secrets}/agent-job-secrets.js +0 -0
  128. /package/templates/skills/{library/playwright-cli → playwright-cli}/SKILL.md +0 -0
@@ -1,72 +1,11 @@
1
- import { randomBytes } from 'crypto';
2
-
3
- /**
4
- * Generate a verification code for Telegram chat ID capture
5
- */
6
- export function generateVerificationCode() {
7
- return 'verify-' + randomBytes(4).toString('hex');
8
- }
9
-
10
- /**
11
- * Register a Telegram webhook
12
- */
13
- export async function setTelegramWebhook(botToken, webhookUrl, secretToken = null) {
14
- // Delete first — Telegram ignores secret_token changes if the URL is unchanged
15
- await deleteTelegramWebhook(botToken);
16
-
17
- const body = { url: webhookUrl };
18
- if (secretToken) {
19
- body.secret_token = secretToken;
20
- }
21
-
22
- const response = await fetch(
23
- `https://api.telegram.org/bot${botToken}/setWebhook`,
24
- {
25
- method: 'POST',
26
- headers: { 'Content-Type': 'application/json' },
27
- body: JSON.stringify(body),
28
- }
29
- );
30
-
31
- const result = await response.json();
32
- return result;
33
- }
34
-
35
- /**
36
- * Get current webhook info
37
- */
38
- export async function getTelegramWebhookInfo(botToken) {
39
- const response = await fetch(`https://api.telegram.org/bot${botToken}/getWebhookInfo`);
40
- const result = await response.json();
41
- return result;
42
- }
43
-
44
- /**
45
- * Delete existing webhook
46
- */
47
- export async function deleteTelegramWebhook(botToken) {
48
- const response = await fetch(`https://api.telegram.org/bot${botToken}/deleteWebhook`, {
49
- method: 'POST',
50
- });
51
- const result = await response.json();
52
- return result;
53
- }
54
-
55
- /**
56
- * Validate bot token by calling getMe
57
- */
58
- export async function validateBotToken(botToken) {
59
- try {
60
- const response = await fetch(`https://api.telegram.org/bot${botToken}/getMe`);
61
- const result = await response.json();
62
- if (result.ok) {
63
- return { valid: true, botInfo: result.result };
64
- }
65
- return { valid: false, error: result.description };
66
- } catch (error) {
67
- return { valid: false, error: error.message };
68
- }
69
- }
1
+ // Re-export Telegram API helpers from the package (single source of truth).
2
+ // The CLI setup wizard shares these helpers with the admin UI server actions.
3
+ export {
4
+ validateBotToken,
5
+ setTelegramWebhook,
6
+ getTelegramWebhookInfo,
7
+ deleteTelegramWebhook,
8
+ } from '../../lib/tools/telegram.js';
70
9
 
71
10
  /**
72
11
  * Get BotFather URL for creating a new bot
@@ -29,9 +29,6 @@ TELEGRAM_BOT_TOKEN=
29
29
  # Secret for validating Telegram webhooks (generate with: openssl rand -hex 32)
30
30
  TELEGRAM_WEBHOOK_SECRET=
31
31
 
32
- # Verification code for getting your chat ID (e.g., verify-abc12345)
33
- TELEGRAM_VERIFICATION=
34
-
35
32
  # Secret for GitHub Actions webhook auth (must match GH_WEBHOOK_SECRET secret)
36
33
  GH_WEBHOOK_SECRET=
37
34
 
@@ -50,10 +47,6 @@ ASSEMBLYAI_API_KEY=
50
47
  # LLM model name override (optional, provider-specific default if unset)
51
48
  # LLM_MODEL=
52
49
 
53
- # Default Telegram chat ID for scheduled notifications
54
- # Get this by messaging your bot and checking the webhook logs, or use @userinfobot
55
- TELEGRAM_CHAT_ID=
56
-
57
50
  # Let's Encrypt email for automatic SSL (docker-compose only, optional)
58
51
  # If not set, Traefik uses a self-signed certificate
59
52
  # LETSENCRYPT_EMAIL=
@@ -71,7 +71,7 @@ jobs:
71
71
  - name: Reload (no version change)
72
72
  if: steps.pull.outputs.status == 'RELOAD'
73
73
  run: |
74
- docker exec thepopebot-event-handler npx pm2 reload all
74
+ docker exec thepopebot-event-handler gosu coding-agent pm2 reload all
75
75
 
76
76
  - name: Pull new image and restart container
77
77
  if: steps.pull.outputs.status == 'VERSION_CHANGED'
@@ -11,11 +11,9 @@
11
11
  # Playwright MCP
12
12
  .playwright-mcp/
13
13
 
14
- # Pi system prompt (generated at runtime from SOUL.md)
14
+ # Pi system prompt (generated at runtime)
15
15
  .pi/SYSTEM.md
16
16
 
17
- # Dynamically activated skills (created at container runtime, not user config)
18
- skills/active/agent-job-secrets
19
17
 
20
18
  # Database
21
19
  /data/
@@ -11,7 +11,7 @@ This directory contains files that get copied into user projects when they run `
11
11
 
12
12
  ## What belongs here
13
13
 
14
- - **Agent job config**: `agent-job/SOUL.md`, `agent-job/CRONS.json`, etc.
14
+ - **Agent job config**: `agent-job/SYSTEM.md`, `agent-job/CRONS.json`, etc.
15
15
  - **Event handler config**: `event-handler/agent-chat/SYSTEM.md`, `event-handler/TRIGGERS.json`, etc.
16
16
  - **GitHub Actions workflows**: `.github/workflows/`
17
17
  - **Docker compose**: `docker-compose.yml`
@@ -4,10 +4,11 @@ This is a [thepopebot](https://github.com/stephengpope/thepopebot) project.
4
4
 
5
5
  ## Directories
6
6
 
7
- - **`agent-job/`** — Agent job configuration: system prompts (`SOUL.md`, `SYSTEM.md`), heartbeat prompt, and cron schedules (`CRONS.json`).
7
+ - **`agent-job/`** — Agent job configuration: system prompt (`SYSTEM.md`), heartbeat prompt, and cron schedules (`CRONS.json`).
8
+ - **`coding-workspace/`** — Optional system prompt (`SYSTEM.md`) for code mode workspaces. Empty by default.
8
9
  - **`agents/`** — Custom agent definitions. Each subdirectory defines an agent (see Managing Agents below).
9
10
  - **`event-handler/`** — Event handler configuration: chat system prompts, trigger definitions (`TRIGGERS.json`), cluster templates, and LiteLLM proxy config.
10
- - **`skills/library/`** — Skill plugins. Activate by symlinking into `skills/active/`.
11
+ - **`skills/`** — Skill plugins. Each subdirectory with a `SKILL.md` is an active skill.
11
12
  - **`data/`** — Runtime data (SQLite database, cluster state). Not checked into git.
12
13
  - **`logs/`** — Agent job logs, organized by job ID. Not checked into git.
13
14
 
@@ -19,16 +20,37 @@ This is a [thepopebot](https://github.com/stephengpope/thepopebot) project.
19
20
 
20
21
  ## Managed Files
21
22
 
22
- Some files are auto-synced by `npx thepopebot init` and will be overwritten on upgrade. Do not edit these:
23
+ Some files are auto-synced by `npx thepopebot init` and will be overwritten on every init/upgrade. Do not edit these:
23
24
 
24
25
  - `.github/workflows/` — CI/CD workflows
25
26
  - `docker-compose.yml`
26
27
  - `.dockerignore`
27
28
  - `.gitignore`
28
- - `agent-job/CLAUDE.md`
29
- - `agents/CLAUDE.md`
30
- - `event-handler/CLAUDE.md`
31
- - `skills/CLAUDE.md`
29
+
30
+ The `CLAUDE.md` files scattered through the project tree (e.g. `agent-job/CLAUDE.md`, `agents/CLAUDE.md`, `event-handler/CLAUDE.md`, `skills/CLAUDE.md`) are scaffolded by `init` from `*.template` sources but are **not** in the managed-paths list — they will not be overwritten if you have edited them. Run `npx thepopebot reset <path>` to restore one to its template default, or `npx thepopebot diff <path>` to see your local changes.
31
+
32
+ ## Agent Scoping
33
+
34
+ Agents can be scoped to subdirectories within the repository. When a chat is launched with a scope (e.g., `agents/gary-vee`), the coding agent runs with that directory as its working directory.
35
+
36
+ ### Directory Structure
37
+
38
+ ```
39
+ agents/
40
+ gary-vee/
41
+ CLAUDE.md ← agent-specific context (optional)
42
+ SYSTEM.md ← agent-specific system prompt (optional)
43
+ skills/ ← agent-specific skills (optional, overrides root skills/)
44
+ agent-job-secrets → ../../../skills/agent-job-secrets (symlink)
45
+ custom-skill/
46
+ ```
47
+
48
+ ### How Scoping Works
49
+
50
+ - **Working directory** — The agent's cwd is set to the scoped directory. It still has access to the full repo.
51
+ - **Skills** — If the scoped directory has a `skills/` folder, those skills are used. If not, the root `skills/` folder is used as a fallback. Sub-agent skills can symlink back to root skills they need.
52
+ - **CLAUDE.md** — The coding agent automatically picks up `.claude/` and `CLAUDE.md` files relative to its working directory.
53
+ - **Default scope** — When no scope is selected, the agent runs from the repository root with root-level skills.
32
54
 
33
55
  ## Agents
34
56
 
@@ -4,8 +4,7 @@ This directory contains your agent job configuration files — system prompts, s
4
4
 
5
5
  ## Files
6
6
 
7
- - **`SOUL.md`** — Agent personality, identity, and values. Included in every agent job system prompt.
8
- - **`SYSTEM.md`** — Runtime environment documentation injected into the agent's context.
7
+ - **`SYSTEM.md`** — Agent system prompt: identity, runtime environment, and instructions. Rendered with full template support (`{{skills}}`, `{{datetime}}`, file includes).
9
8
  - **`HEARTBEAT.md`** — Prompt for the agent's periodic heartbeat cron job.
10
9
  - **`CRONS.json`** — Scheduled job definitions, loaded at server startup.
11
10
 
@@ -27,7 +26,10 @@ There are three action types:
27
26
  }
28
27
  ```
29
28
 
30
- Optional: add `"llm_provider"` and `"llm_model"` to override the default LLM for that job.
29
+ Optional fields:
30
+ - `"scope"` (e.g. `"agents/my-agent"`) — routes the cron to a scoped agent. Its `SYSTEM.md`, skills directory, and working directory all switch to that subdirectory. See `agents/CLAUDE.md` for the full pattern.
31
+ - `"agent_backend"` (e.g. `"claude-code"`, `"codex-cli"`, `"gemini-cli"`, `"pi"`, `"opencode"`, `"kimi-cli"`) — pick which coding agent runs the job, overriding the default set in Admin > Event Handler > Coding Agents.
32
+ - `"llm_model"` — override the model used within the selected coding agent (provider is implicit in the agent).
31
33
 
32
34
  **`command`** — Runs a shell command on the event handler (working directory: project root).
33
35
 
@@ -12,5 +12,21 @@
12
12
  "type": "command",
13
13
  "command": "echo \"pong!\"",
14
14
  "enabled": true
15
+ },
16
+ {
17
+ "name": "scoped-agent-example",
18
+ "schedule": "0 9 * * *",
19
+ "type": "agent",
20
+ "job": "Read jobs/daily-check.md and complete it.",
21
+ "scope": "agents/my-agent",
22
+ "enabled": false
23
+ },
24
+ {
25
+ "name": "agent-backend-override-example",
26
+ "schedule": "0 10 * * *",
27
+ "type": "agent",
28
+ "job": "Summarize open pull requests.",
29
+ "agent_backend": "codex-cli",
30
+ "enabled": false
15
31
  }
16
32
  ]
@@ -1,31 +1,29 @@
1
1
  # Agent Job Environment
2
2
 
3
- You are an autonomous AI agent running inside a Docker container on thepopebot.
3
+ You are an autonomous AI agent running inside a Docker container on thepopebot. You approach tasks methodically — plan before acting, favor simplicity, and prioritize quality over speed.
4
4
 
5
5
  ## Runtime Environment
6
6
 
7
7
  Your workspace is `/home/coding-agent/workspace` — a live git repository.
8
8
 
9
9
  ## Temporary Files
10
- Use `/home/coding-agent/workspace/.tmp/` for working files — downloads, screenshots, intermediate data, scripts, generated files. `/home/coding-agent/workspace/.tmp/` is gitignored and nothing there gets committed. If a tool downloads a file, save it to `/home/coding-agent/workspace/.tmp/` and reference it directly.
10
+ Use `/tmp` for working files — downloads, screenshots, intermediate data, scripts, generated files. If a tool downloads a file, save it to `/tmp` and reference it directly.
11
11
 
12
- **DO NOT USE** `/tmp` because that will leak and waste disk space from writing extra layers to the container.
13
-
14
- Everything in the workspace is automatically committed and pushed when your job finishes. You do not control this. Be intentional about what you put here — **any file you create, move, or download into the workspace WILL be committed.**
12
+ Everything in the workspace `/home/coding-agent/workspace` is automatically committed and pushed when your job finishes. You do not control this. Be intentional about what you put here — **any file you create, move, or download into the workspace WILL be committed.**
15
13
 
16
14
  ## Directory Layout
17
15
 
18
16
  - `agents/` — Agent definitions. Each subdirectory defines an agent with its own prompts.
19
- - `agent-job/` — Runtime config: system prompts (`SOUL.md`, `SYSTEM.md`), cron schedules (`CRONS.json`), heartbeat prompt.
17
+ - `agent-job/` — Runtime config: system prompt (`SYSTEM.md`), cron schedules (`CRONS.json`), heartbeat prompt.
20
18
  - `event-handler/` — Event handler config. Do not edit — managed by the event handler.
21
- - `skills/library/` — Skill plugins. Active skills are symlinked into `skills/active/`.
19
+ - `skills/` — Skill plugins. Each subdirectory with a `SKILL.md` is an active skill.
22
20
  - `data/`, `logs/` — Runtime data and job logs.
23
21
 
24
22
  ## What You Can Edit
25
23
 
26
24
  - `agent-job/CRONS.json` — Add, remove, or change scheduled jobs
27
25
  - `agents/` — Create or remove agent definitions
28
- - `skills/active/` — Activate or deactivate skills via symlinks
26
+ - `skills/` — Add or remove skill directories
29
27
  - Agent prompt files (`.md`) in `agent-job/` and `agents/`
30
28
  - Reports and output files
31
29
 
@@ -35,17 +33,24 @@ Everything in the workspace is automatically committed and pushed when your job
35
33
  - `docker-compose.yml`, `.dockerignore`, `.gitignore` — Managed infrastructure files
36
34
  - `.env` — Environment secrets
37
35
 
36
+ ## Agent Scoping
37
+
38
+ Agents can be scoped to subdirectories under `agents/`. When scoped, the agent's working directory is set to that subdirectory (e.g., `agents/gary-vee/`). The full repo is still accessible.
39
+
40
+ - **Skills fallback** — If the scoped directory has a `skills/` folder, those are used. Otherwise, the root `skills/` folder applies. Sub-agents can symlink individual skills from root: `skills/agent-job-secrets → ../../../skills/agent-job-secrets`.
41
+ - **No skills folder needed** — If you don't create a `skills/` directory in the agent scope, it inherits all root skills automatically.
42
+
38
43
  ## Self-Modification
39
44
 
40
- **Add an agent** — Create `agents/<name>/` with a `jobs/` subfolder, add a cron entry in `agent-job/CRONS.json` pointing to the prompt file, update `agents/CLAUDE.md` to document it, update root `CLAUDE.md` to reflect the new agent.
45
+ **Add an agent** — Create `agents/<name>/` with an optional `CLAUDE.md`, `SYSTEM.md`, and `skills/` directory. Add a cron entry in `agent-job/CRONS.json` if it runs on a schedule. Update `agents/CLAUDE.md` and root `CLAUDE.md`.
41
46
 
42
47
  **Remove an agent** — Delete the `agents/<name>/` folder, remove its cron entries, update `agents/CLAUDE.md` and root `CLAUDE.md`.
43
48
 
44
49
  **Change a schedule** — Edit `agent-job/CRONS.json` (cron expressions, enable/disable).
45
50
 
46
- **Activate a skill** — Symlink from `skills/library/<name>/` into `skills/active/`, update root `CLAUDE.md`.
51
+ **Add a skill** — Create a directory in `skills/` with a `SKILL.md`, update root `CLAUDE.md`.
47
52
 
48
- **Deactivate a skill** — Remove the symlink from `skills/active/`, update root `CLAUDE.md`.
53
+ **Remove a skill** — Delete the directory from `skills/`, update root `CLAUDE.md`.
49
54
 
50
55
  **Keep CLAUDE.md files current** — When you change the structure of the instance (add/remove agents, change schedules, activate skills), update the root `CLAUDE.md` and any affected folder-level `CLAUDE.md` files so the next agent has an accurate picture.
51
56
 
@@ -2,15 +2,22 @@
2
2
 
3
3
  ## Adding an Agent
4
4
 
5
- Each subdirectory defines an agent. Create a folder with a `SYSTEM.md` file:
5
+ Each subdirectory defines an agent. At minimum create a folder with a `SYSTEM.md` file:
6
6
 
7
7
  ```
8
8
  agents/
9
9
  └── my-agent/
10
- └── SYSTEM.md # System prompt — identity, instructions, constraints
10
+ ├── SYSTEM.md # System prompt — identity, instructions, constraints (required)
11
+ ├── CLAUDE.md # Optional — guidance for AI assistants editing this agent's files
12
+ ├── skills/ # Optional — agent-specific skills (overrides root skills/ for this scope)
13
+ └── jobs/ # Optional — reusable task prompts referenced from CRONS.json
11
14
  ```
12
15
 
13
- `SYSTEM.md` is the agent's system prompt. Write it in markdown addressed to the agent (e.g. "You are a code reviewer...").
16
+ `SYSTEM.md` is the agent's system prompt. Write it in markdown addressed to the agent (e.g. "You are a code reviewer..."). `CLAUDE.md` (if present) is read by AI assistants working in this directory — use it for non-obvious context only.
17
+
18
+ **Skills resolution**: when a job runs with `scope: "agents/my-agent"`, the runtime checks `agents/my-agent/skills/` first; missing skills fall back to root `skills/`. To override a built-in skill for one agent, drop a same-named SKILL.md under that agent's `skills/`.
19
+
20
+ > **Important:** `agents/<name>/SYSTEM.md` **replaces** `agent-job/SYSTEM.md` when the agent is scoped — it doesn't extend it. Use `agent-job/SYSTEM.md` as a starting template and adapt it: keep the runtime environment notes, the `/tmp` scratch directive, and add the `{{skills}}` token if you want skill descriptions injected. Then add the agent's identity-specific instructions on top.
14
21
 
15
22
  For agents with multiple complex tasks, add a `jobs/` subfolder:
16
23
 
@@ -25,29 +32,22 @@ agents/
25
32
 
26
33
  ## Scheduling
27
34
 
28
- Add a cron entry in `agent-job/CRONS.json`:
35
+ Add a cron entry in `agent-job/CRONS.json` with a `scope` field pointing at the agent:
29
36
 
30
37
  ```json
31
38
  {
32
- "name": "my-agent-daily",
33
- "schedule": "0 9 * * *",
39
+ "name": "my-agent-weekly-report",
40
+ "schedule": "0 9 * * 1",
34
41
  "type": "agent",
35
- "job": "Read agents/my-agent/SYSTEM.md and follow the instructions there.",
42
+ "scope": "agents/my-agent",
43
+ "job": "Follow the instructions in jobs/weekly-report.md",
36
44
  "enabled": true
37
45
  }
38
46
  ```
39
47
 
40
- For job-specific prompts, chain the reads:
48
+ `scope` activates the agent's identity (`SYSTEM.md`), skills, and working directory — the cron runs as the scoped agent, not from the repo root. `job` is the task prompt the agent receives.
41
49
 
42
- ```json
43
- {
44
- "name": "my-agent-report",
45
- "schedule": "0 9 * * 1",
46
- "type": "agent",
47
- "job": "Read agents/my-agent/SYSTEM.md for context, then read agents/my-agent/prompts/weekly-report.md and complete that task.",
48
- "enabled": true
49
- }
50
- ```
50
+ For reusable tasks, write the prompt as markdown in `agents/<name>/jobs/<task>.md` and reference it from `job` — the agent's working directory is the scoped folder, so the relative path resolves. For one-off tasks, write the prompt inline.
51
51
 
52
52
  ## Removing an Agent
53
53
 
@@ -0,0 +1,7 @@
1
+ # coding-workspace/ — Code Mode System Prompt
2
+
3
+ Optional system prompt for code mode workspaces. Edit `SYSTEM.md` to customize the coding agent's behavior when working on your repos.
4
+
5
+ ## Files
6
+
7
+ - **`SYSTEM.md`** — System prompt for code mode. Empty by default — the coding agent uses its built-in prompt. Add content here to append custom instructions. Supports `{{skills}}`, `{{datetime}}`, and `{{ file.md }}` includes.
@@ -1,5 +1,5 @@
1
1
  # Data Directory
2
2
 
3
- Runtime data including the SQLite database (`thepopebot.sqlite`) and cluster state. Created automatically on server start.
3
+ Runtime data including the SQLite database (`db/thepopebot.sqlite`) and cluster state. Created automatically on server start. Override the DB path with `DATABASE_PATH` in `.env`.
4
4
 
5
5
  Not checked into git.
@@ -46,6 +46,7 @@ services:
46
46
  volumes:
47
47
  - .:/project
48
48
  - ./agent-job:/app/agent-job
49
+ - ./agents:/app/agents
49
50
  - ./event-handler:/app/event-handler
50
51
  - ./skills:/app/skills
51
52
  - ./.env:/app/.env
@@ -19,6 +19,7 @@ services:
19
19
  volumes:
20
20
  - .:/project
21
21
  - ./agent-job:/app/agent-job
22
+ - ./agents:/app/agents
22
23
  - ./event-handler:/app/event-handler
23
24
  - ./skills:/app/skills
24
25
  - ./.env:/app/.env
@@ -0,0 +1,79 @@
1
+ # event-handler/ — Event Handler Configuration
2
+
3
+ This directory holds configuration for the event handler: webhook triggers, chat system prompts, cluster role definitions, LiteLLM proxy routing, and the job-summary prompt. Edit these to shape how your handler reacts to events.
4
+
5
+ ## Files
6
+
7
+ | File | Purpose |
8
+ |------|---------|
9
+ | `TRIGGERS.json` | Webhook trigger definitions — fires actions when matching paths receive HTTP requests |
10
+ | `agent-chat/SYSTEM.md` | System prompt for the chat agent (default chat mode) |
11
+ | `code-chat/SYSTEM.md` | System prompt for code mode chat (workspace-aware) |
12
+ | `clusters/SYSTEM.md` | System prompt prepended to every cluster worker |
13
+ | `clusters/ROLE.md` | Role-template snippet referenced by cluster role definitions |
14
+ | `litellm/main.yaml` | LiteLLM proxy config — routes Claude Code through other providers |
15
+ | `SUMMARY.md` | System prompt for the auto-summary that runs after agent jobs complete |
16
+
17
+ ## TRIGGERS.json
18
+
19
+ JSON array of webhook trigger definitions. Loaded at server boot by `lib/triggers.js`.
20
+
21
+ ```json
22
+ {
23
+ "name": "review-github-event",
24
+ "watch_path": "/github/webhook",
25
+ "actions": [
26
+ { "type": "agent", "job": "Summarize this GitHub event:\n{{body}}" }
27
+ ],
28
+ "enabled": true
29
+ }
30
+ ```
31
+
32
+ | Field | Required | Notes |
33
+ |-------|----------|-------|
34
+ | `name` | Yes | Unique within the file |
35
+ | `watch_path` | Yes | Path to match (`/github/webhook`, `/webhook`, custom paths) |
36
+ | `actions` | Yes | Array — runs in order, fire-and-forget after auth |
37
+ | `enabled` | No | Defaults `true`. Set `false` to keep the entry but skip it |
38
+
39
+ ### Action types
40
+
41
+ Three types — `agent`, `command`, `webhook`. `agent` accepts optional `scope`, `agent_backend`, `llm_model` overrides:
42
+
43
+ ```json
44
+ { "type": "agent", "job": "Process: {{body}}", "scope": "agents/triage", "agent_backend": "claude-code", "llm_model": "claude-sonnet-4-5-20250929" }
45
+ { "type": "command", "command": "echo 'webhook received: {{body}}' >> logs/webhook.log" }
46
+ { "type": "webhook", "url": "https://example.com/hook", "method": "POST", "headers": {}, "vars": { "source": "github" } }
47
+ ```
48
+
49
+ `scope` resolves to a directory under `agents/` (see `agents/CLAUDE.md`). The agent runs with that directory as its working dir, picks up its `SYSTEM.md`, and uses the skills under `agents/<scope>/skills/` falling back to root `skills/`.
50
+
51
+ ### Template tokens (in `job` and `command` strings)
52
+
53
+ `{{body}}`, `{{body.field}}`, `{{query}}`, `{{query.field}}`, `{{headers}}`, `{{headers.field}}`. Tokens are expanded when the trigger fires.
54
+
55
+ ## Chat System Prompts
56
+
57
+ `agent-chat/SYSTEM.md` and `code-chat/SYSTEM.md` are the system prompts injected into chat sessions. They support `{{include path/to/file.md}}`, `{{datetime}}`, and `{{skills}}` variables (resolved by `lib/utils/render-md.js`).
58
+
59
+ - **Agent chat** (`agent-chat/`) — default chat mode. Workspace-agnostic.
60
+ - **Code chat** (`code-chat/`) — code-mode chat. Knows about the active code workspace, repo, branch, and feature branch.
61
+
62
+ Both can be scoped: a chat tied to a workspace with `scope: "agents/foo"` will load `agents/foo/SYSTEM.md` instead of these defaults.
63
+
64
+ ## Cluster Configuration
65
+
66
+ `clusters/SYSTEM.md` is prepended to every cluster worker's system prompt. `clusters/ROLE.md` is a reusable role-template snippet that individual cluster role definitions can reference. Cluster behavior is configured in the Admin UI; these files supply the prompt context.
67
+
68
+ ## LiteLLM Proxy
69
+
70
+ `litellm/main.yaml` is read by the optional LiteLLM sidecar (`docker-compose.litellm.yml`). It routes Claude Code's Anthropic-protocol calls to other providers (OpenAI, Gemini, custom OpenAI-compatible endpoints). Edit when you want to use Claude Code with a non-Anthropic backend. Refer to [LiteLLM docs](https://docs.litellm.ai/) for the schema.
71
+
72
+ ## Summary Prompt
73
+
74
+ `SUMMARY.md` is the prompt for the helper LLM call that auto-summarizes agent job results (PR link, status, files changed). Tweak its tone or formatting here.
75
+
76
+ ## Notes
77
+
78
+ - These files are user-owned — edits are preserved across `thepopebot upgrade`.
79
+ - The Admin UI (`/admin/event-handler/`) configures runtime defaults (LLM provider, coding agent backend, OAuth tokens). Trigger-level `agent_backend` / `llm_model` overrides those defaults.
@@ -48,10 +48,26 @@
48
48
  "enabled": false
49
49
  },
50
50
  {
51
- "name": "review-with-openai",
51
+ "name": "review-with-model-override",
52
52
  "watch_path": "/github/webhook",
53
53
  "actions": [
54
- { "type": "agent", "job": "Review the GitHub event and summarize what happened:\n{{body}}", "llm_provider": "openai", "llm_model": "gpt-4o" }
54
+ { "type": "agent", "job": "Review the GitHub event and summarize what happened:\n{{body}}", "llm_model": "claude-opus-4-7" }
55
+ ],
56
+ "enabled": false
57
+ },
58
+ {
59
+ "name": "review-with-codex",
60
+ "watch_path": "/github/webhook",
61
+ "actions": [
62
+ { "type": "agent", "job": "Review the GitHub event and summarize what happened:\n{{body}}", "agent_backend": "codex-cli" }
63
+ ],
64
+ "enabled": false
65
+ },
66
+ {
67
+ "name": "scoped-webhook-agent",
68
+ "watch_path": "/webhook",
69
+ "actions": [
70
+ { "type": "agent", "job": "A webhook was received. Read jobs/handle-webhook.md and complete it using the payload:\n{{body}}", "scope": "agents/my-agent" }
55
71
  ],
56
72
  "enabled": false
57
73
  }
@@ -1,14 +1,14 @@
1
1
  # skills/ — Agent Skills
2
2
 
3
- Skills are lightweight plugins that extend agent abilities. Each skill lives in `skills/library/<skill-name>/` and is activated by symlinking into `skills/active/`.
3
+ Skills are lightweight plugins that extend agent abilities. Each skill lives in `skills/<skill-name>/`.
4
4
 
5
5
  ## How Skills Work
6
6
 
7
- 1. **Discovery** — The system scans `skills/active/` for directories containing `SKILL.md`.
7
+ 1. **Discovery** — The system scans `skills/` for directories containing `SKILL.md`.
8
8
  2. **Frontmatter loaded** — The `description` from YAML frontmatter is included in the system prompt under "Active skills" (via the `{{skills}}` template variable).
9
9
  3. **Full SKILL.md read on demand** — When the agent decides to use a skill, it reads the full `SKILL.md` for detailed usage instructions.
10
10
 
11
- Both Pi and Claude Code discover skills from the same `skills/active/` directory (via `.pi/skills` and `.claude/skills` symlink bridges).
11
+ All coding agents discover skills from the same `skills/` directory (via `.pi/skills`, `.claude/skills`, etc. symlink bridges).
12
12
 
13
13
  ## Conventions
14
14
 
@@ -48,12 +48,12 @@ description: One sentence describing what the skill does and when to use it.
48
48
  ## Usage
49
49
 
50
50
  ```bash
51
- skills/library/skill-name/script.sh <args>
51
+ skills/skill-name/script.sh <args>
52
52
  ```
53
53
  ```
54
54
 
55
55
  - The `description` field appears in the system prompt — keep it concise and action-oriented.
56
- - Use project-root-relative paths in documentation (e.g., `skills/library/skill-name/script.sh`).
56
+ - Use project-root-relative paths in documentation (e.g., `skills/skill-name/script.sh`).
57
57
 
58
58
  ### Skill Structure
59
59
 
@@ -67,27 +67,26 @@ If a skill needs an API key, add it via the admin UI (Settings > Agent Jobs > Se
67
67
 
68
68
  ### Activation & Deactivation
69
69
 
70
- ```bash
71
- # Activate
72
- ln -s ../library/skill-name skills/active/skill-name
70
+ Skills are active when present in the `skills/` directory. To deactivate, remove or move the skill directory out.
73
71
 
74
- # Deactivate
75
- rm skills/active/skill-name
76
- ```
72
+ All coding agents discover skills from the same `skills/` directory via symlink bridges created by `npx thepopebot init`:
77
73
 
78
- The `skills/active/` directory is shared by both agent backends via symlink bridges:
79
- - `.claude/skills → skills/active`
80
- - `.pi/skills → skills/active`
74
+ - `.claude/skills ../skills` (Claude Code)
75
+ - `.pi/skills → ../skills` (Pi)
76
+ - `.codex/skills → ../skills` (Codex CLI)
77
+ - `.gemini/skills → ../skills` (Gemini CLI)
78
+ - `.kimi/skills → ../skills` (Kimi CLI)
79
+ - `.agents/skills → ../skills` (OpenCode and other plugin-style agents)
81
80
 
82
81
  ## Creating a Skill
83
82
 
84
83
  ### Simple bash skill (most common)
85
84
 
86
85
  ```bash
87
- mkdir skills/library/my-skill
86
+ mkdir skills/my-skill
88
87
  ```
89
88
 
90
- **skills/library/my-skill/SKILL.md:**
89
+ **skills/my-skill/SKILL.md:**
91
90
  ```markdown
92
91
  ---
93
92
  name: my-skill
@@ -101,11 +100,11 @@ Requires MY_API_KEY environment variable.
101
100
 
102
101
  ## Usage
103
102
  ```bash
104
- skills/library/my-skill/run.sh <args>
103
+ skills/my-skill/run.sh <args>
105
104
  ```
106
105
  ```
107
106
 
108
- **skills/library/my-skill/run.sh:**
107
+ **skills/my-skill/run.sh:**
109
108
  ```bash
110
109
  #!/bin/bash
111
110
  set -euo pipefail
@@ -115,10 +114,9 @@ if [ -z "$MY_API_KEY" ]; then echo "Error: MY_API_KEY not set"; exit 1; fi
115
114
  # ... skill logic
116
115
  ```
117
116
 
118
- Then make it executable and activate:
117
+ Then make it executable:
119
118
  ```bash
120
- chmod +x skills/library/my-skill/run.sh
121
- ln -s ../library/my-skill skills/active/my-skill
119
+ chmod +x skills/my-skill/run.sh
122
120
  ```
123
121
 
124
122
  ### Node.js skill
@@ -131,4 +129,4 @@ Always build AND test a skill in the same job. Tell the agent to test with real
131
129
 
132
130
  ## Default Skills
133
131
 
134
- Check `skills/library/` for available built-in skills. Activate any you need by symlinking into `skills/active/`.
132
+ Check `skills/` for available built-in skills (e.g., `agent-job-secrets`, `playwright-cli`).
@@ -7,10 +7,10 @@ description: List and retrieve agent secrets. Plain secrets are also available a
7
7
 
8
8
  ```bash
9
9
  # List available secret keys (fetches current list from server)
10
- node skills/library/agent-job-secrets/agent-job-secrets.js
10
+ node skills/agent-job-secrets/agent-job-secrets.js
11
11
 
12
12
  # Get a secret value (OAuth credentials are auto-refreshed)
13
- node skills/library/agent-job-secrets/agent-job-secrets.js get MY_CREDENTIALS
13
+ node skills/agent-job-secrets/agent-job-secrets.js get MY_CREDENTIALS
14
14
  ```
15
15
 
16
16
  ## Notes