| name | jules-cronjob |
| description | Schedule Jules API sessions via cron-job.org. Use when the user asks to create a Jules session in the future, schedule a Jules task, automate a Jules coding job, or trigger Jules via cron. Handles cron-job.org API auth, correct payload format, timing, and Jules session body.
|
Jules Session via cron-job.org
Schedule a POST https://jules.googleapis.com/v1alpha/sessions request
using the cron-job.org HTTP cron service.
Credentials
Jules API Key
Read from environment or config (in priority order):
echo $JULES_API_KEY
cat ~/.config/verne/config.json
cron-job.org API Key
Available as the environment variable CRONJOB_API_KEY:
echo $CRONJOB_API_KEY
cron-job.org API Reference
Base URL: https://api.cron-job.org
Auth header: Authorization: Bearer <key>
| Operation | Method | Path |
|---|
| List jobs | GET | /jobs |
| Create job | PUT | /jobs |
| Get job | GET | /jobs/{jobId} |
| Update job | PATCH | /jobs/{jobId} |
| Delete job | DELETE | /jobs/{jobId} |
| Get job history | GET | /jobs/{jobId}/history |
| Get execution detail | GET | /jobs/{jobId}/history/{identifier} |
IMPORTANT: Headers format
extendedData.headers must be a dict/object, NOT an array:
"headers": {
"x-goog-api-key": "<jules-key>",
"Content-Type": "application/json"
}
requestMethod values
0=GET, 1=POST, 2=OPTIONS, 3=HEAD, 4=PUT, 5=DELETE, 8=PATCH
Schedule format
All arrays. Use [-1] for "every":
"schedule": {
"timezone": "UTC",
"minutes": [51],
"hours": [17],
"mdays": [11],
"months": [4],
"wdays": [-1]
}
Full Create-Job Payload
{
"job": {
"url": "https://jules.googleapis.com/v1alpha/sessions",
"enabled": true,
"title": "<descriptive name>",
"saveResponses": true,
"requestMethod": 1,
"extendedData": {
"headers": {
"x-goog-api-key": "<JULES_API_KEY>",
"Content-Type": "application/json"
},
"body": "{\"title\": \"<session title>\", \"prompt\": \"<prompt text>\"}"
},
"schedule": {
"timezone": "UTC",
"minutes": [<minute>],
"hours": [<hour>],
"mdays": [<day>],
"months": [<month>],
"wdays": [-1]
}
}
}
Note: body must be a JSON-encoded string (the inner JSON serialized as a string value).
Workflow
Step 1 — Get credentials
JULES_KEY=$(python3 -c "
import os, json
from pathlib import Path
env = os.getenv('JULES_API_KEY')
if env:
print(env)
else:
cfg = Path.home() / '.config/verne/config.json'
print(json.loads(cfg.read_text())['api_key'])
")
CRONJOB_KEY="$CRONJOB_API_KEY"
Step 2 — Get current UTC time, calculate target minute
date -u +"%H %M %d %m"
Step 3 — Build and send the request
import json, os, subprocess, datetime
jules_key = "<from step 1>"
cronjob_key = os.environ["CRONJOB_API_KEY"]
now = datetime.datetime.utcnow()
target = now + datetime.timedelta(minutes=2)
request_body = json.dumps({
"title": "<session title>",
"prompt": "<detailed prompt>"
})
payload = {
"job": {
"url": "https://jules.googleapis.com/v1alpha/sessions",
"enabled": True,
"title": "<cron job label>",
"saveResponses": True,
"requestMethod": 1,
"extendedData": {
"headers": {
"x-goog-api-key": jules_key,
"Content-Type": "application/json"
},
"body": request_body
},
"schedule": {
"timezone": "UTC",
"minutes": [target.minute],
"hours": [target.hour],
"mdays": [target.day],
"months": [target.month],
"wdays": [-1]
}
}
}
result = subprocess.run(
["curl", "-s", "-w", "\nHTTP:%{http_code}", "-X", "PUT",
"https://api.cron-job.org/jobs",
"-H", f"Authorization: Bearer {cronjob_key}",
"-H", "Content-Type: application/json",
"-d", json.dumps(payload)],
capture_output=True, text=True
)
lines = result.stdout.strip().split("\n")
print("HTTP:", lines[-1])
print("Response:", json.loads("\n".join(lines[:-1])))
Step 4 — Confirm and report to user
After a successful response ({"jobId": 12345}), report:
- Job ID
- Scheduled time (UTC)
- Target URL
- Jules session title and prompt summary
Step 5 — Optionally check execution result
After the scheduled time has passed:
curl -s "https://api.cron-job.org/jobs/<jobId>/history" \
-H "Authorization: Bearer $CRONJOB_API_KEY" | python3 -m json.tool
curl -s "https://api.cron-job.org/jobs/<jobId>/history/<identifier>" \
-H "Authorization: Bearer $CRONJOB_API_KEY" | python3 -m json.tool
Jules Session Body Fields
| Field | Type | Notes |
|---|
title | string | Required. Human-readable session name. |
prompt | string | The coding task description. |
sourceContext.source | string | Optional. e.g. "sources/github.com/owner/repo" |
sourceContext.githubRepoContext.startingBranch | string | Optional branch. |
automationMode | string | Optional. |
requirePlanApproval | bool | Optional. |
Common Mistakes to Avoid
- DO NOT hardcode API keys in skill docs or scripts — always read from
$CRONJOB_API_KEY.
- DO NOT use an array for
extendedData.headers — must be a plain object/dict.
- DO NOT use
POST /jobs — the create endpoint is PUT /jobs.
- DO NOT forget to JSON-serialize
extendedData.body as a string (double-encode).
- DO NOT forget that
schedule.months is 1-indexed (January = 1).
- Always use
saveResponses: true so you can inspect the Jules API response later.