{"id":50584826,"url":"https://github.com/owsas/cli-routines","last_synced_at":"2026-06-05T05:02:29.106Z","repository":{"id":361026725,"uuid":"1249468817","full_name":"owsas/cli-routines","owner":"owsas","description":"cli-routines","archived":false,"fork":false,"pushed_at":"2026-05-28T21:58:48.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-28T23:21:04.422Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/owsas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T18:26:21.000Z","updated_at":"2026-05-28T21:58:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/owsas/cli-routines","commit_stats":null,"previous_names":["owsas/cli-routines"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/owsas/cli-routines","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owsas%2Fcli-routines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owsas%2Fcli-routines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owsas%2Fcli-routines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owsas%2Fcli-routines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/owsas","download_url":"https://codeload.github.com/owsas/cli-routines/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owsas%2Fcli-routines/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33930311,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-05T05:02:28.397Z","updated_at":"2026-06-05T05:02:29.100Z","avatar_url":"https://github.com/owsas.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cli-routines\n\nSchedule and run local routines — shell commands, OpenCode prompts, or Claude prompts — on a cron schedule.\n\n## Install\n\n```bash\ngit clone git@github.com:owsas/cli-routines.git\ncd cli-routines\ngo build -o routines .\nsudo cp routines /usr/local/bin/\n```\n\nOr with `go install`:\n\n```bash\ngo install github.com/owsas/cli-routines@latest\n```\n\n## Quickstart\n\n```bash\n# Create a default config file\nroutines init\n\n# List your routines\nroutines list\n\n# Run a routine immediately\nroutines run example-routine\n\n# Start the daemon (runs enabled routines on schedule)\nroutines start\n\n# Check daemon status and next run times\nroutines status\n\n# Stop the daemon\nroutines stop\n```\n\n## Config\n\nRoutines are defined in `~/.cli-routines/routines.json`.\n\n### Schema\n\n```json\n{\n  \"routines\": [\n    {\n      \"name\": \"daily-standup\",\n      \"description\": \"Prep standup notes\",\n      \"schedule\": \"0 9 * * 1-5\",\n      \"folder\": \"/Users/juan/my-project\",\n      \"executor\": {\n        \"type\": \"opencode\",\n        \"prompt\": \"Summarize git changes from last 24h\"\n      },\n      \"enabled\": true,\n      \"notify\": true\n    }\n  ]\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `name` | string | Unique identifier for the routine |\n| `description` | string | Human-readable description |\n| `schedule` | string | Cron expression (minute, hour, day of month, month, day of week) |\n| `folder` | string | Working directory when the routine runs |\n| `executor` | object | What to run (see executor types below) |\n| `enabled` | bool | Whether the daemon should run this on schedule |\n| `notify` | bool | Whether to show a desktop notification on completion |\n\n### Executor types\n\n#### `shell` — Run a shell command\n\n```json\n{\n  \"type\": \"shell\",\n  \"command\": \"pg_dump mydb \u003e backup-$(date +%Y%m%d).sql\"\n}\n```\n\nRuns `bash -c \"\u003ccommand\u003e\"` in the routine's folder.\n\n#### `opencode` — Run an OpenCode prompt\n\n```json\n{\n  \"type\": \"opencode\",\n  \"prompt\": \"Summarize git changes from the last 24 hours\",\n  \"model\": \"\"\n}\n```\n\nRuns `opencode run \"\u003cprompt\u003e\" --dir \u003cfolder\u003e --dangerously-skip-permissions`.  \nSet `model` to a specific model (e.g. `\"anthropic/claude-sonnet-4-20250514\"`) or leave empty for OpenCode's default.\n\n#### `claude` — Run a Claude prompt\n\n```json\n{\n  \"type\": \"claude\",\n  \"prompt\": \"Review this codebase for potential issues\",\n  \"model\": \"\",\n  \"permissionMode\": \"\",\n  \"dangerouslySkipPermissions\": false\n}\n```\n\nRuns `claude -p \"\u003cprompt\u003e\"` in the routine's folder. Requires the [Claude CLI](https://docs.anthropic.com/en/docs/claude-code).  \nSet `model` to override the default model.\n\nFor **unattended** routines that need to edit files or run tools without an\napproval prompt, set the permission mode:\n\n- `permissionMode` — maps to Claude's `--permission-mode` flag. One of\n  `default`, `acceptEdits`, `plan`, `bypassPermissions`.\n- `dangerouslySkipPermissions` — shorthand for `permissionMode: \"bypassPermissions\"`\n  (mirrors the opencode executor's `--dangerously-skip-permissions`). Ignored\n  when `permissionMode` is set explicitly.\n\nWithout either, `claude -p` uses whatever mode your Claude settings default to —\nwhich may pause on approval prompts and stall a scheduled run.\n\n### Cron syntax\n\nStandard 5-field cron expressions:\n\n```\n┌── minute (0-59)\n│ ┌── hour (0-23)\n│ │ ┌── day of month (1-31)\n│ │ │ ┌── month (1-12)\n│ │ │ │ ┌── day of week (0-6, 0=Sunday)\n│ │ │ │ │\n* * * * *\n```\n\n| Expression | Meaning |\n|---|---|\n| `0 9 * * 1-5` | Every weekday at 9:00 AM |\n| `0 14 * * 5` | Every Friday at 2:00 PM |\n| `0 3 * * *` | Every day at 3:00 AM |\n| `*/15 * * * *` | Every 15 minutes |\n\nSupports `@every` syntax too: `@every 1h30m`, `@every 5m`, `@daily`, `@hourly`.\n\n## CLI Reference\n\n| Command | Description |\n|---|---|\n| `routines init` | Create `~/.cli-routines/routines.json` with an example routine |\n| `routines list` | List all routines (alias: `ls`) |\n| `routines status` | Show daemon status and next run times |\n| `routines start` | Start the daemon in the background |\n| `routines start --foreground` | Start the daemon in the foreground (pinned to terminal) |\n| `routines stop` | Stop the running daemon |\n| `routines run \u003cname\u003e` | Run a single routine immediately (foreground) |\n\n## Logs\n\nAll routine execution is logged to `~/.cli-routines/routines.log`:\n\n```\n[2026-05-25 09:00:01] daily-standup        START (opencode: Summarize git changes...)\n[2026-05-25 09:00:01] daily-standup        Running in: /Users/juan/my-project\n[2026-05-25 09:00:45] daily-standup        DONE (44s)\n[2026-05-26 03:00:00] nightly-cleanup      START (shell: find . -name '*.tmp'...)\n[2026-05-26 03:00:01] nightly-cleanup      DONE (1s)\n```\n\n## Files\n\n| File | Purpose |\n|---|---|\n| `~/.cli-routines/routines.json` | Routine definitions |\n| `~/.cli-routines/routines.pid` | Daemon PID file |\n| `~/.cli-routines/routines.log` | Execution log |\n\n## Running on login (macOS)\n\nTo have the daemon start automatically when you log in, create a LaunchAgent:\n\n```bash\ncat \u003e ~/Library/LaunchAgents/com.cli-routines.plist \u003c\u003c 'EOF'\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"\n  \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n  \u003ckey\u003eLabel\u003c/key\u003e\n  \u003cstring\u003ecom.cli-routines\u003c/string\u003e\n  \u003ckey\u003eProgramArguments\u003c/key\u003e\n  \u003carray\u003e\n    \u003cstring\u003e/usr/local/bin/routines\u003c/string\u003e\n    \u003cstring\u003estart\u003c/string\u003e\n    \u003cstring\u003e--foreground\u003c/string\u003e\n  \u003c/array\u003e\n  \u003ckey\u003eRunAtLoad\u003c/key\u003e\n  \u003ctrue/\u003e\n  \u003ckey\u003eKeepAlive\u003c/key\u003e\n  \u003ctrue/\u003e\n  \u003ckey\u003eStandardOutPath\u003c/key\u003e\n  \u003cstring\u003e/tmp/routines-launchd.log\u003c/string\u003e\n  \u003ckey\u003eStandardErrorPath\u003c/key\u003e\n  \u003cstring\u003e/tmp/routines-launchd.log\u003c/string\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\nEOF\n\nlaunchctl load ~/Library/LaunchAgents/com.cli-routines.plist\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowsas%2Fcli-routines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fowsas%2Fcli-routines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowsas%2Fcli-routines/lists"}