# opcache-gui: a browser front end for the Zend OPcache of one server

> opcache-gui is a PHP package that renders Zend OPcache statistics, settings and cached files in a React interface you can drop on a server as a single index.php. It gives you cache invalidation and a full cache reset from the browser, which is exactly why it should not sit on a public URL.

**amnuts/opcache-gui** — A clean, effective and responsive interface for Zend OPcache

- Repository: https://github.com/amnuts/opcache-gui
- Stars: 1,367 · Forks: 197
- Language: PHP
- License: not declared
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/amnuts-opcache-gui

## It answers the question every PHP deploy eventually asks

PHP's OPcache keeps compiled bytecode in memory, and when something does not behave after a deploy, the first question is whether the cache is holding a stale copy. opcache-gui answers that in a browser instead of in a log file. It shows the host and platform you are on, the OPcache version in use, when the cache was last reset, the available functions and directives with links to the php.net manual, and the core statistics such as hit count, memory used, free memory and wasted memory.

The audience is an engineer with a shell on a server who wants a picture rather than a number. It is deliberately a small package: one index.php file, a src/ directory for the PHP side, and a build/ directory holding the compiled front end.

The interface needs a modern browser, since it is built with ReactJS and Axios, and it needs a minimum of PHP 7.1. Both requirements are stated plainly in the project description, which is the sort of detail that usually goes missing and later becomes your afternoon.

## One file on the web server, or a Composer dependency

There are two ways in, and the quickest is the crudest. Clone the repository or copy the index.php file to a location your web server can load, then point a browser at it, for example https://www.example.com/opcache/index.php. That single file is the whole application, front end included.

The second way is Composer, which pulls the package into a project and gives you the namespaced class rather than a script you copy around.

```bash
composer require amnuts/opcache-gui
```

The namespace is Amnuts\Opcache and the class you use is \Amnuts\Opcache\Service, so a controller or a routing entry point can build the interface with the options array you pass in.

```php
<?php

use Amnuts\Opcache\Service;

// assuming location of: /var/www/html/opcache.php
require_once __DIR__ . '/../vendor/autoload.php';

// specify any options you want different from the defaults, if any
$options = [/* ... */];

// setup the class and pass in your options, if you have any
$opcache = (new Service($options))->handle();
```

You can also include the shipped entry point directly, which gives the same result as copying index.php by hand, and the project notes a symlink as another route if you would rather not copy files at all.

```php
<?php

// assuming location of: /var/www/html/opcache.php

require_once __DIR__ . '/../vendor/amnuts/opcache-gui/index.php';
```

## The options array is the whole configuration surface

Everything is controlled by one array, and the defaults are the specification. The options decide whether the files tab appears (allow_filelist), whether a link to invalidate individual files is offered (allow_invalidate), whether the whole cache can be reset (allow_reset), and whether real-time updates can be switched on and off (allow_realtime). refresh_time sets how often the data refreshes in seconds, defaulting to 5.

Presentation options sit alongside them: size_precision for the digits after the decimal point, size_space for whether a size reads as 1MB or 1 MB, charts to switch between a gauge and plain numbers, debounce_rate in milliseconds for the keyup event that drives filtering, and per_page for the file list, where false means no pagination. The highlight array controls which of the memory, hits, keys and jit buffer figures are shown, and datetime_format fixes the timestamp format.

Two details deserve attention. The cookie that stores your view state is named opcachegui and lives for 365 days by default, which is a long time for a cookie that identifies a browser to an admin page. And overriding is incremental, so passing only the keys you care about leaves the rest at their defaults.

```php
$opcache = (new Service([
    'refresh_time' => 2,
    'allow_reset' => false
]))->handle();
```

That last example is the one to copy into production. Turning allow_reset off removes the button that clears the entire cache, which is a foot-gun you do not want one click away.

## The cached files tab is where the real work happens

The files tab lists every file currently in the cache with its associated statistics. You can filter the results to find a particular script, change the sort order, invalidate the cache for an individual file, or invalidate every file matching your current search, which is the feature that makes this more than a status page. A misbehaving file can be cleared on its own instead of flushing the cache for the whole application.

Two options shape the experience. allow_filelist set to false suppresses the file list altogether, which is the setting to use if the interface is exposed more widely than you would like. per_page sets the page size, with 200 as the default, and false turns pagination off so a large cache renders in one page.

Filtering is not a server round trip on every keystroke, because debounce_rate holds the keyup event back for 250 milliseconds before it is sent. That is a small thing, and it is the difference between an interface that feels heavy on a cache with thousands of entries and one that does not.

## Renaming every tab with a language pack

The interface text lives in a JSON structure supplied through the language_pack option, and the default is null, which means the built-in English strings. Set it to a JSON document and the tab labels and button captions are replaced, which is how you would localise the page for a team that does not read English.

The project demonstrates this with a deliberately silly pirate pack, and the example is useful precisely because it shows the full set of keys you have to supply: Overview, Cached, Ignored, Preloaded, Reset cache, Enable real-time update and Disable real-time update.

