PHPackages                             hivellm/thunder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. hivellm/thunder

ActiveLibrary

hivellm/thunder
===============

HiveLLM binary RPC (Thunder) — wire v1 codec, family profiles, multiplexed client

v0.2.2(yesterday)05↑2900%1Apache-2.0PHP &gt;=8.2

Since Jul 19Compare

[ Source](https://github.com/hivellm/thunder-php)[ Packagist](https://packagist.org/packages/hivellm/thunder)[ RSS](/packages/hivellm-thunder/feed)WikiDiscussions Synced today

READMEChangelogDependencies (4)Versions (3)Used By (1)

Thunder — PHP SDK
=================

[](#thunder--php-sdk)

The PHP lane of the Thunder RPC family (`hivellm/thunder`). Wire bytes are identical to the Rust, TypeScript, Python, C# and Go lanes — every implementation pins its default test run to `conformance/vectors/*.yaml`(SPEC-005), so one PR changes wire behaviour everywhere or fails CI.

Layout
------

[](#layout)

- `src/Wire/` — the wire layer (SPEC-001): the 8-variant `Value`, array-encoded `Request` / `Response`, `PUSH_ID` (= `u32::MAX`), and the length-prefixed MessagePack frame codec with the cap checked before body allocation. Encoding uses [`rybakit/msgpack`](https://github.com/rybakit/msgpack.php)driven at the low level, which reproduces the reference (rmp-serde) shortest-form integer packing byte for byte.
- `src/Client/` — the multiplexed client (SPEC-003) and the protocol `Config`(SPEC-002): demux by id, per-call timeouts, all three handshake styles, lazy reconnect, push routing, typed errors classifying both conventions, and the connection `Pool`.
- `tests/` — unit tests plus the corpus loader (TST-020), the primary cross-language proof, run by the default `phpunit`.

Usage
-----

[](#usage)

```
use HiveLLM\Thunder\Client\Client;
use HiveLLM\Thunder\Client\ClientConfig;
use HiveLLM\Thunder\Client\Config;
use HiveLLM\Thunder\Client\Credentials;
use HiveLLM\Thunder\Client\ServerException;
use HiveLLM\Thunder\Wire\Value;

// Start from THE standard and add only your own identity. Everything else —
// handshake shape, frame cap, error convention — is the family default.
$config = Config::standard()->withScheme('myapp')->withPort(9000);

$client = Client::connect('myapp://localhost:9000', $config,
    (new ClientConfig())->withCredentials(Credentials::token('secret')));

try {
    echo $client->call('PING')->asStr();
} catch (ServerException $e) {
    // Branch on the class and the code, never on message text (CLT-052).
    error_log("server refused: {$e->errorCode}");
}
```

### Pipelining, and the one thing PHP cannot do

[](#pipelining-and-the-one-thing-php-cannot-do)

Every other lane demultiplexes with a background reader. PHP has no threads and no event loop, so this client demuxes **on read**: while waiting for one id it consumes whatever arrives, routing pushes to the handler and dropping unknown ids. Responses are matched by id, never by arrival order — the contract CLT-010 actually specifies.

What genuinely differs is that one PHP thread cannot *await* two calls at once. For real multiple-in-flight, send and collect are separate steps:

```
$a = $client->send('SLOW');   // written, not awaited
$b = $client->send('FAST');

echo $client->collect($b)->asStr();  // may complete first
echo $client->collect($a)->asStr();
```

`call()` is the one-at-a-time convenience over both.

### Pooling

[](#pooling)

`N` operations over a pooled connection pay **one** connect and one handshake, not `N` (CLT-080):

```
$pool = new Pool('myapp://localhost:9000', $config);

$pool->with(function (Client $client): void {
    $client->call('SET', [Value::str('k'), Value::str('v')]);
    $client->call('GET', [Value::str('k')]);   // same connection
});
```

The callback form is not stylistic: the connection returns in a `finally`, so an early return or an exception cannot leak it.

### Two more things PHP forces this lane to do differently

[](#two-more-things-php-forces-this-lane-to-do-differently)

**A `Value` is built through factories, never inferred.** PHP has one string type for both text and binary, but Thunder does not: `Str` encodes as MessagePack `str` and `Bytes` as `bin`, and WIRE-015 forbids smuggling one as the other. A design that guessed the variant from the PHP value could not tell `Value::str('AB')` from `Value::bytes('AB')` — so the variant is always named.

**A `Map` is a list of pairs, not a PHP array.** Thunder map keys may be any value and order is observable (WIRE-002); a PHP array would restrict keys to `int|string` and collapse duplicates. Use `Value::mapOf([...])` for the common string-keyed case, or `MapEntry` directly when keys are not strings.

Test / quality gate
-------------------

[](#test--quality-gate)

```
composer install
vendor/bin/phpstan analyse    # type-check first: the faster signal
vendor/bin/phpunit            # unit tests + the corpus, one command
```

The corpus is not a separate target. TST-020 requires it in the **default** test command — never feature-gated, never skipped — because a conformance run that has to be remembered is one that stops happening.

Release train (PKG-011)
-----------------------

[](#release-train-pkg-011)

This package versions in lockstep with every other lane: one tag, one version, everywhere. It publishes to [Packagist](https://packagist.org/) as `hivellm/thunder`, which resolves from a VCS tag — so, like the Go lane, there is no push step, but the tag must exist.

The shared gate in `release.yml` runs this lane's checks on the tagged commit before anything ships.

Where this code lives
---------------------

[](#where-this-code-lives)

The source of truth is the `php/` directory of the [Thunder monorepo](https://github.com/hivellm/thunder), alongside the other five lanes and the conformance corpus they all share.

The corpus is read from `../conformance/vectors/` relative to this package. If this code is ever mirrored to a standalone repository (as the Go lane is), those vectors are absent there and the corpus tests **skip** — they still run for real upstream, which is where a wire change actually lands. A skipped corpus in a mirror is expected; a skipped corpus in the monorepo is a bug.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance100

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community5

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/575599?v=4)[André Ferreira](/maintainers/andrehrf)[@andrehrf](https://github.com/andrehrf)

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/hivellm-thunder/health.svg)

```
[![Health](https://phpackages.com/badges/hivellm-thunder/health.svg)](https://phpackages.com/packages/hivellm-thunder)
```

###  Alternatives

[ably/ably-php

Ably REST client library for PHP.

597.9M34](/packages/ably-ably-php)[tarantool/client

PHP client for Tarantool.

68452.6k23](/packages/tarantool-client)[rootsoft/algorand-php

Community SDK to interact with the Algorand network, in PHP &amp; Laravel

4315.4k](/packages/rootsoft-algorand-php)[czdb/searcher

A PHP library for efficient IP geolocation using compact database formats.

285.5k1](/packages/czdb-searcher)[onebot/libonebot

PHP 的 LibOneBot 库，通过此库可快速接入 OneBot 生态

175.3k1](/packages/onebot-libonebot)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
