Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<img alt="Development Statue" src="https://img.shields.io/badge/status-in%20development-yellow?style=for-the-badge">
</p>

Tapper is a tiny debugger for PHP. Call `tp($value)` anywhere in your code and
the payload streams live into a terminal UI running as a separate process —
like `console.log`, but with a dedicated, scrollable, filterable viewer
instead of stdout.

```PHP
<?php

Expand All @@ -31,6 +36,57 @@ foreach (range(1, 3) as $i) {

![Tapper demo animation](assets/demo.webp)

## Installation

Tapper hasn't been released yet and isn't on Packagist, so `composer require`
won't work. For now, clone the repo and install it from source:

```bash
git clone https://github.com/tapperphp/tapper.git
cd tapper
composer install
```

Requires PHP 8.2+ (tested on 8.2, 8.3 and 8.4).

## Usage

Start the TUI in one terminal — it opens a local socket and waits for a script to connect:

```bash
php bin/tapper
```

Then, in another terminal, run any PHP script that calls `tp()` (see the
example above, or `examples/BasicExample.php`) — its output streams into the
TUI live:

```bash
php examples/BasicExample.php
```

### Keyboard shortcuts

- `↑`/`↓` (or `k`/`j`), `g`/`G` — move the cursor, jump to top/bottom
- `Enter` / `Space` — open the details view for the selected log (syntax-highlighted
payload, source snippet, stack trace); `↑`/`↓`/`←`/`→` scroll it, `Backspace`/`Esc` closes it
- `/` — filter logs live as you type; `Enter` confirms, `Esc` clears the filter and returns to the live tail
- `Enter` — also resumes a script paused on `tp(...)->wait()`
- `Ctrl+L` — clear all logs
- `?` — shortcuts popup, `q` — quit

## Documentation

For the two-process architecture, the TUI's component model, and the wire
protocol between a debuggee script and the TUI, see [`docs/`](docs).

## Testing

```bash
composer test:unit # Pest
composer test:lint # Pint (check only)
```

## 🚧 Project Status

This project is in active development and not yet ready for production use.
Expand Down
8 changes: 4 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ sequenceDiagram
participant Sock as unix socket (tapper.sock)
participant Server as Server.php (TUI process)
participant State as AppState
participant Loop as ReactPHP loop
participant Reactor as ReactPHP loop
participant TUI as php-tui Display

App->>Tapper: tp($value)
Expand All @@ -25,12 +25,12 @@ sequenceDiagram
Tapper->>Sock: write JSON-RPC-ish request, blocks on fgets()
Sock->>Server: decoded NDJSON message
Server->>State: appendLog(new LogItem(...))
State-->>Loop: onChange callback fires
State-->>Reactor: onChange callback fires
Server-->>Sock: write {"result":"ok"}
Sock-->>Tapper: response
Tapper-->>App: unblocks, statement completes
Loop->>Loop: next 1/60s render tick sees shouldDraw=true
Loop->>TUI: Application::draw() -> Display::draw(widgets)
Reactor->>Reactor: next 1/60s render tick sees shouldDraw=true
Reactor->>TUI: Application::draw() -> Display::draw(widgets)
```

## Inside the TUI process
Expand Down
Loading