Introducing Hono CLI
Introducing Hono CLI
Hono has provided many innovative features: a router leveraging regular expressions, lightweight server-side JSX, RPC through TypeScript types, and multi-runtime support using Web Standards. We’ve competed globally with ideas and implementation.
Today, we’re introducing the Hono CLI.
Hono CLI is a command-line interface with an entirely new concept.
- It’s NOT a
create-*tool - It’s NOT just development commands (
dev&build&deploy) - It’s NOT a Vite wrapper
It’s a CLI for humans and AI. Once installed, you can use the hono command:
hono --help
There are five subcommands:
hono docshono searchhono requesthono servehono optimize
Let’s look at each one.
hono docs
First is hono docs. You run it like this:
hono docs [path]
For path, you specify a path from the Hono website (https://hono.dev). For example, to view the ”Routing” page, you would do:
hono docs /docs/api/routing
This lets you view the documentation.
But you might be thinking, “That’s it?” Yes, that’s it. However, the key point is that Markdown is output to standard output.

You can probably guess. This is AI-friendly. There are no HTML tags that come with fetching web pages. Since it’s standard output, AI coding agents can read it.
hono search
Next is hono search.
hono search <query>
For query, you specify a search term. For example, to find documentation about middleware:
hono search middleware
This outputs URLs and paths of relevant pages from the website in JSON format to standard output.

This means that combined with hono docs, “AI can autonomously search and read documentation”. For example, to search for and read documentation about basic authentication, the flow would be:
hono search "basic auth"- Get the path
/docs/middleware/builtin/basic-auth - Pass it to
hono docsas an argument - The corresponding documentation’s Markdown is displayed
There are more AI-oriented commands. Let’s move on.
hono request
The next command is hono request.
hono request [file]
The default value for file is src/index.ts, but to specify it explicitly:
hono request src/index.ts
To understand this command, first imagine Hono’s app.request() API. Using app.request(), you can send requests to a Hono app and get responses without starting a server. This is very convenient for checking behavior and testing.
Here’s code that sends a GET request to path /, with the returned Response object going into res:
const res = await app.request('/')
hono request sends the request specified on the command line to the Hono app in the file you specify, and prints the result.
hono request src/index.ts
This executes:
const res = await app.request('/')
For example, here’s a Hello World app:
// src/index.ts
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello World'))
export default app
Let’s run hono request on this file.

-P specifies the path / to request. The default method is GET. The standard output prints the result in JSON format: “status code is 200, body is Hello World”. You can do more complex things. Like curl, you can use -X to specify the method and -d to specify the body.
hono request \
-P /api/users \
-X POST \
-d '{"name":"Alice"}' \
src/index.ts
This command is very convenient for humans. Previously, when testing an app, you’d start a server using Wrangler, Deno, Bun, or Node.js commands, then hit it with a web browser or curl. But with hono request, you can test your app without starting a server!
AI can use it too. This is very powerful. You’ve probably seen coding agents start servers and run curl. You’ve also seen them fail to shut down servers properly, causing port conflicts and starting multiple servers… With hono request, you don’t even need to start a server, so you can test apps very quickly, accurately, and cleanly.
And AI can combine this command with the previous two commands:
hono search=> Find documentationhono docs=> Read documentationhono request=> Test the app
You can write this workflow as steps in AGENTS.md or CLAUDE.md. This works as-is:
# My App Development Guidelines
## Hono Development
Use the `hono` CLI for efficient development. View all commands with `hono --help`.
### Core Commands
- **`hono docs [path]`** - Browse Hono documentation
- **`hono search <query>`** - Search documentation
- **`hono request [file]`** - Test app requests without starting a server
### Quick Examples
```bash
# Search for topics
hono search middleware
hono search "getting started"
# View documentation
hono docs /docs/api/context
hono docs /docs/guides/middleware
# Test your app
hono request -P /api/users src/index.ts
hono request -P /api/users -X POST -d '{"name":"Alice"}' src/index.ts
```
### Workflow
1. Search documentation: `hono search <query>`
2. Read relevant docs: `hono docs [path]`
3. Test implementation: `hono request [file]`
Watch the demo. You can see a coding agent creating an app using the hono commands.

hono serve
So far, these have been commands for AI. Now let’s introduce commands for humans. The first is hono serve.
hono serve index.ts
This starts the Hono app in index.ts at http://localhost:7070.
?? That’s it?? Doesn’t that just remove the need for the Node.js Adapter? Can’t you do the same thing with Wrangler, Deno, or Bun?
No, there’s a --use option. Imagine app.use().
app.use(middleware)
app.use() applies middleware to the app. For example, the built-in logger middleware is used like this:
app.use(logger())
Extract just logger() from there. In hono serve, you can specify it as the value of the --use option and apply middleware without changing your app code.
hono serve --use 'logger()' src/index.ts
This way, even apps that don’t specify a logger will output logs.

Applying this, you can even add Basic authentication without rewriting code:
hono serve \
--use "logger()" \
--use "basicAuth({username:'foo',password:'bar'})" \
src/index.ts
Now, if you don’t pass an entry path like src/index.ts to this subcommand, an empty app is used.

Accessing http://localhost:7070 returns 404. Applying this, you can start a server combining middleware even without local files.
For example, you can start a server that serves local files:
hono serve \
--use "serveStatic({root:'./'})"
You can also use helpers, so using the Proxy helper’s proxy, you can set up a reverse proxy for the Ramen API:
hono serve \
--use '(c) => proxy(`https://ramen-api.dev${new URL(c.req.url).pathname}`)'
hono optimize
The final command is hono optimize.
hono optimize [entry]
Before explaining the command, let’s talk about Hono’s routers. RegExpRouter is one of the fastest routers in the JavaScript world. Under certain conditions, it’s the fastest. The idea behind RegExpRouter is to combine dynamic route information into one large regular expression and match it all at once when a request comes in. This has weaknesses:
- Slow initialization
- Large file size
To solve these, two routers were invented in Hono and provided as presets:
- LinearRouter -
hono/quick - PatternRouter -
hono/tiny
Indeed, LinearRouter is fast in benchmarks including initialization, and PatternRouter has a small bundle size. But I want to use RegExpRouter!
So today we’re introducing the seventh router (the six existing ones are the five current routers plus the deprecated StaticRouter): PreparedRegExpRouter.
The idea behind PreparedRegExpRouter is to pre-convert the route information equivalent to the regular expressions created by RegExpRouter into strings and hardcode them.
Suppose you have an app like this:
import { Hono } from 'hono'
const app = new Hono()
app.get('/posts', (c) => c.json({}))
app.get('/posts/:id', (c) => c.json({}))
app.put('/posts', (c) => c.json({}))
export default app
This route information is pre-converted to strings and passed to the router’s constructor:
const routerParams = [
{ ALL: [/^\/posts\/([^/]+)$()/, [0, 0, []], { '/posts': [[], []] }] },
{ '/posts': [[['']]], '/posts/:id': [[[2], { id: 1 }]] }
]
const router = new PreparedRegExpRouter(...routerParams)
This first makes initialization faster. Let’s look at benchmark results measuring router performance including initialization.

If we sort this…

LinearRouter is naturally first, but PreparedRegExpRouter takes second place. RegExpRouter is much further back. Compared to RegExpRouter, PreparedRegExpRouter is 16.5 times faster (in benchmarks including initialization).
Back to the Hono CLI story.
hono optimize “optimizes Hono for your app”. So what is optimized Hono? It’s this:
class Hono extends HonoBase {
constructor(options = {}) {
super(options)
const routerParams = [
{ ALL: [/^\/posts\/([^/]+)$()/, [0, 0, []], { '/posts': [[], []] }] },
{ '/posts': [[['']]], '/posts/:id': [[[2], { id: 1 }]] }
]
this.router = new PreparedRegExpRouter(...routerParams)
}
}
In other words, it becomes a Hono with PreparedRegExpRouter implemented for that specific app.
Let’s run hono optimize.

The optimized result of src/index.ts is written to dist/index.js. You can then deploy it directly with wrangler deploy:
hono optimize src/index.ts
wrangler deploy dist/index.js
So how much smaller did it get? Let’s compare a build without optimization that’s minified, a file run with hono optimize with the minify option, and one using the hono/tiny preset.

While it doesn’t reach hono/tiny’s size, compared to the original app’s 18.0KB, it’s significantly smaller at 11.14KB. That’s a 38% reduction.
In other words, hono optimize makes your app faster and smaller. This is how Hono CLI provides simple subcommands for humans: hono serve and hono optimize.
Note: We want to make the optimization technique using PreparedRegExpRouter available in build and bundle tools like Vite build plugins in the future.
Summary
Hono CLI provides five subcommands:
hono docshono searchhono requesthono servehono optimize
These are commands for humans and AI.
The Hono CLI repository is public:
And you can try Hono CLI right now:
npm i @hono/cli
Enjoy!