1
Upload manager.php to the folder you want to manage inside your web root
2
Open manager.php in your browser
3
Activate the free license issued for the current domain
4
Complete the one-time setup and choose your access password
Single-file installation. No Composer, npm or database is required. Manager-private state is stored automatically in .tyrusmanager outside the web root. Settings → Backups defaults to Auto: a silent same-origin check verifies whether a harmless temporary .bak probe can be read over HTTP. If it is blocked, backups stay beside the original file for maximum visibility; if it is exposed or the check cannot be completed, new backups use a mirrored path under private .tyrusmanager/backups. No backup catalog or tracking file is created, and existing sibling backups are not moved automatically.
Recommended layout
/public_html/
manager.php
app/
assets/
/private-or-parent-storage/
.tyrusmanager/
.manager_config
.activity_log
.login_attempts
.blocked_ips
backups/
ExamplePlace manager.php in /public_html/tools/ to manage that subtree without installing a framework or package manager.
Current licensing model: PHP File Manager is free and domain-locked. A free license already activated for a domain remains free for that domain under the terms accepted at activation.
Activation happens before the one-time setup. The downloadable build validates the license key against the current domain and stores the local license state in the private manager storage.
1
Open the downloaded manager.php on the domain where it will be used.
2
Enter the free license key issued for that domain and choose Activate License.
3
After validation succeeds, complete the setup wizard. Domain mismatch, suspended access and integrity failures remain explicit errors and are not bypassed.
Need a license key?
Get Tyrus Free. Email verification issues a free key bound to the domain you enter.
🛸
First Run: License Activation and Setup
On first launch, the licensed build validates the license for the current domain and then opens the one-time setup wizard. The setup screen keeps the cinematic dark interface with its animated SVG background and Tyrus branding.
① Access Password
- Minimum 15 characters
- Live password strength meter with length-first scoring
- Live password match indicator for the two password fields
- Suggest strong password generates a cryptographically secure password with Web Crypto
- Show or hide either password field
② Site URL
- Full site URL used by Preview and the site-cache purge action
- Inline URL validation
- Logo tip: capitalize each word in the domain to split the dynamic logo into separate color groups
③ Hosting Disk Space
- Preset buttons: 10 / 20 / 50 / 100 / 200 GB, plus a custom value
- Custom GB input with step controls
- Live conversion from GB to bytes
Language switcher: EN / RO / DK is available directly in the setup interface.
Setup submission: validation runs before the POST and the PRG flow prevents accidental form resubmission after redirects.
Configuration is stored as JSON in the private .tyrusmanager/.manager_config: bcrypt password hash, site URL, disk quota, setup date and language.
ExampleFor https://example.com, set the site URL exactly to the HTTPS origin and choose the disk quota that reflects the hosting account you are managing.
- Password verified against the bcrypt hash in the private
.tyrusmanager/.manager_config
- Change password from Settings → Security. The current password is re-verified with
password_verify(), attempts are rate-limited and the new bcrypt hash is written atomically to the private .tyrusmanager/.manager_config.
- Built-in password generator with a 16–64 character length control, Web Crypto randomness and a live length-first strength meter
- Brute-force protection: failed-login state is stored privately in
.tyrusmanager/.login_attempts
- Attempt 1: “Something doesn’t seem right here.”
- Attempt 2: “Interesting... do you continue?”
- Attempt 3: the IP is locked for 15 minutes and recorded in the private
.tyrusmanager/.blocked_ips.
- Session timeout: 30 minutes of inactivity, followed by an automatic return to login
- A warning bar appears 2 minutes before expiry with a live countdown
- The Extend control refreshes both the browser inactivity timer and the PHP session
- Mouse, keyboard, click and scroll activity refresh the browser inactivity counter
- Actions are timestamped in the private
.tyrusmanager/.activity_log; the IP address is recorded for LOGIN and LOGOUT only
ExampleThree failed login attempts lock the IP for 15 minutes; successful activity then uses the normal 30-minute inactivity timeout.
During a temporary IP lockout, the normal login page is replaced by a dedicated full-screen blocked-access canvas:
- Human face drawn procedurally using
ctx.bezierCurveTo and ctx.ellipse
- Eyes that follow the cursor in real time; pupils track mouse with clamped movement
- Random blinking with variable timing (randomized 180–480 frames)
- Periodic glitch effect;
getImageData/putImageData slice displacement + red tint
- CRT scanlines; horizontal lines at 4px intervals across the full canvas
- Radial vignette; dark edges closing in
- Custom cursor; default cursor hidden, replaced by small red dot
- Blocked: right-click, F12, Ctrl+U/I/S, Escape, scroll
- Messages with progressive fade-in (2s and 5s delays)
- Mouse leaving window: text color shifts + letter spacing expands
- Subtle breathing animation on the body element
ExampleWhen an IP is temporarily locked, the normal login form is replaced by the dedicated blocked-access screen until the lock expires.
Header Bar
- Dynamic logo; generated from the site URL. Each word colored differently. Capitalizing words in the URL = separate color per word
- Disk usage bar; visual bar showing used / total space with exact MiB/GiB values. Cache refreshed every 30 minutes
- Animated language switcher; pill slides smoothly between EN / RO / DK (cubic-bezier). Zero page reload; full UI re-renders via
applyUiLang(). On mobile: simple bordered buttons
- Header buttons: 📋 Log · ⚠ Errors · 🐘 PHP · ⌨ Shortcuts · 🔓/🔑 Root OFF/ON · ▶ Preview · 💾 Save · Logout
Toolbar
- Navigation; ← Back / → Forward with full history. Buttons disabled correctly at history boundaries
- Breadcrumb; clickable path segments for fast navigation
- Search files; filename search (max 100 results, case-insensitive, recursive)
- In files; toggle for content search panel
- New Folder / New File; modal with name input
Sidebar (Left Panel)
- Resizable; drag border (min 160px, max 520px). Persisted in localStorage + sessionStorage. Double-click = reset to 270px
- SERVER FILES; full file/folder tree with type icons
- Favorites ⭐; star/unstar any file or folder. Stored server-side. Inline SVG star icon in list
- Multiple selection; checkboxes + Select All. Bulk: ZIP · Download · Rename · Delete
- Bulk ZIP; create named archive from selected items
- Bulk Download; selected as ZIP, streamed directly to browser (built via
tempnam, deleted immediately after transfer)
- Multi-rename; batch rename wizard for selected files
- Upload zone; drag & drop or click. Conflict modal: Replace / Keep both (auto-numbered) / Cancel
- Content search input; search inside files from sidebar
Context Menu (Right-click / Long-press)
Edit · Preview · Open · Download · Rename · ZIP / Backup · Extract here · Permissions (chmod) · Delete · Add to Favorites / Remove from Favorites
ExampleSelect several log files in the sidebar, create a ZIP from the selection, then open another folder without losing the editor tabs already in use.
Built on CodeMirror 5. The editor bundle is embedded in manager.php and served by the same file, with no third-party runtime CDN.
203 Verified Filename Mappings
The bundled editor has 203 verified filename/content mappings resolving into 110 registered CodeMirror modes. The mapping layer includes extension mappings plus special filename/content cases.
C · C++ · C# · Java · Clojure · CMake · COBOL · CoffeeScript · Lisp · Crystal · CSS · Cypher · D · Dart · Diff/Patch · Django · Dockerfile · DTD · Elm · Erlang · Fortran · Assembly (GAS) · GFM · Gherkin · Go · Groovy · Handlebars · Haskell · HTML · HTTP · INI · JavaScript · TypeScript · JSON · JSON5 · JSONC · Jinja2 · JSX · TSX · Julia · Kotlin · LESS · LiveScript · Lua · Markdown · Mathematica · F#/OCaml · Modelica · Mscgen · NGINX · NSIS · N-Triples · Octave · Pascal · PEG.js · Perl · PHP · Pig · PowerShell · Properties · Protocol Buffers · Puppet · Python · Q/KDB+ · R · RPM Spec · reStructuredText · Ruby · Rust · SAS · SCSS · Sass · Scala · Scheme · Shell/Bash · Zsh · Fish · Ksh · Csh · Tcsh · Smalltalk · Smarty · SQL · MySQL · PostgreSQL · SQLite · LaTeX · Stylus · Swift · Tcl · Textile · TOML · Turtle (RDF) · Twig · Visual Basic · VBScript · Verilog · VHDL · Vue · WebIDL · XML · SVG · XQuery · YAML · Z80 Assembly
Special filename detection: .htaccess → shell · .env → shell · Dockerfile → dockerfile · Makefile → shell · .gitignore → shell · .babelrc / .eslintrc → JSON
Editor Features
- Bracket matching · Auto-close brackets · Active line highlight
- Code folding; foldGutter with 4 fold addons (brace, indent, XML, comment)
- Autocomplete; 5 hint engines (anyword, JS, CSS, HTML, XML). 400ms delay, min 3 chars, suppressed in strings/comments.
Ctrl+Space = manual
- Comment/uncomment;
Ctrl+/
- Font size control; A− / A+ in bottom bar
- Custom scrollbars; macOS-style (3px transparent border)
- Image preview; jpg, jpeg, png, gif, webp, svg, ico shown inline instead of editor
Tabs
- Multiple files open simultaneously
- Drag & drop reordering; left/right drop indicator with violet box-shadow
- Modified dot; visual indicator when file has unsaved changes
- Tab context menu (right-click): Close / Close Others / Close Unmodified / Close All
- Unsaved changes warning on close
Find & Replace
- Highlights all matches simultaneously with markText
- Active match in different color; counter display:
3 / 12
- Navigate: Enter (next) / Shift+Enter (previous)
- Replace One → / Replace All ⟳
ExampleOpening Dockerfile, composer.json, app.tsx and schema.sql selects the verified editor mode from filename/content mapping rather than relying on one generic text mode.
Opens as a side panel next to the editor via the 🔍 Analyze button. Supports: .php · .css · .scss · .less · .js · .ts · .jsx · .tsx
Visual line markers; issues marked directly in editor with color-coded classes. Click issue in panel → setCursor + scrollIntoView + 1.5s highlight flash on the line.
Minified file detection; by filename (.min.js, .bundle.js, etc.) or content (avg line >300 chars). Shows friendly message with “Analyze anyway →” button.
PHP Checks
| Check | Severity | Description |
| PHP Syntax | 🔴 error | php -l via shell_exec or token_get_all() ParseError fallback |
| var_dump / print_r left in code | 🟡 warning | Debug output not removed |
| $_SERVER['PHP_SELF'] without htmlspecialchars() | 🟡 warning | XSS vulnerability |
| die()/exit() with hardcoded string | 🟡 warning | Exposes server info in production |
| $_POST/$_GET/$_REQUEST without isset() | 🟡 warning | Context-aware; 3 lines up/down checked |
| PHP function typos (118 patterns) | 🔴 error | array_mpa → array_map, jsno_encode → json_encode, etc. |
| Duplicate function definitions | 🔴 error | With first-definition line reference |
| return outside any function | 🟡 warning | Structural brace-depth analysis |
| md5() for passwords | 🟡 warning | Only when near password/pass/pwd/hash context |
| TODO / FIXME / HACK | 🔵 info | Full comment text extracted |
CSS / SCSS / LESS Checks
| Check | Severity | Description |
| Invalid CSS property | 🟡 warning | 350+ valid properties validated |
| CSS property typo | 🔴 error | ~160 patterns, Levenshtein ≤ 3 suggestion |
| Invalid property value | 🔴 error | Value validated against known valid options per property |
| Duplicate property in block | 🟡 warning | Same property defined twice in same block |
| Double semicolon ;; | 🟡 warning | Common typo |
JS / TS Checks
| Check | Severity | Description |
| console.log left in code | 🔵 info | Remove before production |
| debugger; left in code | 🟡 warning | Stops execution in browser |
| typeof compared with == | 🟡 warning | Should use === |
| Invalid NaN comparison (=== NaN) | 🔴 error | Use Number.isNaN() or isNaN() |
| eslint-disable left in | 🔵 info | May be forgotten |
| TODO / FIXME / HACK | 🔵 info | Full comment text extracted |
Robustness: PCRE limits 10M, JIT disabled, try/catch Throwable wrap; never crashes. Compatible PHP 8.0 → 8.4.
ExampleAnalyze a PHP file containing a known typo pattern: the analyzer reports the matching issue, marks the line and lets you jump directly to it. The PHP typo engine contains 118 verified patterns.
Every save can preserve the previous version as .bak. The selected mode controls where new backups are written; existing backups remain usable when the mode changes.
- Auto — recommended: after login, a same-origin probe checks whether a harmless temporary
.bak can be read over HTTP. Protected servers use sibling backups; exposed or unverified servers use private storage.
- Next to original: writes
file.ext.bak beside file.ext. Use only when direct HTTP access to .bak files is blocked by the web server.
- Private storage: writes a mirrored backup path under private
.tyrusmanager/backups outside the public web root. No separate backup catalog is created.
ExampleEdit /public_html/app/config.php and save once. In sibling mode the previous version becomes /public_html/app/config.php.bak; in private mode it is mirrored under .tyrusmanager/backups. Diff .bak resolves either location.
Click any .zip file → opens as panel replacing the editor area.
- Expandable tree; hierarchical with depth indentation
- Cascading checkboxes; select folder = select all children recursively. Partial selection = individual files sent
- Custom hierarchical sort; folders first, files alphabetically
- Selective extraction; intelligent prefix-stripping, no unwanted nested paths
- Conflict pre-check; shows exact files that would be overwritten before extracting
- Drag & drop extraction; drag from ZIP panel onto folder in file panel. Destination folder highlights on hover
- Full extract; extract all contents at once
ExampleOpen release.zip in the ZIP browser, inspect its tree first, select only config/ and public/, then extract those entries instead of unpacking the entire archive.
File Search
Toolbar search box; recursive filename search, case-insensitive, max 100 results, instant sidebar results.
Content Search
- Searches inside files; max 50 files × 5 matches per file
- Results grouped by file with match count badge
- Line number + content with search term highlighted in yellow
- Click result → opens file, jumps to exact line
- Text extensions only; skips binaries
ExampleSearch filenames for invoice, then use content search for API_KEY to locate the exact files and highlighted lines that contain it.
Diff .bak
Every save automatically creates a .bak of the previous version in the active backup location. ↕ Diff .bak and Restore resolve both sibling and private backups transparently, so switching location does not make an existing backup unusable. If a file is deleted with backup while Private storage is active, its mirrored backup remains under .tyrusmanager/backups and can be reached with ROOT ON.
Side-by-side Compare
- File 1: current editor file (automatic)
- File 2: click any file in sidebar while panel is open
- Stats:
+N added / -N removed
- Color-coded: changed (amber/blue) · added (green) · removed (red) · separator (dark)
- Independent scrolling per column
ExampleAfter editing index.php, use Diff .bak to compare the current file with its previous saved version before deciding whether to restore.
- Pattern controls: Prefix · Suffix · Find · Replace (all combinable)
- Auto-numbering: 001, 002, 003…
- Live preview: old name → new name per file. Individual inputs editable
- Changed names highlighted yellow
- All renames in one operation with conflict detection
ExampleRename a selected image set from IMG_*.jpg to a numbered pattern such as gallery_001.jpg, review the preview, then apply once conflicts are clear.
Activity Log
Every action is logged with timestamp, action type and file path. LOGIN and LOGOUT also record the IP address. The private JSON log is stored in .tyrusmanager/.activity_log, keeps the latest 50 entries and can be cleared from the Log panel.
PHP Error Log
- Parses CI4 format (
LEVEL - DATE --> MSG) and PHP standard ([date] PHP Fatal error:) log formats
- Reconstructs full stack traces
- Groups by severity: Critical/Error · Warning · Notice/Info
- Collapse/expand per group
- Stack traces displayed inline with APPPATH/SYSTEMPATH highlighting
- Reverse chronological order
ExampleIf a save fails, check the activity log for the file action and the PHP error panel for the server-side error before changing permissions or code.
Root OFF (default); navigation limited to document root (public_html).
Root ON; navigate above public_html to server root. Access logs, configs, files outside web root. Warning shown as toast notification and header button changes to 🔑 Root ON when active.
ExampleKeep ROOT OFF for routine work. Turn ROOT ON only when you intentionally need the broader document-root view or a private mirrored backup, then turn it off again.
All operations via manager.php?action=ACTION:
| Backend API | Description |
| list | Directory contents; name, type, size, modified, path, permissions |
| read | File content (max 5MB) |
| readimage | Image as base64 data URI (jpg, png, gif, webp, svg, ico) |
| save | Save file; automatically backs up the previous version in the active backup location |
| upload | Upload; modes: ask / replace / copy (auto-numbered) |
| download | Download single file via HTTP |
| download-zip | Multiple files as ZIP; built via tempnam, streamed to browser, deleted immediately after |
| delete | Delete files/folders recursively; optional .bak backup uses the active backup location |
| rename | Rename; conflict detection, optional force overwrite |
| newfolder | Create directory (recursive mkdir) |
| newfile | Create empty file |
| zip | Create ZIP archive on server |
| zip-list | ZIP contents as hierarchical tree |
| unzip | Extract full ZIP archive |
| unzip-selective | Extract selected items with intelligent prefix-stripping |
| unzip-check | Pre-check extraction conflicts before extracting |
| chmod | Change file/folder permissions |
| search | Recursive filename search (max 100 results) |
| searchcontent | Text inside files (max 50 files × 5 matches) |
| diskusage | Disk usage; crawls 2 levels above docroot, cached 30 minutes |
| diff | File vs .bak with 3-line context |
| compare | Side-by-side diff between any two arbitrary files |
| lint | PHP/CSS/JS analysis; structured issue array |
| errorlog | Parse PHP error log (CI4 + standard format) |
| clearerrorlog | Clear the PHP error log file |
| phpinfo | Parsed PHP info; version, extensions, settings |
| getfavorites | List favorited paths |
| togglefavorite | Add or remove from favorites |
| getlog | Activity log entries |
| clearlog | Clear activity log |
| clearcache | LiteSpeed purge header + CI4 writable/cache folder wipe |
| getdocroot | Server document root path |
| multirename | Batch rename with conflict detection |
ExampleThe interface uses actions such as read, save, zip-list, unzip-selective, diff and lint; these are internal manager actions, not a public third-party REST API.
416 UI keys per language. The complete manager interface is available in EN / RO / DK.
- Zero page reload switching;
switchLang() → applyUiLang() + loadFiles() + renderTabs()
- All DOM elements updated: buttons, modals, placeholders, cheatsheet (fully regenerated), ZIP hints, timeout bar
- Language persisted in a cookie and the private
.tyrusmanager/.manager_config
- Animated pill switcher (desktop): cubic-bezier slide, no-transition on init to avoid flash
🇬🇧 English 🇷🇴 Romanian 🇩🇰 Danish
ExampleSwitch EN → RO → DK from the manager header: labels are re-rendered without a full page reload and the selected language is persisted.
| Breakpoint | Behavior |
| < 425px | Log hidden, disk bar hidden, micro buttons 8px, simple lang switcher |
| 425–599px | Log appears first (order:-1) before Errors |
| 600–1023px | Lang switcher static in header (no absolute positioning) |
| 1024–1100px | Lang switcher static, compact toolbar |
| > 1100px | Full desktop layout, animated pill centered absolute |
- Sidebar drawer; slides from left, overlay to close, auto-closes on file open / ZIP / image, stays open on folder navigate
- Long press 500ms; context menu at touch position, haptic feedback (
navigator.vibrate(30)), move finger = cancel
- Tab system; max-width 90px, ellipsis, close always visible, horizontal scroll
- Diff/Compare; hidden under 768px (insufficient space for split view)
ExampleOn a phone, open the sidebar drawer, long-press a file for its context actions, open it in an editor tab and close the drawer without changing the desktop workflow.
| Shortcut | Action |
| Ctrl + S | Save current file |
| Ctrl/⌘ + K | Open command palette |
| Ctrl + W | Close current tab |
| Ctrl + Z | Undo |
| Ctrl + Y | Redo |
| Ctrl + F | Find in file |
| Ctrl + H | Find & Replace |
| Ctrl + / | Comment / uncomment line |
| Tab | Indent selection |
| Ctrl + Space | Manual autocomplete |
| Escape | Close autocomplete / modal |
| A+ / A− | Increase / decrease font size |
| Right-click file | Context menu |
| Right-click tab | Tab context menu |
| Drag tab | Reorder tabs |
| Drag sidebar border | Resize sidebar |
| Double-click border | Reset sidebar width to default |
| F1 | Open keyboard shortcuts cheatsheet |
| Ctrl + Q | Analyze / lint current file |
| Delete / Shift + Delete | Delete selection; Shift+Delete skips the confirm dialog |
ExampleUse Ctrl/⌘ + K for the command palette, Ctrl + S to save and Ctrl + Q to analyze the active file without leaving the editor.
- PHP 8.0 or newer; the current build is tested through PHP 8.4
- ZipArchive is required for ZIP create, browse and extraction features
- A writable private directory outside the web root is required for manager state. The manager creates
.tyrusmanager automatically when possible; TYRUS_MANAGER_STORAGE can define an explicit location.
- No Composer · No npm · No database installation · No third-party runtime CDN
ExampleA minimal installation can run on PHP 8.0+ with writable private storage. ZIP create/browse/extract additionally needs the PHP ZipArchive extension.
Start with the exact error shown by the manager. The checks below map the most common failures to the component that actually controls them.
- Activation fails: verify the domain shown by the manager, the complete license key and outbound HTTPS access from PHP. A domain-locked key is not interchangeable between unrelated domains.
- Setup cannot save: verify that PHP can create/write the private
.tyrusmanager location or configure TYRUS_MANAGER_STORAGE to a writable private path.
- ZIP actions unavailable: enable the PHP
ZipArchive extension in the same runtime that serves manager.php. CLI PHP and web-server PHP may load different extensions.
- Unexpected backup location: check Settings → Backups. In Auto mode an exposed or unverified
.bak probe intentionally selects private storage.
- Frequent login return: the authenticated session expires after 30 minutes of inactivity. Use the session warning/extend control when you are actively editing.
Short answers to the decisions that most often matter before deployment.
Is PHP File Manager free?
Yes. The current product model is free and domain-locked.
Does it need Composer, npm or a database?
No package manager or database installation is required. The product is distributed as one PHP file and stores its private state in server-side files.
Can one license be moved to another domain?
The license is domain-locked. Activation and deactivation are explicit operations; do not assume a key issued for one unrelated domain will validate on another.
Are backups always public beside the edited file?
No. Auto can use sibling or private storage depending on the protection probe, and Private always writes new backups outside the public web root.