```php
$opcache = (new Service([
    'language_pack' => <<<EOJSON
{
    "Overview": "Crows nest",
    "Cached": "Thar Booty",
    "Ignored": "The Black Spot",
    "Preloaded": "Ready an' waitin', Cap'n",
    "Reset cache": "Be gone, yer scurvy dogs!",
    "Enable real-time update": "Keep a weathered eye",
    "Disable real-time update": "Avert yer eyes, sea dog!"
}
EOJSON
]))->handle();
```

A partial pack is the interesting case. Supplying only the strings you care about, for example a translated Reset cache label, leaves the rest in English, so localisation does not have to be all or nothing.

## A reset button with no documented access control

Here is the part worth reading twice before you deploy this. The interface can invalidate files and, with allow_reset enabled, reset the entire cache. The overview also reports the host, the platform, the OPcache version and the last reset time.

The documentation does not describe any authentication, authorisation or IP restriction for the page. It describes where to put the file, which options to pass, and what each tab shows, and it stops there. So the security model is whatever your web server provides, and if index.php lands on a public URL, then anyone who finds it can look at your file paths and can clear the cache on demand.

That is why the safe configuration is to set allow_reset and allow_invalidate to false, and allow_filelist to false, on any copy that is reachable from outside your network. The remaining value is the read-only view of statistics, which is the part that was probably what you wanted in the first place.

The alternative to this package is to read the OPcache status functions yourself and render a page of your own. You get no shipped interface, no file list, and no invalidation links, and in exchange you control authentication and output completely. For a one-off diagnostic on a server you already trust, that is often the smaller decision.

## The front end is a compiled artifact and the test script is a stub

The React interface is not hand-edited in the repository. The package.json scripts compile build/_frontend/interface.jsx into build/interface.js with Babel and the React preset, and compile build/_frontend/interface.scss into build/interface.css with Sass in compressed mode. The project also depends on Axios for the requests that back the real-time updates, and the front-end build tooling is listed under devDependencies alongside Babel, Sass and the class properties transform plugin.

One line in that same package.json is worth flagging. The test script is a placeholder that prints Error: no test specified and exits with a failure, so there is no JavaScript test suite to run. The rest of the build is real, but a green build tells you nothing about behaviour.

For a project like this that is a reasonable trade. The bulk of the logic lives in PHP, where the interface is a thin layer over the OPcache status data, and the front end is a presentational piece that is regenerated from source when the design changes.

## MIT terms, and a release cadence that has slowed

The project states an MIT licence in the README and in the package.json metadata, which means you can read it, modify it and ship your own copy without copyleft obligations. That matters for the drop-a-single-file deployment model, because plenty of teams patch the interface in place rather than tracking upstream.

The release history is uneven, and the dates tell the story better than any claim about maintenance. Version 3.6.1 shipped on 2026-05-05, before it came 3.6.0 on 2025-07-28, and before that 3.5.5 on 2024-06-23. The last push to the repository was on 2026-09-06, so work continues, but the gap between public releases is measured in months rather than weeks.

For a page you drop on a server, that is a manageable rhythm. The cost of being behind is low, because the interface reads whatever the running PHP version reports, and the risk is really about a newer PHP release changing how the underlying status data is exposed.

## Conclusion

opcache-gui is worth installing on a single server you control, especially when a stale opcode cache is the suspected cause of a deploy that did not take effect, and the per-file invalidation and search-driven invalidation are the features that justify it over reading the status functions yourself. It is the wrong choice for shared hosting where you cannot restrict the URL, and for teams that need monitoring over time, since the interface is a page rather than an agent. Verify three things first: that your PHP is 7.1 or newer, that the allow_invalidate and allow_reset options are set to false in any environment reachable from outside your network, and that index.php is served by the same web server process whose OPcache you actually want to inspect.

## FAQ

### How do I install opcache-gui on my server?

Copy the index.php file from the repository to a location your web server can serve and open it in a browser, or install the package with composer require amnuts/opcache-gui and use the \Amnuts\Opcache\Service class from your autoloader. The project also suggests symlinking the vendored index.php into your web root.

### What PHP version does opcache-gui need?

A minimum of PHP 7.1. The interface itself is built with ReactJS and Axios and is meant for modern browsers, so the browser requirement is separate from the PHP version.

### Can I stop opcache-gui from resetting the cache?

Yes. The allow_reset option controls whether the option to reset the whole cache is offered, and allow_invalidate controls the link to invalidate individual files. Passing 'allow_reset' => false to the Service class removes the reset button, and setting allow_filelist to false suppresses the file list entirely.

### How do I change the text of the tabs in opcache-gui?

Pass a JSON structure through the language_pack option, where the default is null for the built-in English strings. The example in the documentation supplies keys such as Overview, Cached, Ignored, Preloaded and Reset cache, and you can translate only the labels you care about.

### How often does the opcache-gui page refresh itself?

The refresh_time option sets the interval in seconds and defaults to 5. Real-time updates are a separate switch controlled by allow_realtime, which lets the user turn the option to enable or disable real-time updates on and off.

## Sources

- [amnuts/opcache-gui on GitHub](https://github.com/amnuts/opcache-gui)
- [Issues](https://github.com/amnuts/opcache-gui/issues)
- [README](https://github.com/amnuts/opcache-gui/blob/master/README.md)
- [Releases](https://github.com/amnuts/opcache-gui/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/amnuts-opcache-gui
