@elmiristic/agent-ready 0.1.2 → 0.1.4
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/README.md +39 -16
- package/package.json +1 -1
- package/src/init.js +3 -1
- package/src/steps/collectSchedule.js +85 -0
- package/src/steps/scaffold.js +2 -2
- package/src/templates/workflow.js +3 -3
package/README.md
CHANGED
|
@@ -2,39 +2,62 @@
|
|
|
2
2
|
|
|
3
3
|
Wire an AI coding agent into any GitHub repo in 5 minutes.
|
|
4
4
|
|
|
5
|
-
Tag a Trello card **agent-ready
|
|
5
|
+
Tag a Trello card **agent-ready** and Claude reads the task, writes the code, opens a PR, and pings you on Telegram. Runs on your schedule, in your timezone.
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npx agent-ready init
|
|
10
|
+
npx @elmiristic/agent-ready init
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The wizard
|
|
14
|
-
1. Connect your Trello board
|
|
15
|
-
2. Add your Anthropic API key
|
|
16
|
-
3. Give you a Telegram chat ID via @agent_ready_bot
|
|
17
|
-
4. Set all GitHub secrets automatically
|
|
18
|
-
5. Write the GitHub Actions workflows into your repo
|
|
13
|
+
That's it. The wizard handles everything.
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
## What the wizard sets up
|
|
16
|
+
|
|
17
|
+
1. **Board** - connect your Trello board and pick the right lists
|
|
18
|
+
2. **Anthropic** - add your Claude API key
|
|
19
|
+
3. **Telegram** - message [@agentreadybot](https://t.me/agentreadybot) and paste your chat ID. No bot setup needed.
|
|
20
|
+
4. **Schedule** - pick your timezone and the times you want the agent to run each day
|
|
21
|
+
5. **GitHub secrets** - set automatically via GitHub CLI, or manually if you prefer
|
|
22
|
+
6. **Workflow files** - written directly into your repo under `.github/`
|
|
23
|
+
|
|
24
|
+
Then run:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git add .github && git commit -m "feat: add agent-ready" && git push
|
|
28
|
+
```
|
|
21
29
|
|
|
22
30
|
## How it works
|
|
23
31
|
|
|
24
|
-
1. Add the `agent-ready` label to a Trello card in your
|
|
25
|
-
2. The agent runs at
|
|
26
|
-
3. Claude reads the card title
|
|
27
|
-
4. A PR is opened
|
|
32
|
+
1. Add the `agent-ready` label to a Trello card in your To Do list
|
|
33
|
+
2. The agent runs at the times you chose during setup
|
|
34
|
+
3. Claude reads the card title and description, finds the relevant files, and writes the code
|
|
35
|
+
4. A PR is opened with a summary of the change
|
|
28
36
|
5. You get a Telegram message with the PR link
|
|
29
|
-
6. Merge the PR
|
|
37
|
+
6. Merge the PR and the card moves to Done automatically
|
|
38
|
+
|
|
39
|
+
Nothing touches `main` without your review.
|
|
40
|
+
|
|
41
|
+
## Schedule
|
|
42
|
+
|
|
43
|
+
During setup you pick your timezone and up to two daily run times. The wizard converts them to UTC and writes the correct cron expressions into your workflow file. You can also trigger a run manually anytime from the GitHub Actions tab.
|
|
30
44
|
|
|
31
45
|
## Requirements
|
|
32
46
|
|
|
33
47
|
- Node.js 18+
|
|
34
48
|
- A GitHub repository
|
|
35
|
-
- GitHub CLI (`gh`) for automatic secret setup (optional - can set manually)
|
|
36
49
|
- A Trello account
|
|
37
|
-
- An Anthropic API key
|
|
50
|
+
- An Anthropic API key (get one at [console.anthropic.com](https://console.anthropic.com))
|
|
51
|
+
- GitHub CLI (`gh`) for automatic secret setup — optional, secrets can be added manually
|
|
52
|
+
|
|
53
|
+
## Supported board tools
|
|
54
|
+
|
|
55
|
+
| Tool | Status |
|
|
56
|
+
|------|--------|
|
|
57
|
+
| Trello | Available |
|
|
58
|
+
| Jira | Coming soon |
|
|
59
|
+
| Linear | Coming soon |
|
|
60
|
+
| GitHub Projects | Coming soon |
|
|
38
61
|
|
|
39
62
|
## License
|
|
40
63
|
|
package/package.json
CHANGED
package/src/init.js
CHANGED
|
@@ -4,6 +4,7 @@ import { selectProvider } from './steps/selectProvider.js'
|
|
|
4
4
|
import { collectTrello } from './steps/collectTrello.js'
|
|
5
5
|
import { collectAnthropic } from './steps/collectAnthropic.js'
|
|
6
6
|
import { collectTelegram } from './steps/collectTelegram.js'
|
|
7
|
+
import { collectSchedule } from './steps/collectSchedule.js'
|
|
7
8
|
import { setGithubSecrets } from './steps/setGithubSecrets.js'
|
|
8
9
|
import { scaffold } from './steps/scaffold.js'
|
|
9
10
|
import { done } from './steps/done.js'
|
|
@@ -15,9 +16,10 @@ export async function init() {
|
|
|
15
16
|
const board = await collectTrello()
|
|
16
17
|
const anthropic = await collectAnthropic()
|
|
17
18
|
const telegram = await collectTelegram()
|
|
19
|
+
const schedule = await collectSchedule()
|
|
18
20
|
const secrets = { ...board, ...anthropic, ...telegram }
|
|
19
21
|
await setGithubSecrets(secrets)
|
|
20
|
-
await scaffold()
|
|
22
|
+
await scaffold({ crons: schedule.crons })
|
|
21
23
|
await done()
|
|
22
24
|
} catch (err) {
|
|
23
25
|
if (err.name === 'ExitPromptError') {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { select, confirm, input } from '@inquirer/prompts'
|
|
3
|
+
|
|
4
|
+
const TIMEZONES = [
|
|
5
|
+
{ name: 'UTC+0 — London, Lisbon', value: 0 },
|
|
6
|
+
{ name: 'UTC-5 — New York, Toronto', value: -5 },
|
|
7
|
+
{ name: 'UTC-6 — Chicago, Mexico City', value: -6 },
|
|
8
|
+
{ name: 'UTC-7 — Denver, Phoenix', value: -7 },
|
|
9
|
+
{ name: 'UTC-8 — Los Angeles, Vancouver', value: -8 },
|
|
10
|
+
{ name: 'UTC+1 — Paris, Berlin, Rome', value: 1 },
|
|
11
|
+
{ name: 'UTC+2 — Cairo, Kyiv, Helsinki', value: 2 },
|
|
12
|
+
{ name: 'UTC+3 — Istanbul, Moscow, Riyadh', value: 3 },
|
|
13
|
+
{ name: 'UTC+4 — Dubai, Baku', value: 4 },
|
|
14
|
+
{ name: 'UTC+5 — Karachi, Tashkent', value: 5 },
|
|
15
|
+
{ name: 'UTC+5:30 — Mumbai, Kolkata', value: 5.5 },
|
|
16
|
+
{ name: 'UTC+6 — Dhaka, Almaty', value: 6 },
|
|
17
|
+
{ name: 'UTC+7 — Bangkok, Jakarta', value: 7 },
|
|
18
|
+
{ name: 'UTC+8 — Singapore, Beijing, Perth', value: 8 },
|
|
19
|
+
{ name: 'UTC+9 — Tokyo, Seoul', value: 9 },
|
|
20
|
+
{ name: 'UTC+10 — Sydney, Melbourne', value: 10 },
|
|
21
|
+
{ name: 'UTC+12 — Auckland', value: 12 },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
function toUtcHour(localHour, offsetHours) {
|
|
25
|
+
const utc = ((localHour - offsetHours) % 24 + 24) % 24
|
|
26
|
+
return Math.round(utc)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function askHour(label) {
|
|
30
|
+
const raw = await input({
|
|
31
|
+
message: ` ${label} (0-23, e.g. 9 for 9am)`,
|
|
32
|
+
validate: (v) => {
|
|
33
|
+
const n = Number(v)
|
|
34
|
+
if (isNaN(n) || n < 0 || n > 23) return 'Enter a number between 0 and 23'
|
|
35
|
+
return true
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
return Number(raw)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function collectSchedule() {
|
|
42
|
+
console.log(chalk.bold(' Schedule'))
|
|
43
|
+
console.log()
|
|
44
|
+
console.log(chalk.dim(' Choose when the agent checks for tasks each day.'))
|
|
45
|
+
console.log()
|
|
46
|
+
|
|
47
|
+
const offset = await select({
|
|
48
|
+
message: ' Your timezone',
|
|
49
|
+
choices: TIMEZONES,
|
|
50
|
+
pageSize: 10,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
console.log()
|
|
54
|
+
|
|
55
|
+
const hour1 = await askHour('First run time')
|
|
56
|
+
const utc1 = toUtcHour(hour1, offset)
|
|
57
|
+
|
|
58
|
+
console.log()
|
|
59
|
+
|
|
60
|
+
const addSecond = await confirm({
|
|
61
|
+
message: ' Add a second daily run?',
|
|
62
|
+
default: true,
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
console.log()
|
|
66
|
+
|
|
67
|
+
const crons = [`0 ${utc1} * * *`]
|
|
68
|
+
|
|
69
|
+
if (addSecond) {
|
|
70
|
+
const hour2 = await askHour('Second run time')
|
|
71
|
+
const utc2 = toUtcHour(hour2, offset)
|
|
72
|
+
crons.push(`0 ${utc2} * * *`)
|
|
73
|
+
console.log()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const fmt = (h) => `${h % 12 === 0 ? 12 : h % 12}${h < 12 ? 'am' : 'pm'}`
|
|
77
|
+
const times = addSecond
|
|
78
|
+
? `${fmt(hour1)} and ${fmt(Number(crons[1].split(' ')[1]) + offset)}`
|
|
79
|
+
: fmt(hour1)
|
|
80
|
+
|
|
81
|
+
console.log(chalk.dim(` Agent will run at ${times} your time.`))
|
|
82
|
+
console.log()
|
|
83
|
+
|
|
84
|
+
return { crons }
|
|
85
|
+
}
|
package/src/steps/scaffold.js
CHANGED
|
@@ -6,7 +6,7 @@ import { workflowTemplate } from '../templates/workflow.js'
|
|
|
6
6
|
import { agentScriptTemplate } from '../templates/agentScript.js'
|
|
7
7
|
import { doneWorkflowTemplate } from '../templates/doneWorkflow.js'
|
|
8
8
|
|
|
9
|
-
export async function scaffold() {
|
|
9
|
+
export async function scaffold({ crons } = {}) {
|
|
10
10
|
const spinner = ora({ text: ' Generating workflow files...', indent: 2 }).start()
|
|
11
11
|
|
|
12
12
|
const cwd = process.cwd()
|
|
@@ -19,7 +19,7 @@ export async function scaffold() {
|
|
|
19
19
|
|
|
20
20
|
await fs.writeFile(
|
|
21
21
|
path.join(workflowsDir, 'agent-ready.yml'),
|
|
22
|
-
workflowTemplate(),
|
|
22
|
+
workflowTemplate(crons),
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
await fs.writeFile(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export function workflowTemplate() {
|
|
1
|
+
export function workflowTemplate(crons = ['0 9 * * *', '0 17 * * *']) {
|
|
2
|
+
const cronLines = crons.map(c => ` - cron: '${c}'`).join('\n')
|
|
2
3
|
return `name: agent-ready
|
|
3
4
|
|
|
4
5
|
on:
|
|
5
6
|
schedule:
|
|
6
|
-
|
|
7
|
-
- cron: '0 17 * * *'
|
|
7
|
+
${cronLines}
|
|
8
8
|
workflow_dispatch:
|
|
9
9
|
|
|
10
10
|
permissions:
|