{"id":31058310,"url":"https://github.com/bnomei/kirby-janitor","last_synced_at":"2025-09-15T07:04:54.212Z","repository":{"id":37587520,"uuid":"160715400","full_name":"bnomei/kirby-janitor","owner":"bnomei","description":"Kirby Plugin for running commands like cleaning the cache from within the Panel, PHP code, CLI or a cronjob","archived":false,"fork":false,"pushed_at":"2025-07-17T12:48:16.000Z","size":2358,"stargazers_count":89,"open_issues_count":1,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-09-05T18:21:50.394Z","etag":null,"topics":["backup","button","cache","cli","command","cronjob","job-runner","kirby","kirby-cms","kirby-plugin","kirby4","kirby5","maintenance","maintenance-mode","notifications","panel","render","repl","tinker","view-buttons"],"latest_commit_sha":null,"homepage":"https://forum.getkirby.com/t/kirby3-janitor-plugin/23573","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bnomei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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},"funding":{"github":"bnomei","patreon":"bnomei","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://buymeacoff.ee/bnomei","https://paypal.me/bnomei"]}},"created_at":"2018-12-06T18:28:50.000Z","updated_at":"2025-09-04T18:39:23.000Z","dependencies_parsed_at":"2022-07-20T12:32:33.128Z","dependency_job_id":"d428198d-c9ec-42f7-b1b0-116b47616bb7","html_url":"https://github.com/bnomei/kirby-janitor","commit_stats":{"total_commits":292,"total_committers":10,"mean_commits":29.2,"dds":"0.21232876712328763","last_synced_commit":"c48d5b1fd2e5974f48d9ba08476c62b070aa830e"},"previous_names":["bnomei/kirby-janitor"],"tags_count":123,"template":false,"template_full_name":null,"purl":"pkg:github/bnomei/kirby-janitor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fkirby-janitor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fkirby-janitor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fkirby-janitor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fkirby-janitor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bnomei","download_url":"https://codeload.github.com/bnomei/kirby-janitor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bnomei%2Fkirby-janitor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273913582,"owners_count":25189985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"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":["backup","button","cache","cli","command","cronjob","job-runner","kirby","kirby-cms","kirby-plugin","kirby4","kirby5","maintenance","maintenance-mode","notifications","panel","render","repl","tinker","view-buttons"],"created_at":"2025-09-15T07:04:02.969Z","updated_at":"2025-09-15T07:04:54.192Z","avatar_url":"https://github.com/bnomei.png","language":"PHP","funding_links":["https://github.com/sponsors/bnomei","https://patreon.com/bnomei","https://buymeacoff.ee/bnomei","https://paypal.me/bnomei","https://www.buymeacoffee.com/bnomei"],"categories":[],"sub_categories":[],"readme":"# Kirby Janitor\n\n[![Kirby 5](https://flat.badgen.net/badge/Kirby/5?color=ECC748)](https://getkirby.com)\n![PHP 8.2](https://flat.badgen.net/badge/PHP/8.2?color=4E5B93\u0026icon=php\u0026label)\n![Release](https://flat.badgen.net/packagist/v/bnomei/kirby-janitor?color=ae81ff\u0026icon=github\u0026label)\n[![Discord](https://flat.badgen.net/badge/discord/bnomei?color=7289da\u0026icon=discord\u0026label)](https://discordapp.com/users/bnomei)\n[![Buymecoffee](https://flat.badgen.net/badge/icon/donate?icon=buymeacoffee\u0026color=FF813F\u0026label)](https://www.buymeacoffee.com/bnomei)\n\n\nJanitor is a Kirby CMS Plugin for running commands.\n\n- It is a Panel Button!\n- It has commands built-in for cleaning the cache, sessions, create zip-backup, pre-generate thumbs, open URLs, refresh the current Panel page and more.\n- You can define your own commands (call API hooks, play a game, hack a server, ...)\n- It can be triggered in your frontend code, with the official kirby CLI and a CRON.\n\n## Install\n\nYou have to use composer to install both the plugin and the CLI locally into your project:\n\n```bash\ncomposer require getkirby/cli bnomei/kirby-janitor\n```\n\n\u003e [!WARNING]\n\u003e You need to install the CLI with composer into your project and not use the global version. Since Janitor depends on the CLI to be available, installing only the janitor plugin via submodules or via ZIP is NOT supported.\n\n## Setup\n\n### CLI Command\n\nIn any blueprint create a janitor field with your command, browse to that page in panel and press the button.\n\n**site/blueprints/page/default.yml**\n```yml\ntitle: Default Page\nfields:\n  call_my_command:\n    type: janitor\n    command: 'example --data test'\n    label: Call `Example` Command\n```\n\nJanitor will automatically fill in the current model.\n\n- The `--model` argument will have the UUID or ID of the current model. You can use `janitor()-\u003emodel($cli-\u003earg('model'))` to get the object.\n- But if for example you press the panel button on a page you will have `--page` argument set to the UUID or ID of that page. Use `$cli-\u003ekirby()-\u003epage($cli-\u003earg('page'))` to get the object.\n- If you call it on a file view then `--file` arg will be set. Use `$cli-\u003ekirby()-\u003efile($cli-\u003earg('file'))` to get the object.\n- On a panel user view... `--user`. Use `$cli-\u003ekirby()-\u003euser($cli-\u003earg('user'))` to get the object.\n- And lastly `--site` (boolean) will be automatically set when you had the button in the `site/blueprints/site.yml` blueprint. `if($cli-\u003earg('site')) { $cli-\u003ekirby()-\u003esite(); }`\n\nCreate a Kirby CLI command [via a custom plugin](https://getkirby.com/docs/reference/plugins/extensions/commands) or put them into `site/commands`.\n\n**site/commands/example.php**\n```php\n\u003c?php\n\nuse Bnomei\\Janitor;\nuse Kirby\\CLI\\CLI;\n\nreturn [\n    'description' =\u003e 'Example',\n    'args' =\u003e [] + Janitor::ARGS, // page, file, user, site, data, model\n    'command' =\u003e static function (CLI $cli): void {\n        $page = page($cli-\u003earg('page'));\n\n        // output for the command line\n        $cli-\u003esuccess(\n            $page-\u003etitle() . ' ' . $cli-\u003earg('data')\n        );\n\n        // output for janitor\n        janitor()-\u003edata($cli-\u003earg('command'), [\n            'status' =\u003e 200,\n            'message' =\u003e $page-\u003etitle() . ' ' . $cli-\u003earg('data'),\n        ]);\n    }\n];\n\n```\n\n### View Buttons\n\nYou can also use Janitor to create custom [view buttons](https://getkirby.com/releases/5/view-buttons#custom-vue-component).\n\n**site/blueprints/page/default.yml**\n```yml\nbuttons:\n  myCommand:\n    component: k-janitor-view-button\n    props:\n      command: whistle\n      label: Whistle\n      icon: audio\n  open: true\n  preview: true\n  settings: true\n```\n\n### Callback\n\nInstead of using a command you can also create a callback in a custom plugin options or any config file.\n\n**site/config/config.php**\n```php\n\u003c?php\n\nreturn [\n    'example' =\u003e function ($model, $data = null) {\n        return [\n            'status' =\u003e 200,\n            'message' =\u003e $model-\u003etitle() . ' ' . $data,\n        ];\n    },\n    // ... other options\n];\n```\n\nThe Janitor plugin has a special command `janitor:job` that you can use to trigger your callback.\n\n**site/blueprints/page/default.yml**\n```yml\ntitle: Default Page\nfields:\n  call_my_command:\n    type: janitor\n    command: 'janitor:job --key example --data test'\n    label: Call `Example` Command\n```\n\nThe `$model` will match the model of whatever page, file, user or site object you pressed the button at.\n\n\u003e [!NOTE]\n\u003e Why just a single model variable instead of one each for page, file, user and site? For one reason to make it work directly with any existing version 2 callbacks you might have already created and secondly because this why it is very easy to get the model that triggered the callback.\n\n### Built in commands and examples\n\nThis plugin comes with a [few commands](https://github.com/bnomei/kirby-janitor/tree/master/commands) you might like to use yourself and some [example commands](https://github.com/bnomei/kirby-janitor/tree/master/tests/site/commands) used to showcase the various options the button has (like how to change the icon or open a URL in a new tab). Some commands can be used in both panel and terminal. Others are limited in their use to either one of them. In the terminal you can use `--help` argument to view the help for each command.\n\n- `janitor:backupzip`, creates a backup zip\n- `janitor:call`, calls a method on the current model with optional data parameter\n- `janitor:cleancontent`, removes fields from content file that are not defined in your blueprints\n- `janitor:clipboard`, copies a defined value to your clipboard\n- `janitor:download`, triggers a download of an URL\n- `janitor:flush`, flush a cache by providing its name (default: pages cache)\n- `janitor:job`, run a callback\n- `janitor:maintenance`, toggle maintenance mode\n- `janitor:open`, triggers opening of an URL in panel\n- `janitor:out`, sends a message to the CLI output stream\n- `janitor:pipe`, map input argument to output argument\n- `janitor:render`, render a certain page or all pages (to create thumb jobs)\n- `janitor:thumbs`, process thumb jobs of a certain page or all pages\n- `janitor:tinker`, run a REPL session in terminal\n- `janitor:trash`, removes an entry from given cache by key or page (default: pages cache)\n- `janitor:undertaker`, backups a page and its subpages to a zip. You need to manually trigger it with a [hook](https://github.com/bnomei/kirby-janitor/blob/master/tests/site/config/config.php).\n\nThe plugin will register these commands starting with `janitor:*` automatically - no copying required.\u003cbr\u003eBut if you want to re-use any of the other example provided you need to copy them to your `site/commands`-folder\n\n### Blueprint field options\n\nThe button you create with the `field: janitor` in your blueprint can be configured to do various things. Checkout the [example default.yml blueprint](https://github.com/bnomei/kirby-janitor/blob/master/tests/site/blueprints/pages/default.yml) to familiarize yourself with how to use it.\n\n- `autosave`, if `true` then save before pressing the button\n- `backgroundColor`, sets backgroundColor of button\n- `color`, sets text color of button\n- `confirm`, sets text for confirmation after clicking the button and before executing the command, can prevent the execution of the command if the user clicks `cancel` in the OS dialog\n- `command`, command like you would enter it in terminal, with [query language support](https://getkirby.com/docs/guide/blueprints/query-language) and page/file/user/site/data arguments\n- `cooldown`, time in milliseconds the message is flashed on the button (default: 2000)\n- `error`, set message on button to show on all **non-200**-status returns with query language support, also will print to `console.error()`\n- `headline`, set headline of the button, use `headline: \" \"` for better alignment with custom `width`s\n- `help`, set help of the button\n- `icon`, set the [icon](https://getkirby.com/docs/reference/panel/icons) of the button\n- `intab`, if `true` then use in combination with the `open`-option to open an URL in a new tab\n- `label`, set label of the button\n- `progress`, set message to show while the button waits for the response, with query language support\n- `success`, set message to show on all **200**-status returns, with query language support\n- `unsaved`, if `false` then disable the button if panel view has unsaved content\n\n### Janitor API options\n\nIn either the command or the callback you will be setting/returning data to the Janitor button via its api. Depending on what you return you can trigger various things to happen in the panel.\n\n- `backgroundColor`, see `backgroundColor`-field option\n- `clipboard`, string to copy to clipboard\n- `color`, see `color`-field option\n- `download`, URL to start downloading\n- `error`, see `error`-field option, print to `console.error()`\n- `warn`, print to `console.warn()`\n- `log`, print to `console.log()`\n- `headline`, see `help`-field option\n- `help`, see `help`-field option\n- `icon`, see `icon`-field option\n- `label`, see `label`-field option\n- `message`, see `message`-field option\n- `notification`, array of method and message, like `['success', 'Deployed!']`\n- `open`, URL to open, use with `intab`-field option to open in a new tab\n- `reload`, if `true` will reload panel view once api call is received\n- `success`, see `success`-field option\n- `status`, return `200` for a **green** button flash, anything else for a **red** flash\n\n### Examples\n\nAgain... check out the [built-in commands](https://github.com/bnomei/kirby-janitor/tree/master/commands) and plugin [example commands](https://github.com/bnomei/kirby-janitor/tree/master/tests/site/commands) to learn how to use the field and api options yourself.\n\n```yml\ntest_ping:\n  type: janitor\n  command: 'ping' # see tests/site/commands/ping.php\n  label: Ping\n  progress: ....\n  success: Pong\n  error: BAMM\n\njanitor_open:\n  type: janitor\n  command: 'janitor:open --data {{ user.panel.url }}'\n  intab: true\n  label: Open current user URL in new tab\n  icon: open\n  # the open command will forward the `data` arg to `open` and open that URL\n\njanitor_clipboarddata:\n  type: janitor\n  command: 'janitor:clipboard --data {{ page.title }}'\n  label: 'Copy \"{{ page.title }}\" to Clipboard'\n  progress: Copied!\n  icon: copy\n  # the clipboard command will forward the `data` arg to `clipboard` and copy that\n\njanitor_download:\n  type: janitor\n  command: 'janitor:download --data {{ site.index.files.first.url }}'\n  label: Download File Example\n  icon: download\n  # the download command will forward the `data` arg to `download` and start downloading that\n\njanitor_backupzip:\n  type: janitor\n  command: 'janitor:backupzip'\n  cooldown: 5000\n  label: Generate Backup ZIP\n  icon: archive\n\njanitor_render:\n  type: janitor\n  command: 'janitor:render'\n  label: Render pages to create missing thumb jobs\n\njanitor_thumbssite:\n  type: janitor\n  command: 'janitor:thumbs --site'\n  label: Generate thumbs from existing thumb jobs (full site)\n\njanitor_callWithData:\n  label: Call method on model with Data\n  type: janitor\n  command: 'janitor:call --method repeatAfterMe --data {{ user.id }}'\n```\n\nIf you want you can also call any of [the core shipping with the CLI](https://github.com/getkirby/cli#available-core-commands) like `clear:cache`.\n\nKeep in mind that the Janitor panel button and webhooks will append the `--quiet` option on all commands automatically to silence outputs to the non-existing CLI. But if you use `janitor()-\u003ecommand()` you will have to append `--quiet` to your command yourself.\n\n### Running commands in your code\n\nYou can run any command in you own code as well like in a model, template, controller or hook. Since commands do not return data directly you need to retrieve data stored for Janitor using a helper `janitor()-\u003edata($commandName)`.\n\n#### Get data returned from a command\n```php\nKirby\\CLI\\CLI::command('whistle'); // tests/site/commands/whistle.php\nvar_dump(janitor()-\u003edata('whistle'));\n```\n\n#### Create and download a backup\n\n**site/config/config.php**\n```php\n\u003c?php\n\nreturn [\n    // ATTENTION: choose a different secret!\n    'bnomei.janitor.secret' =\u003e 'e9fe51f94eadabf54',\n\n    'routes' =\u003e [\n        // custom webhook endpoint reusing janitors secret\n        [\n            'pattern' =\u003e 'webhook/(:any)/(:any)',\n            'action' =\u003e function($secret, $command) {\n                if ($secret != janitor()-\u003eoption('secret')) {\n                    \\Kirby\\Http\\Header::status(401);\n                    die();\n                }\n\n                if ($command === 'backup') {\n                    janitor()-\u003ecommand('janitor:backupzip --quiet');\n                    $backup = janitor()-\u003edata('janitor:backupzip')['path'];\n                    if (F::exists($backup)) {\n                        \\Kirby\\Http\\Header::download([\n                            'mime' =\u003e F::mime($backup),\n                            'name' =\u003e F::filename($backup),\n                        ]);\n                        readfile($backup);\n                        die(); // needed to make content type work\n                    }\n                }\n            }\n        ],\n    ],\n];\n```\n\n#### Calling a command with parameters\n\nSupplying parameter to the core CLI functions can be a bit tricky since you need to separate argument key and argument values. It seems easy with one but gets a bit tedious with a dynamic list of parameters and if values contain `space`-chars or quotes. But fret not – Janitor has a helper for that as well.\n\n```php\nKirby\\CLI\\CLI::command('uuid', '--page', 'some/page'); // tests/site/commands/uuid.php\n\njanitor()-\u003ecommand('uuid --page some/page');\n\nvar_dump(janitor()-\u003edata('uuid')['message']); // page://82h2nkal12ls\n```\n\n\u003e Remember that using the `janitor()-\u003ecommand($string)`-helper you can call any of your own commands and the core commands as well, not just the ones defined by Janitor.\n\nIf you want to work with command strings yourself you can use the following static helper method.\n\n```php\nlist($name, $args) = Bnomei\\Janitor::parseCommand('uuid --page page://82h2nkal12ls');\nKirby\\CLI\\CLI::command($name, ...$args);\n```\n\n\n### Webhook with secret\n\nYou can not call Janitors api unauthenticated. You either need to use the panel button or you can set a `secret` in your `site/config/config.php` file and call the janitor api URL with that secret.\n\n**site/config/config.php**\n```php\n\u003c?php\n\nreturn [\n  'bnomei.janitor.secret' =\u003e 'e9fe51f94eadabf54', // whatever string you like\n  //... other options\n];\n```\n\nYou could also use a callback if you want to store the secret in a `.env` file and have it loaded by my [dotenv plugin](https://github.com/bnomei/kirby3-dotenv).\n\n**/.env**\n```dotenv\n# whatever key and value you like\nMY_JANITOR_SECRET=e9fe51f94eadabf54\n```\n\n**site/config/config.php**\n```php\n\u003c?php\n\nreturn [\n  'bnomei.janitor.secret' =\u003e fn() =\u003e env('MY_JANITOR_SECRET'),\n  //... other options\n];\n```\n\n#### example URL\n```\nhttps://dev.bnomei.com/plugin-janitor/e9fe51f94eadabf54/janitor%3Abackupzip\n```\n\n#### example URL with urlencoded arguments\n```\nhttp://dev.bnomei.com/plugin-janitor/e9fe51f94eadabf54/janitor%3Athumbs%20--site\n```\n### CRON\n\n#### Webhook with wget or curl\n\nYou can also use the secret to trigger a job using wget or curl.\n\n```php\nwget https://dev.bnomei.com/plugin-janitor/e9fe51f94eadabf54/janitor%3Abackupzip --delete-after\n// or\ncurl -s https://dev.bnomei.com/plugin-janitor/e9fe51f94eadabf54/janitor%3Abackupzip \u003e /dev/null\n```\n\nAre you having issues with PHP bin and cron? [read this](https://github.com/bnomei/kirby-janitor/issues/105).\n\n#### Kirby CLI (installed with composer)\n\nin your cron scheduler add the following command\n\n```\ncd /path/to/my/kirby/project/root \u0026\u0026 vendor/bin/kirby janitor:backupzip\n```\n\n## Maintenance Mode\n\nYou can toggle maintenance mode with a janitor button like this:\n\n```yml\n  janitor_maintenance:\n    type: janitor\n    command: 'janitor:maintenance --user {{ user.uuid }}'\n    cooldown: 5000\n    label: 'Maintenance: {{ site.isUnderMaintenance.ecco(\"DOWN\",\"UP\") }}'\n    icon: '{{ site.isUnderMaintenance.ecco(\"cancel\",\"circle\") }}'\n```\n\nIf you need to add a custom check when maintenance mode is enforced you can do this by providing a callback for the `bnomei.janitor.maintenance.check` option.\n\n**site/config/config.php**\n```php\n\u003c?php\n\nreturn [\n    // return `true` for maintenance and `false` to skip maintenance\n    'bnomei.janitor.maintenance.check' =\u003e function(): bool {\n        // example: block unless it is a logged-in user and it has the admin role\n        return kirby()-\u003eusers()-\u003ecurrent()?-\u003erole()-\u003eisAdmin() !== true;\n    },\n    // other options...\n];\n```\n\nYou can also overwrite the maintenance snippet if you create your own and store it as `site/snippets/maintenance.php`.\n\n## Tinker(well), REPL and Debugging\n\nYou can use the `kirby janitor:tinker` command to start a REPL session in the terminal. This is a great way to test code snippets, debug and explore your Kirby installation. Another alternative would be using the [Tinkerwell App](https://tinkerwell.app/) which has built-in support for Kirby as long as it can find the `./kirby/bootstrap.php` file via the matching [driver](https://github.com/beyondcode/tinkerwell/blob/58254e11a6aad428eefd63b1ae624b0568414227/src/Drivers/KirbyTinkerwellDriver.php#L14). \n\n## Dependencies\n\n- [Kirby CLI](https://github.com/getkirby/cli)\n- [CLImate](https://github.com/thephpleague/climate)\n- [Symfony Finder](https://symfony.com/doc/current/components/finder.html)\n\n## Disclaimer\n\nThis plugin is provided \"as is\" with no guarantee. Use it at your own risk and always test it yourself before using it in a production environment. If you find any issues, please [create a new issue](https://github.com/bnomei/kirby-janitor/issues/new).\n\n## License\n\n[MIT](https://opensource.org/licenses/MIT)\n\nIt is discouraged to use this plugin in any project that promotes racism, sexism, homophobia, animal abuse, violence or any other form of hate speech.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnomei%2Fkirby-janitor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbnomei%2Fkirby-janitor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbnomei%2Fkirby-janitor/lists"}