Playground
The Playground imports @agntn/hashes into the page and runs the tool executors there. Every digest, HMAC, verdict and listing is the library's own answer, the same code the CLI and the MCP server run. Nothing is sent anywhere. The worker serves the page and that's the end of its involvement.
| Operation | Runs | Tool |
|---|---|---|
| Hash | hashCompute({ algorithm, input, inputEncoding, encoding, salt, parameters }) | hash_compute |
| HMAC | hashHmac({ algorithm, input, inputEncoding, key, keyEncoding, encoding }) | hash_hmac |
| Verify | hashVerify({ algorithm, input, inputEncoding, expected, encoding, salt, parameters }) | hash_verify |
| Algorithms | hashAlgorithms({ family }) or ({ algorithm }) | hash_algorithms |
The parameter fields come from info().options. Pick scrypt and N, r, p and keyLength show up. Pick SHA-256 and they're gone.
Every state is a link
The form writes itself into the address: /playground?op=hash&algorithm=keccak256&input=transfer(address,uint256) opens the page on that answer. Paste it to someone and they see what you saw.
Costs are the tool's costs
The playground calls the executors, so it inherits their limits. scrypt with N 1048576 is refused the same way an agent would be refused. The defaults are the real defaults, so PBKDF2 at 600000 rounds of SHA-512 does take a moment in a browser tab. That's the point of a KDF, it isn't the page being slow.
The two snippets
Under the fields the page prints the same call as a CLI line and as a tool invocation in JSON, both with copy buttons. They're built from the form, so what you copy is what you ran. The answer ends in a Full tool response row with the exact text a model would get.