Automate Claude Code on a schedule.
Chat with Claude from Telegram.
Manage everything from a beautiful TUI.
Why OpenCrons · Install · How it works · Quick start · Telegram bot · CLI reference · Configuration · Security · Roadmap
OpenCrons is an open-source scheduler that runs Claude Code (claude -p) jobs on cron schedules. It pairs a terminal-native TUI with a Telegram bot — so you can define, monitor, and chat with your AI jobs from anywhere. Built for developers, researchers, and teams who want structured, repeatable AI automation.
Built with Go · Cobra · Charmbracelet · SQLite · Catppuccin Mocha
OpenCrons is a young project — security coverage is incomplete. Use it with this in mind.
Every scheduled job runs claude -p with --permission-mode bypassPermissions. This means:
- No sandbox — the agent process runs with your full user permissions, in your working directory, with access to your filesystem, network, and any tools Claude Code can invoke
- No tool restrictions by default — unless you explicitly set
disallowed_toolson a job, the agent can read files, write files, run shell commands, and call external services - Unattended — jobs trigger on a cron schedule with no human in the loop to approve or reject individual actions
This is intentional for automation — but it means the prompt is the security boundary. A poorly scoped prompt can lead to unintended writes, deletions, or network calls.
Practical guidance:
- Scope prompts tightly to the task at hand
- Use
disallowed_toolsto restrict capabilities where possible (e.g.Bash(rm:*)) - Set a
working_dirthat contains only what the job needs access to - Review execution logs regularly (
opencrons logs) - Keep your Claude Code version up to date
This project just released and does not yet cover all security aspects. Contributions and issues are welcome.
Requires Go 1.25+ and Claude Code.
go install github.com/DikaVer/opencrons/cmd/opencrons@latestThat's it. The binary lands in $GOPATH/bin — already in your PATH if Go is set up correctly.
🔨 Build from source
git clone https://github.com/DikaVer/opencrons.git
cd opencrons
# Linux / macOS
sudo make install
# Windows
go install ./cmd/opencrons/🗑️ Uninstall
# Linux / macOS
sudo make uninstall
# Windows (PowerShell)
Remove-Item "$(go env GOPATH)\bin\opencrons.exe"Verify:
opencrons --helpOpenCrons has three modes of operation:
| Mode | What it does |
|---|---|
| 🖥️ Interactive TUI | Run opencrons with no args. A full-screen menu for creating, editing, and managing jobs. |
| ⌨️ CLI commands | Scriptable subcommands — opencrons add, opencrons list, opencrons run, etc. |
| 💬 Telegram bot | Runs inside the daemon. Chat with Claude, trigger jobs, and get notifications — all from your phone. |
📝 You define a job
→ ⏰ cron schedule triggers it
→ 📄 OpenCrons reads the prompt file
→ 🚀 pipes it to `claude -p` with your configured model & effort
→ 📊 captures output, cost, and token usage
→ 💾 logs everything to SQLite
→ 💬 (optionally) sends a summary to Telegram
Every job runs as an isolated subprocess with --permission-mode bypassPermissions for unattended operation, and --output-format json for structured result parsing.
opencrons setupThe wizard walks you through:
- 🔑 Provider — detects your Anthropic configuration
- 💬 Messenger — connect a Telegram bot (optional)
- 🤖 Chat defaults — pick a default model and effort level
- ⚡ Daemon mode — background process or OS service
opencrons addThe interactive wizard asks for a name, cron schedule, working directory, model, and prompt. Or go fully non-interactive:
opencrons add --non-interactive \
--name "daily-review" \
--schedule "0 9 * * *" \
--working-dir "/path/to/project" \
--prompt-content "Review open PRs and summarize findings." \
--model sonnetopencrons startThe daemon runs your cron jobs, watches for config changes (hot-reload), and starts the Telegram bot if configured. Stop it with opencrons stop.
opencrons logs # all jobs
opencrons logs daily-review # specific job
opencrons logs daily-review -n 50 # specific job, last 50 entriesThe Telegram integration turns OpenCrons into a remote AI assistant you can reach from your pocket.
- 🤖 Create a bot via @BotFather on Telegram
- 🔧 Run
opencrons setuporopencrons settingsto configure the bot token - 🔐 Pair your account:
- Verification code — OpenCrons generates a code, you send it to your bot to prove ownership
| Command | Action |
|---|---|
/new |
🆕 Start a fresh chat session |
/stop |
🛑 Cancel a running query |
/jobs |
📋 Browse and trigger jobs |
/model |
🧠 Switch model (Sonnet, Opus, Haiku) |
/effort |
⚡ Adjust effort level |
/status |
📊 Daemon and session info |
/help |
❓ Show all commands |
Send any text message to chat with Claude directly. Sessions persist across messages — Claude remembers context until you /new.
opencrons add # create a job (interactive wizard)
opencrons list # list all jobs
opencrons edit <name> # edit a job
opencrons remove <name> # delete a job (--force to skip confirmation)
opencrons enable <name> # enable a disabled job
opencrons disable <name> # disable a job
opencrons validate # validate all job configsopencrons run <name> # run a job immediately
opencrons logs [name] # view execution logs (-n to set limit)opencrons start # start the daemon (foreground)
opencrons start --install # install as OS service
opencrons stop # stop the daemon
opencrons status # check daemon statusopencrons setup # first-time setup wizard
opencrons settings # manage all settings
opencrons debug [on|off] # toggle debug loggingopencrons --verbose # verbose output (any subcommand)
opencrons --help # help for any commandEach job is a YAML file in schedules/ with a corresponding prompt in prompts/.
| Field | Description | Default |
|---|---|---|
name |
Unique identifier (alphanumeric, hyphens, underscores) | required |
schedule |
Cron expression (0 9 * * *) |
required |
working_dir |
Project directory for execution | required |
prompt_file |
Markdown file with the prompt | <name>.md |
model |
sonnet, opus, or haiku |
provider default |
effort |
low, medium, high, or max |
high |
timeout |
Seconds before killing the job | 300 |
disallowed_tools |
Tool restrictions (e.g. Bash(git:*)) |
none |
summary_enabled |
Generate execution summary | false |
enabled |
Whether the job runs on schedule | true |
OpenCrons stores its configuration and data in a platform-specific directory:
| Platform | Path |
|---|---|
| 🐧 Linux | ~/.opencrons/ or $XDG_CONFIG_HOME/opencrons/ |
| 🍎 macOS | ~/.opencrons/ or $XDG_CONFIG_HOME/opencrons/ |
| 🪟 Windows | %APPDATA%\opencrons\ |
~/.opencrons/
├── .agents/ # agent config directory (canonical)
│ └── skills/ # scheduling skill + plugin skills
├── .claude/ → .agents/ # provider symlink (Anthropic)
├── AGENTS.md # agent instructions (canonical)
├── CLAUDE.md → AGENTS.md # provider symlink (Anthropic)
├── schedules/ # job configs (YAML)
├── prompts/ # prompt files (Markdown)
├── logs/ # execution stdout/stderr
├── summary/ # execution summaries
├── data/opencrons.db # SQLite database
├── settings.json # all settings
└── opencrons.pid # daemon lock file
The .agents/ directory and AGENTS.md file are the canonical (real) locations. Provider-specific names like .claude/ and CLAUDE.md are created as symlinks so that each provider's tooling finds what it expects. On Windows without developer mode, junctions and hard links are used as fallbacks.
OpenCrons copies AGENTS.md and .agents/ into your config directory during setup. AGENTS.md is injected into every job as context — it acts as a shared system prompt so Claude understands it's running inside OpenCrons.
You can customize it to add project-wide instructions, coding standards, or constraints that apply to all your scheduled jobs.
A ready-to-use example is included in the repo at .workspace-example/ — it's copied automatically on first run via opencrons setup.
| Linux | macOS | Windows | |
|---|---|---|---|
| CLI & TUI | ✅ | ✅ | ✅ |
| Daemon | ✅ | ✅ | ✅ |
| OS service install | ✅ | ✅ | ✅ |
When a job triggers, OpenCrons:
- 📄 Reads the prompt file and prepends a task preamble
- 📎 Optionally appends a summary prompt
- 🔒 Pipes everything via stdin to
claude -p(avoids argument length limits) - 🚀 Passes
--effort,--model,--permission-mode bypassPermissions,--output-format json - 📝 Captures stdout/stderr to log files
- 📊 Parses the JSON response for cost, token usage, and result
- 💾 Writes execution records to SQLite
Config changes are picked up automatically — the daemon watches the schedules/ directory with fsnotify and hot-reloads jobs without restart.
OpenCrons is focused on Claude Code today, but the vision is broader.
- ⌨️ Codex CLI support — run OpenAI's Codex CLI alongside Claude Code jobs
- 🏷️ Job tags and filtering
- 📱 Push notifications (beyond Telegram)
- 🔀 Multi-provider jobs — run the same prompt against Claude and GPT in parallel, compare results
- 🧠 Agent task memory — persistent per-job memory that survives between runs; agents accumulate context across executions rather than starting cold each time
- 🔄 Workflow agent pipeline — chain multiple agents into a directed pipeline where each agent's output becomes the next one's input; branch on conditions, fan out in parallel, merge results
- 📦 Sandbox environment — run agents inside an isolated container or VM with restricted filesystem and network access, so
bypassPermissionsis safer by construction
Have an idea? Open an issue — contributions are welcome.
make build # build binary
make build-all # cross-compile (linux + windows)
make test # run tests
make lint # golangci-lint
make tidy # go mod tidy
make clean # remove build artifactscmd/opencrons/ → entry point
internal/
├── cmd/ → Cobra commands + TUI menu
├── config/ → job config, YAML I/O, prompt files
├── tui/ → interactive wizards and menus
├── executor/ → claude -p command builder and runner
├── storage/ → SQLite (execution logs, chat sessions)
├── daemon/ → cron orchestrator, hot-reload, OS service
├── platform/ → cross-platform paths, PID, settings
├── provider/ → AI provider interface
├── messenger/telegram/ → Telegram bot handlers
├── chat/ → chat session manager
├── logger/ → debug logging
└── ui/ → shared styles (Catppuccin Mocha)