{"id":17046623,"url":"https://github.com/sebobo/shel.neos.terminal","last_synced_at":"2026-02-27T08:58:06.593Z","repository":{"id":42432229,"uuid":"334907420","full_name":"Sebobo/Shel.Neos.Terminal","owner":"Sebobo","description":"Terminal emulator for interacting with Neos CMS","archived":false,"fork":false,"pushed_at":"2025-04-04T09:35:47.000Z","size":2675,"stargazers_count":14,"open_issues_count":6,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-02T21:18:30.719Z","etag":null,"topics":["hacktoberfest","neoscms","terminal-emulator"],"latest_commit_sha":null,"homepage":"","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/Sebobo.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","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},"funding":{"patreon":"shelzle","github":"sebobo"}},"created_at":"2021-02-01T10:09:18.000Z","updated_at":"2025-04-04T09:35:23.000Z","dependencies_parsed_at":"2024-01-08T14:56:05.079Z","dependency_job_id":"44b42776-8673-4a66-876f-ba0ee228d9aa","html_url":"https://github.com/Sebobo/Shel.Neos.Terminal","commit_stats":{"total_commits":110,"total_committers":3,"mean_commits":"36.666666666666664","dds":"0.036363636363636376","last_synced_commit":"e38f1016d373ebd74a506c0563d00c0ddd963976"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sebobo%2FShel.Neos.Terminal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sebobo%2FShel.Neos.Terminal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sebobo%2FShel.Neos.Terminal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sebobo%2FShel.Neos.Terminal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sebobo","download_url":"https://codeload.github.com/Sebobo/Shel.Neos.Terminal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253186469,"owners_count":21868062,"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","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":["hacktoberfest","neoscms","terminal-emulator"],"created_at":"2024-10-14T09:46:55.596Z","updated_at":"2025-10-25T12:08:51.825Z","avatar_url":"https://github.com/Sebobo.png","language":"PHP","funding_links":["https://patreon.com/shelzle","https://github.com/sponsors/sebobo","https://www.patreon.com/shelzle"],"categories":[],"sub_categories":[],"readme":"# Neos CMS terminal for running Eel expressions and other commands in the UI\n\n[![Tests](https://github.com/Sebobo/Shel.Neos.Terminal/actions/workflows/tests.yml/badge.svg)](https://github.com/Sebobo/Shel.Neos.Terminal/actions/workflows/tests.yml)\n\nThis package provides a Terminal emulator plugin for the [Neos CMS](https://www.neos.io) UI.\nSeveral commands are provided to save time during development \u0026 debugging of Neos CMS projects.\n\nAll commands and their output are also automatically available in the browser dev console\nas `NeosTerminal` - for easier handling of JSON results and persistent history. \n\nIt uses the great [terminal component](https://github.com/linuswillner/react-console-emulator) by [Linus Willner](https://github.com/linuswillner).\n\n**Quick overview:**\n              \n* Run commands via the Neos UI or in the browser console\n  * Evaluate Eel expressions on the currently selected page \u0026 content\n  * Search for nodes by their properties\n  * Flush caches\n  * Repair nodes\n* Autocompletion for command names  \n* Open Terminal via `t+t` shortcut  \n* Limit commands to backend roles\n* Create your own commands and provide them in your own packages\n* Full support for the [Shel.Neos.CommandBar](https://github.com/Sebobo/Shel.Neos.CommandBar)\n\n## How it looks\n\nWatch the [video](https://vimeo.com/manage/videos/538570712)\n\n![Terminal example in the Neos CMS backend](Documentation/shel-neos-terminal-example.jpg)\n\n## Installation\n\nRun the following command in your Neos project:\n\n```shell\ncomposer require shel/neos-terminal\n```\n\n### Supported Neos versions\n\nDue to required React features, the Terminal UI integration is only available \nfor more recent Neos versions which provide React \u003e= 16.8.\nBut the commands are still registered and available via the `NeosTerminal` global \nwindow object even when the React version is too old.\n\n| Neos version | Terminal         |\n|--------------| ---------------- |\n| 4.3          | Commands are only available via the browser console |\n| 5.2 - 5.3    | Full support     |\n| 7.0+         | Full support     |\n| 8.0+         | Full support     |\n| 9.0+         | Full support     |\n\n## Usage\n\nThere are three ways to access the terminal functionality:\n\n1. Open the terminal by clicking on the terminal icon in the top menu bar in the Neos backend.\n2. Open the terminal with the `t t` hotkey (configured via the Neos hotkey API in the `Settings.yaml`).\n3. Access the terminal commands from the browser dev console via the global `NeosTerminal` object.\n\nNow you can run any of the provided commands, or your own.\n\n## Included commands\n\nAvailable default commands:\n\n* `eel` - Eel expression parser\n* `flushCache` - Flush one or all Neos/Flow caches\n* `help` - Show command list and their arguments\n* `clear` - Clear terminal\n* `search` - Search for nodes by their properties\n* `nodeRepair` - Repair nodes\n\nYou can add [custom commands](#adding-your-own-commands). \n\n### Eel evaluator\n\nThe `eel` command allows you to run any Eel expression.\n\nYou can run simple expressions:\n\n```\neel 5+2\n```                                  \n\nRead a specific setting:\n\n```\neel Configuration.setting('Neos.Flow.core.context')\n```                               \n\nGet a list of all Eel helpers:\n\n```\neel Configuration.setting('Neos.Fusion.defaultContext')\n```\n\nOr more complex ones. The following call will return the labels of all subpages of your homepage: \n\n```\neel Array.map(q(site).children().get(), page =\u003e page.label)\n```\n\nBy default, the current `site`, `documentNode` and the currently selected `node` are\navailable in your expression context.\n\n*Note:* The command will run some conversions on the result:\n\n* If the result is a node or a list of nodes, each node will be replaced\nwith a list of their `properties`.\n* Properties that are objects are replaced with their classname.\n\nThis will be optimised in future releases and should improve the readability of the output.\n\n### Flush caches\n\nThe `flushCache` command allows you to flush all caches or a single cache.\n\nE.g. the following call will flush the Fusion rendering cache:\n\n```\nflushCache Neos_Fusion_Content\n```\n\nIf the cache identifier is omitted, all caches are flushed.\n\nPlease use this command only when absolutely necessary.\nCaching issues can be fixed in the implementation.\n\n### Repair nodes\n\nThe `nodeRepair` command allows you to repair nodes by their nodetype. \nIt uses the same plugins and methods as the `./flow node:repair` CLI command.\n\nE.g. the following call will remove undefined properties from the Neos example text nodes:\n\n```\nnodeRepair removeUndefinedProperties Neos.NodeTypes:Text\n```\n\nYou can also do a dry run by adding the `-d` option and see what the method would do:\n\n```\nnodeRepair --dryRun removeUndefinedProperties Neos.NodeTypes:Text\n```\n\nTo filter by workspace you can add the name of the workspace:\n\n```\nnodeRepair --workspace user-admin removeUndefinedProperties Neos.NodeTypes:Text\n```\n\n**Warning:** Some repair methods would ask you for confirmation when you run them via CLI. \nCurrently they would execute without asking for confirmation.\n\n## Configuration\n\n### Enabling the plugin in Production context \n\nBy default, the plugin is only loaded in *Development* context.\nIf you want to have it active in *Production*, you have to override the setting in your `Settings.yaml`:\n\n```yaml\nNeos:\n  Neos:\n    Ui:\n      frontendConfiguration:\n        'Shel.Neos.Terminal:Terminal':\n          enabled: true\n```\n\n### Security\n\nExecuting commands in the Neos backend opens up a possible security risk.\n\nTherefore, if you use this plugin in production, make sure only a limited\nnumber of users have access to it.\n\nWhen creating your own commands, keep in mind to make sure nothing bad can happen to your\ndatabase or other systems.\n\nExample: If you have your own Eel helper that can send API requests to another system \nwith full write access, this could be abused by someone if a backend user with\nenough privileges is hacked.\n\n### Theming\n\nHave a look at the [Settings.yaml](Configuration/Settings.yaml) in this package and its `frontendConfiguration`.\nIt allows you to override the theme with your own.\n\n### Command policies\n\nBy default, any *Administrator* has full access to all existing and added commands.\n\nAdditionally, the role `Shel.Neos.Terminal:TerminalUser` exists which by default can only run the `eel` command.\nYou can add more privileges to this role to allow more commands and assign it to users or as a `parentRole` for other roles.\nSee [Policy.yaml](Configuration/Policy.yaml) in this package for examples.\n\n## Adding your own commands\n\nAdding your commands takes just a few steps (depending on what you plan to do).\n\nCreate a new class named `MyCommand` and implement the `TerminalCommandControllerPluginInterface` from \nthis package or inherit from `AbstractTerminalCommand`. \nAs soon as you implemented all required methods, you are good to go!\n\nAs an example, you can create a command to show the joke of the day with the following class.\nJust adapt the namespace depending on your own package key.\n\n```php\n\u003c?php\ndeclare(strict_types=1);\n\nnamespace Vendor\\Package\\Command;\n\nuse Neos\\Flow\\Http\\Client\\Browser;\nuse Neos\\Flow\\Http\\Client\\CurlEngine;\nuse Shel\\Neos\\Terminal\\Domain\\CommandContext;\nuse Shel\\Neos\\Terminal\\Domain\\CommandInvocationResult;\nuse Shel\\Neos\\Terminal\\Command\\TerminalCommandInterface;\n\nclass JokeCommand implements TerminalCommandInterface\n{           \n\n    public static function getCommandName(): string\n    {\n        return 'jod';\n    }\n\n    public static function getCommandDescription(): string\n    {\n        return 'Joke of the day';\n    }\n\n    public static function getCommandUsage(): string\n    {\n        return 'jod [\u003cstring\u003e]';\n    }\n\n    public function invokeCommand(string $argument, CommandContext $commandContext): CommandInvocationResult\n    {\n        $browser = new Browser();\n        $browser-\u003esetRequestEngine(new CurlEngine());\n        $jokeResponse = json_decode($browser-\u003erequest('https://api.jokes.one/jod')-\u003egetBody()-\u003egetContents());\n        $joke = $jokeResponse-\u003econtents-\u003ejokes[0]-\u003ejoke;\n\n        $result = $joke-\u003etitle . ': ' . $joke-\u003etext;\n\n        return new CommandInvocationResult(true, $result);\n    }\n}\n```\n\nDid you create awesome commands that could be helpful to others?\nSend a link to a [gist](https://gist.github.com) containing the PHP class or a link to your repo, and we can add it to the docs.\n\n### Providing feedback to Neos UI\n\nThe Neos UI supports `ServerFeedbacks`. Those are commonly used to trigger reload of\nnodes and documents or changing the state of nodes after manipulating them.\n\nYou can add those feedbacks to the `CommandInvocationResult`.\n\nAn example of a invocation method which triggers a reload of the Neos UI guestframe \nafter a node has been updated execution would look like this:\n\n```php\n  public function invokeCommand(string $argument, CommandContext $commandContext): CommandInvocationResult\n    {\n        $newNodeTitle = $argument;\n        $commandContext-\u003egetFocusedNode()-\u003esetProperty('title', $newNodeTitle);    \n        $result = 'I updated the node title';\n        $feedback = [\n            new \\Neos\\Neos\\Ui\\Domain\\Model\\Feedback\\Operations\\ReloadDocument()        \n        ];\n\n        return new CommandInvocationResult(true, $result, $feedback);\n    }\n```\n\nIf you have a Neos UI plugin that has its own registered feedbacks you can trigger them too.\n\n### Providing commands in other packages\n\nIf you have a package that provides a command, you should check whether the\nTerminal is installed in your code when defining the command.\n\nIn order to achieve that, you have to wrap the command class in a condition\nand use the fully qualified name to reference classes and interfaces from the \nTerminal package:\n\n```php\nif (interface_exists('Shel\\Neos\\Terminal\\Command\\TerminalCommandInterface', false)) {\n    class JokeCommand implements \\Shel\\Neos\\Terminal\\Command\\TerminalCommandInterface\n    {\n        public static function getCommandName(): string { ... }\n        public static function getCommandDescription(): string { ... }\n        public static function getCommandUsage(): string { ... }\n\n        public function invokeCommand(string $argument, \\Shel\\Neos\\Terminal\\Domain\\CommandContext $commandContext): \\Shel\\Neos\\Terminal\\Domain\\CommandInvocationResult {\n            ...\n\n            return new \\Shel\\Neos\\Terminal\\Domain\\CommandInvocationResult(true, $result);\n        }\n    }\n} else {\n    class JodCommand {}\n}\n```\n\n## Supporting this plugin / how to get rid of the sponsorship badge\n\nCreating and maintaining a plugin like this takes a lot of time.\nTherefore, I decided to add a small nagging badge to promote financial support for my work.\n\nThere are several ways to get rid of the little sponsoring badge in the terminal:\n\n1. Get in touch with [me](sponsor@helzle.it) for a direct sponsoring of 100€ (excl. VAT) / registration key\n2. Become a sponsor via [Github](https://github.com/sebobo) 20$+/month level\n3. Become a [patreon](https://www.patreon.com/shelzle) 20$+/month level\n\nIn return, you will feel much better, and you get a registration key you can put\ninto your settings which will disable the mentioned badge.\n\nThis will help me to further develop this and other plugins.\nOf course, I'll also do my best to react quickly to issues \u0026 questions.\n\nThere is a 4th way: Fork this repo and patch the verification check (or whatever other way you might find).\nSure you can do that. But you will receive bad karma, and you won't be helping the future of this plugin.\n\nIf the badge doesn't bother you, that's fine too. Keep it and enjoy the plugin :).\n\n## Contribute\n\nContributions are very welcome.\n\nFor code contributions, please create a fork and create a PR against the lowest maintained\nbranch of this repository (currently master).\n\n* Don't include any generated file in `/Resources/Public/` in your change.\n* Please provide a thorough explanation of your change and well-formed commit messages in your commits.\n\n### Run Tests\n\nMake sure you have the behat dependency required in your `composer.json` and run the following command:\n\n```console\nFLOW_CONTEXT=Testing bin/phpunit -c Build/BuildEssentials/PhpUnit/FunctionalTests.xml Packages/Plugins/Shel.Neos.Terminal/Tests/Functional\n```\n\n## License\n\nSee [License](LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebobo%2Fshel.neos.terminal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsebobo%2Fshel.neos.terminal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebobo%2Fshel.neos.terminal/lists"}