prodboard 0.0.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # prodboard
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1aa4d25: Add `prodboard install` and `prodboard uninstall` commands to manage a user-level systemd service for the daemon
8
+
9
+ ## 0.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - dc917e9: Initial release of prodboard — a self-hosted, CLI-first issue tracker and cron scheduler for AI coding agents.
14
+
15
+ Features:
16
+
17
+ - Full CLI for issue tracking (add, ls, show, edit, mv, rm, comment)
18
+ - MCP server with 14 tools for AI agent integration
19
+ - Cron-based scheduler daemon for automated agent runs
20
+ - SQLite-backed persistent storage
21
+ - Configurable via JSONC config file
22
+ - Template engine for schedule prompts with board context injection
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 prodboard contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,302 @@
1
+ # prodboard
2
+
3
+ Give Claude Code a persistent task board and a cron scheduler so it can manage work across sessions.
4
+
5
+ **The problem:** Claude Code loses context between sessions. It can't remember what tasks exist, what's in progress, or what to work on next. There's no way to schedule it to run recurring jobs like daily triage or nightly CI.
6
+
7
+ **The solution:** prodboard is a local issue tracker backed by SQLite that Claude Code can read and write through MCP tools. It also includes a cron daemon that spawns Claude Code on a schedule to work through tasks autonomously.
8
+
9
+ ```
10
+ You (CLI) ──┐
11
+ ├──▶ SQLite DB ◀── MCP Server ◀── Claude Code
12
+ Cron Daemon ──┘
13
+ ```
14
+
15
+ ## What You Get
16
+
17
+ - **An issue board Claude Code can use** — Claude reads, creates, updates, and completes issues via MCP tools during any session
18
+ - **Scheduled Claude Code runs** — Define cron jobs that spawn Claude Code to triage issues, run maintenance, or work through the backlog
19
+ - **A CLI you can use too** — Same board, human-friendly commands. Add issues, check status, review what Claude did
20
+ - **Everything local** — Single SQLite file at `~/.prodboard/db.sqlite`. No servers, no accounts, no cloud
21
+
22
+ ## Quick Start
23
+
24
+ ```bash
25
+ # Install
26
+ bun install -g prodboard
27
+
28
+ # Initialize
29
+ prodboard init
30
+
31
+ # Connect Claude Code to the board
32
+ claude mcp add prodboard -- bunx prodboard mcp
33
+ ```
34
+
35
+ That's it. Open Claude Code and start talking to it:
36
+
37
+ ## Things You Can Say to Claude Code
38
+
39
+ Once connected, you can manage your board entirely through conversation:
40
+
41
+ ### Setting Up Cron Jobs
42
+
43
+ ```
44
+ "Every hour, tail the nginx access and error logs. If you see
45
+ anything unusual — spikes in 5xx errors, suspicious request
46
+ patterns, or unexpected traffic — create a new issue to investigate"
47
+
48
+ "Every 2 hours, pick up the next todo issue and try to fix it.
49
+ Open a PR with your changes, comment the PR link on the issue,
50
+ and move the issue to review"
51
+
52
+ "Every 2 hours, pick up the next issue in review. Check out the
53
+ PR, verify the code is correct and tests pass. If everything
54
+ looks good, merge it. If not, add a review comment on the PR
55
+ explaining what needs to change and move the issue back to todo"
56
+
57
+ "Create a cron job that runs every 6 hours to check for
58
+ and fix any TypeScript type errors in the project"
59
+
60
+ "Set up a daily schedule at 9 AM on weekdays to review
61
+ the board and work on the highest priority task"
62
+
63
+ "Add a cron job that runs every night at midnight to
64
+ run the test suite and create issues for any failures"
65
+
66
+ "Schedule a weekly cleanup every Friday at 5 PM to
67
+ archive all done issues and summarize what was accomplished"
68
+
69
+ "Create a schedule that runs every 30 minutes to monitor
70
+ the API health endpoint and create an issue if it's down"
71
+ ```
72
+
73
+ ### Managing Tasks
74
+
75
+ ```
76
+ "Add a task to fix the authentication timeout bug in the API"
77
+
78
+ "What's on the board right now?"
79
+
80
+ "Pick up the next task and start working on it"
81
+
82
+ "Mark the login bug as done, I fixed it manually"
83
+
84
+ "Create an issue to refactor the database layer, mark it as todo"
85
+
86
+ "Show me all in-progress issues"
87
+
88
+ "Add a comment to the auth bug — we need to check the session TTL"
89
+ ```
90
+
91
+ ### Reviewing Activity
92
+
93
+ ```
94
+ "Show me what the last cron run did"
95
+
96
+ "What tasks did you complete this week?"
97
+
98
+ "Show the schedule stats for the daily triage job"
99
+ ```
100
+
101
+ Claude Code handles all the MCP tool calls behind the scenes — you just talk to it naturally.
102
+
103
+ ## Adding Tasks from the CLI
104
+
105
+ You can also manage the board directly:
106
+
107
+ ```bash
108
+ prodboard add "Fix login bug" -d "OAuth callback URL is wrong" -s todo
109
+ prodboard add "Add dark mode" -s todo
110
+ prodboard add "Write API tests" -s todo
111
+ prodboard ls
112
+ ```
113
+
114
+ ### Starting the Scheduler
115
+
116
+ ```bash
117
+ # Start the cron daemon (keeps running in foreground)
118
+ prodboard daemon
119
+
120
+ # Or preview what's scheduled without running anything
121
+ prodboard daemon --dry-run
122
+ ```
123
+
124
+ ## CLI Reference
125
+
126
+ ### Issues
127
+
128
+ ```bash
129
+ prodboard add "Fix bug" -d "description" -s todo # Create
130
+ prodboard ls # List (table)
131
+ prodboard ls --status todo --status in-progress # Filter by status
132
+ prodboard ls --search "login" --json # Search + JSON output
133
+ prodboard show <id> # Details + comments
134
+ prodboard edit <id> --title "New title" -s review # Update fields
135
+ prodboard mv <id> done # Change status
136
+ prodboard rm <id> --force # Delete
137
+ ```
138
+
139
+ ### Comments
140
+
141
+ ```bash
142
+ prodboard comment <id> "Looking into this" # Add comment
143
+ prodboard comment <id> "Fixed" --author claude # With author
144
+ prodboard comments <id> # List comments
145
+ ```
146
+
147
+ ### Schedules
148
+
149
+ ```bash
150
+ prodboard schedule add --name "job" --cron "0 9 * * *" --prompt "Do X"
151
+ prodboard schedule ls # List schedules
152
+ prodboard schedule edit <id> --cron "0 10 * * *" # Edit
153
+ prodboard schedule enable <id> # Enable
154
+ prodboard schedule disable <id> # Disable
155
+ prodboard schedule rm <id> --force # Delete
156
+ prodboard schedule run <id> # Run immediately
157
+ prodboard schedule logs # Run history
158
+ prodboard schedule stats --days 7 # Statistics
159
+ ```
160
+
161
+ ### Daemon
162
+
163
+ ```bash
164
+ prodboard daemon # Start (foreground)
165
+ prodboard daemon --dry-run # Preview schedules
166
+ prodboard daemon status # Check if running
167
+ ```
168
+
169
+ ### Other
170
+
171
+ ```bash
172
+ prodboard config # Show configuration
173
+ prodboard version # Show version
174
+ ```
175
+
176
+ IDs support prefix matching — use `a3f9` instead of the full `a3f9b2c1d4e5f678`.
177
+
178
+ ## MCP Tools
179
+
180
+ These are the tools Claude Code sees when connected to the board:
181
+
182
+ | Tool | What Claude Uses It For |
183
+ |------|------------------------|
184
+ | `board_summary` | See issue counts and recent activity |
185
+ | `list_issues` | Browse issues with filters |
186
+ | `get_issue` | Read full issue details and comments |
187
+ | `create_issue` | Log a new task or bug |
188
+ | `update_issue` | Change title, description, or status |
189
+ | `delete_issue` | Remove an issue |
190
+ | `add_comment` | Leave notes on issues (default author: "claude") |
191
+ | `pick_next_issue` | Claim the oldest todo, move to in-progress |
192
+ | `complete_issue` | Mark done with an optional summary comment |
193
+ | `list_schedules` | See scheduled jobs |
194
+ | `create_schedule` | Set up a new cron job |
195
+ | `update_schedule` | Modify a schedule |
196
+ | `delete_schedule` | Remove a schedule |
197
+ | `list_runs` | Check run history and results |
198
+
199
+ MCP resources: `prodboard://issues` (board summary) and `prodboard://schedules` (active schedules).
200
+
201
+ ## Configuration
202
+
203
+ Config file: `~/.prodboard/config.jsonc`
204
+
205
+ ```jsonc
206
+ {
207
+ "general": {
208
+ "statuses": ["todo", "in-progress", "review", "done", "archived"],
209
+ "defaultStatus": "todo",
210
+ "idPrefix": ""
211
+ },
212
+ "daemon": {
213
+ "maxConcurrentRuns": 2,
214
+ "maxTurns": 50,
215
+ "hardMaxTurns": 200,
216
+ "runTimeoutSeconds": 1800,
217
+ "runRetentionDays": 30,
218
+ "logLevel": "info",
219
+ "useWorktrees": "auto"
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## Scheduler Details
225
+
226
+ ### Cron Syntax
227
+
228
+ Standard 5-field cron:
229
+
230
+ ```
231
+ ┌───────────── minute (0-59)
232
+ │ ┌─────────── hour (0-23)
233
+ │ │ ┌───────── day of month (1-31)
234
+ │ │ │ ┌─────── month (1-12)
235
+ │ │ │ │ ┌───── day of week (0-6, Sun=0)
236
+ │ │ │ │ │
237
+ * * * * *
238
+ ```
239
+
240
+ | Expression | Meaning |
241
+ |-----------|---------|
242
+ | `0 9 * * 1-5` | Weekdays at 9 AM |
243
+ | `*/15 * * * *` | Every 15 minutes |
244
+ | `0 0 1 * *` | First of every month |
245
+ | `0 9,17 * * *` | 9 AM and 5 PM daily |
246
+
247
+ ### Template Variables
248
+
249
+ Use in schedule prompts to inject board context:
250
+
251
+ | Variable | Value |
252
+ |----------|-------|
253
+ | `{{board_summary}}` | "3 todo, 1 in-progress, 0 review" |
254
+ | `{{todo_count}}` | Number of todo issues |
255
+ | `{{in_progress_count}}` | Number of in-progress issues |
256
+ | `{{datetime}}` | Current ISO 8601 timestamp |
257
+ | `{{schedule_name}}` | Name of the schedule |
258
+
259
+ ```bash
260
+ prodboard schedule add \
261
+ --name "morning-standup" \
262
+ --cron "0 9 * * 1-5" \
263
+ --prompt "Board: {{board_summary}}. Pick the next todo and work on it."
264
+ ```
265
+
266
+ ### Running as a systemd Service
267
+
268
+ ```bash
269
+ # Install and start as a user-level systemd service (no sudo needed)
270
+ prodboard install
271
+
272
+ # Check status
273
+ systemctl --user status prodboard
274
+
275
+ # Remove the service
276
+ prodboard uninstall
277
+
278
+ # Reinstall (e.g. after updating prodboard)
279
+ prodboard install --force
280
+ ```
281
+
282
+ ## Troubleshooting
283
+
284
+ **"prodboard is not initialized"** — Run `prodboard init`.
285
+
286
+ **MCP not connecting** — Verify `claude mcp add prodboard -- bunx prodboard mcp` was run, or check `~/.prodboard/mcp.json`.
287
+
288
+ **Daemon not starting** — Check `~/.prodboard/logs/daemon.log`. Make sure `claude` CLI is installed and `ANTHROPIC_API_KEY` is set.
289
+
290
+ **Stale PID file** — The daemon crashed. Run `prodboard daemon` to restart (auto-cleans stale PIDs).
291
+
292
+ ## Development
293
+
294
+ ```bash
295
+ bun install
296
+ bun test
297
+ bun run typecheck
298
+ ```
299
+
300
+ ## License
301
+
302
+ MIT
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bun
2
+ import { main } from "../src/index.ts";
3
+
4
+ main();
@@ -0,0 +1,100 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "prodboard Configuration",
4
+ "type": "object",
5
+ "properties": {
6
+ "general": {
7
+ "type": "object",
8
+ "properties": {
9
+ "statuses": {
10
+ "type": "array",
11
+ "items": { "type": "string" },
12
+ "default": ["todo", "in-progress", "review", "done", "archived"],
13
+ "description": "Issue statuses in display order"
14
+ },
15
+ "defaultStatus": {
16
+ "type": "string",
17
+ "default": "todo",
18
+ "description": "Default status for new issues"
19
+ },
20
+ "idPrefix": {
21
+ "type": "string",
22
+ "default": "",
23
+ "description": "Optional prefix for issue IDs"
24
+ }
25
+ },
26
+ "additionalProperties": false
27
+ },
28
+ "daemon": {
29
+ "type": "object",
30
+ "properties": {
31
+ "maxConcurrentRuns": {
32
+ "type": "integer",
33
+ "minimum": 1,
34
+ "default": 2,
35
+ "description": "Maximum concurrent scheduled runs"
36
+ },
37
+ "maxTurns": {
38
+ "type": "integer",
39
+ "minimum": 1,
40
+ "default": 50,
41
+ "description": "Default max turns for Claude invocations"
42
+ },
43
+ "hardMaxTurns": {
44
+ "type": "integer",
45
+ "minimum": 1,
46
+ "default": 200,
47
+ "description": "Absolute max turns (cannot be overridden)"
48
+ },
49
+ "runTimeoutSeconds": {
50
+ "type": "integer",
51
+ "minimum": 60,
52
+ "default": 1800,
53
+ "description": "Timeout per run in seconds"
54
+ },
55
+ "runRetentionDays": {
56
+ "type": "integer",
57
+ "minimum": 1,
58
+ "default": 30,
59
+ "description": "Days to retain run history"
60
+ },
61
+ "logLevel": {
62
+ "type": "string",
63
+ "enum": ["debug", "info", "warn", "error"],
64
+ "default": "info",
65
+ "description": "Daemon log level"
66
+ },
67
+ "logMaxSizeMb": {
68
+ "type": "number",
69
+ "minimum": 1,
70
+ "default": 10,
71
+ "description": "Max log file size in MB"
72
+ },
73
+ "logMaxFiles": {
74
+ "type": "integer",
75
+ "minimum": 1,
76
+ "default": 5,
77
+ "description": "Max number of rotated log files"
78
+ },
79
+ "defaultAllowedTools": {
80
+ "type": "array",
81
+ "items": { "type": "string" },
82
+ "description": "Default tools allowed for scheduled runs"
83
+ },
84
+ "nonGitDefaultAllowedTools": {
85
+ "type": "array",
86
+ "items": { "type": "string" },
87
+ "description": "Default tools for non-git environments"
88
+ },
89
+ "useWorktrees": {
90
+ "type": "string",
91
+ "enum": ["auto", "always", "never"],
92
+ "default": "auto",
93
+ "description": "Worktree usage strategy"
94
+ }
95
+ },
96
+ "additionalProperties": false
97
+ }
98
+ },
99
+ "additionalProperties": false
100
+ }
package/package.json CHANGED
@@ -1,11 +1,52 @@
1
1
  {
2
2
  "name": "prodboard",
3
- "version": "0.0.0",
4
- "description": "",
5
- "main": "index.js",
3
+ "version": "0.1.1",
4
+ "description": "Self-hosted, CLI-first issue tracker and cron scheduler for AI coding agents",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/G4brym/prodboard"
10
+ },
11
+ "homepage": "https://github.com/G4brym/prodboard#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/G4brym/prodboard/issues"
14
+ },
15
+ "keywords": [
16
+ "cli",
17
+ "issue-tracker",
18
+ "mcp",
19
+ "ai-agents",
20
+ "scheduler",
21
+ "cron",
22
+ "sqlite"
23
+ ],
24
+ "bin": {
25
+ "prodboard": "bin/prodboard.ts"
26
+ },
6
27
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
28
+ "dev": "bun run bin/prodboard.ts",
29
+ "test": "bun test",
30
+ "typecheck": "bun x tsc --noEmit",
31
+ "changeset": "changeset",
32
+ "version": "changeset version",
33
+ "release": "bun run test && bun run typecheck && npm publish"
34
+ },
35
+ "dependencies": {
36
+ "@modelcontextprotocol/sdk": "^1.12.1"
37
+ },
38
+ "engines": {
39
+ "bun": ">=1.0.0"
8
40
  },
9
- "author": "",
10
- "license": "MIT"
41
+ "files": [
42
+ "bin/",
43
+ "src/",
44
+ "templates/",
45
+ "config.schema.json",
46
+ "CHANGELOG.md"
47
+ ],
48
+ "devDependencies": {
49
+ "@changesets/cli": "^2.29.8",
50
+ "@types/bun": "^1.3.9"
51
+ }
11
52
  }
@@ -0,0 +1,86 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { ensureDb } from "../db.ts";
3
+ import { getIssueByPrefix } from "../queries/issues.ts";
4
+ import { createComment, listComments } from "../queries/comments.ts";
5
+ import { renderTable, formatDate, jsonOutput } from "../format.ts";
6
+
7
+ function parseArgs(args: string[]): { flags: Record<string, string | boolean>; positional: string[] } {
8
+ const flags: Record<string, string | boolean> = {};
9
+ const positional: string[] = [];
10
+
11
+ for (let i = 0; i < args.length; i++) {
12
+ const arg = args[i];
13
+ if (arg.startsWith("--")) {
14
+ const key = arg.slice(2);
15
+ if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
16
+ flags[key] = args[++i];
17
+ } else {
18
+ flags[key] = true;
19
+ }
20
+ } else if (arg.startsWith("-") && arg.length === 2) {
21
+ const key = arg.slice(1);
22
+ if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
23
+ flags[key] = args[++i];
24
+ } else {
25
+ flags[key] = true;
26
+ }
27
+ } else {
28
+ positional.push(arg);
29
+ }
30
+ }
31
+ return { flags, positional };
32
+ }
33
+
34
+ export async function comment(args: string[], dbOverride?: Database): Promise<void> {
35
+ const { flags, positional } = parseArgs(args);
36
+ const issueIdOrPrefix = positional[0];
37
+ const body = positional.slice(1).join(" ");
38
+
39
+ if (!issueIdOrPrefix || !body) {
40
+ console.error("Usage: prodboard comment <issue-id> <body> [--author/-a author]");
41
+ throw new Error("Invalid arguments");
42
+ }
43
+
44
+ const db = dbOverride ?? ensureDb();
45
+ const issue = getIssueByPrefix(db, issueIdOrPrefix);
46
+
47
+ const author = (flags.author ?? flags.a) as string | undefined;
48
+ const c = createComment(db, {
49
+ issue_id: issue.id,
50
+ body,
51
+ author: typeof author === "string" ? author : undefined,
52
+ });
53
+
54
+ console.log(`Added comment by ${c.author} on issue ${issue.id}`);
55
+ }
56
+
57
+ export async function comments(args: string[], dbOverride?: Database): Promise<void> {
58
+ const { flags, positional } = parseArgs(args);
59
+ const issueIdOrPrefix = positional[0];
60
+
61
+ if (!issueIdOrPrefix) {
62
+ console.error("Usage: prodboard comments <issue-id> [--json]");
63
+ throw new Error("Invalid arguments");
64
+ }
65
+
66
+ const db = dbOverride ?? ensureDb();
67
+ const issue = getIssueByPrefix(db, issueIdOrPrefix);
68
+ const cmts = listComments(db, issue.id);
69
+
70
+ if (flags.json) {
71
+ console.log(jsonOutput(cmts));
72
+ return;
73
+ }
74
+
75
+ if (cmts.length === 0) {
76
+ console.log("No comments.");
77
+ return;
78
+ }
79
+
80
+ const table = renderTable(
81
+ ["Author", "Date", "Comment"],
82
+ cmts.map((c) => [c.author, formatDate(c.created_at), c.body]),
83
+ { maxWidths: [12, 18, 60] }
84
+ );
85
+ console.log(table);
86
+ }