binocs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +21 -0
- data/README.md +528 -0
- data/Rakefile +7 -0
- data/app/assets/javascripts/binocs/application.js +105 -0
- data/app/assets/stylesheets/binocs/application.css +67 -0
- data/app/channels/binocs/application_cable/channel.rb +8 -0
- data/app/channels/binocs/application_cable/connection.rb +8 -0
- data/app/channels/binocs/requests_channel.rb +13 -0
- data/app/controllers/binocs/application_controller.rb +62 -0
- data/app/controllers/binocs/requests_controller.rb +69 -0
- data/app/helpers/binocs/application_helper.rb +61 -0
- data/app/models/binocs/application_record.rb +7 -0
- data/app/models/binocs/request.rb +198 -0
- data/app/views/binocs/requests/_empty_list.html.erb +9 -0
- data/app/views/binocs/requests/_request.html.erb +61 -0
- data/app/views/binocs/requests/index.html.erb +115 -0
- data/app/views/binocs/requests/show.html.erb +227 -0
- data/app/views/layouts/binocs/application.html.erb +109 -0
- data/config/importmap.rb +6 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20240101000000_create_binocs_requests.rb +36 -0
- data/exe/binocs +86 -0
- data/lib/binocs/agent.rb +153 -0
- data/lib/binocs/agent_context.rb +165 -0
- data/lib/binocs/agent_manager.rb +302 -0
- data/lib/binocs/configuration.rb +65 -0
- data/lib/binocs/engine.rb +61 -0
- data/lib/binocs/log_subscriber.rb +56 -0
- data/lib/binocs/middleware/request_recorder.rb +264 -0
- data/lib/binocs/swagger/client.rb +100 -0
- data/lib/binocs/swagger/path_matcher.rb +118 -0
- data/lib/binocs/tui/agent_output.rb +163 -0
- data/lib/binocs/tui/agents_list.rb +195 -0
- data/lib/binocs/tui/app.rb +726 -0
- data/lib/binocs/tui/colors.rb +115 -0
- data/lib/binocs/tui/filter_menu.rb +162 -0
- data/lib/binocs/tui/help_screen.rb +93 -0
- data/lib/binocs/tui/request_detail.rb +899 -0
- data/lib/binocs/tui/request_list.rb +268 -0
- data/lib/binocs/tui/spirit_animal.rb +235 -0
- data/lib/binocs/tui/window.rb +98 -0
- data/lib/binocs/tui.rb +24 -0
- data/lib/binocs/version.rb +5 -0
- data/lib/binocs.rb +27 -0
- data/lib/generators/binocs/install/install_generator.rb +61 -0
- data/lib/generators/binocs/install/templates/create_binocs_requests.rb +36 -0
- data/lib/generators/binocs/install/templates/initializer.rb +25 -0
- data/lib/tasks/binocs_tasks.rake +38 -0
- metadata +149 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 951ede246b19df8711837e0024c936962a8e56c60351a1fa1c47202ff6923ebb
|
|
4
|
+
data.tar.gz: b21a7315ffd445e61326d0bc7332431cde04f7d44510fdfda24f0938351717a2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 10ec890ba59758423105071b00baa05183d9a22e51b92106831b9b8c4f40d11d8bdc1c391934bc99a1f426c50e012523ce74c4442602c93b32ba3bd3d51389fd
|
|
7
|
+
data.tar.gz: 50c57ebe70c4997edf303bb7bbdda1fd29d2a03474317c4f93fa9281aceaa97b9ee05c23b45ccc9f7ad32c7c1b72a74b542220a22396de92796e34822ca09c7f
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Zincan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
# Binocs
|
|
2
|
+
|
|
3
|
+
A Laravel Telescope-inspired request monitoring dashboard for Rails applications. Binocs provides real-time visibility into HTTP requests through both a web interface and a terminal UI with vim-style navigation, making debugging and development easier whether you prefer the browser or the command line.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Real-time Request Monitoring**: Watch requests stream in as they happen via ActionCable/Turbo Streams
|
|
8
|
+
- **Comprehensive Request Details**: View params, headers, request/response bodies, logs, and exceptions
|
|
9
|
+
- **Powerful Filtering**: Filter by HTTP method, status code, path, controller, and more
|
|
10
|
+
- **Exception Tracking**: Quickly identify and debug errors with full backtrace
|
|
11
|
+
- **Performance Insights**: Track request duration and memory usage
|
|
12
|
+
- **Dark Theme UI**: Beautiful, modern interface built with Tailwind CSS
|
|
13
|
+
- **Terminal UI (TUI)**: Vim-style keyboard navigation for console-based monitoring
|
|
14
|
+
- **AI Agent Integration**: Launch Claude Code or OpenCode directly from request context to debug issues
|
|
15
|
+
- **Swagger Integration**: View OpenAPI documentation for requests and jump to Swagger UI
|
|
16
|
+
- **Production Safe**: Automatically disabled in production environments
|
|
17
|
+
|
|
18
|
+
## Screenshots
|
|
19
|
+
|
|
20
|
+
### Web Dashboard
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
*Real-time request monitoring with filtering and status indicators*
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
*Detailed view showing params, headers, body, logs, and exceptions*
|
|
27
|
+
|
|
28
|
+
### Terminal UI (TUI)
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
*Vim-style navigation in your terminal*
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+
*Split-screen detail view with tabbed content*
|
|
35
|
+
|
|
36
|
+
### AI Agent Integration
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
*Launch AI coding agents directly from request context*
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Ruby 3.0+
|
|
44
|
+
- Rails 7.0+
|
|
45
|
+
- ActionCable (for real-time updates)
|
|
46
|
+
- ncurses development libraries (for TUI - typically pre-installed on macOS/Linux)
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
### 1. Add Binocs to your Gemfile
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
# Gemfile
|
|
54
|
+
gem 'binocs', path: 'path/to/binocs' # For local development
|
|
55
|
+
|
|
56
|
+
# Or from GitHub (once published)
|
|
57
|
+
# gem 'binocs', github: 'zincan/binocs'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Install the gem
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
bundle install
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Run the install generator
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bin/rails generate binocs:install
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This will:
|
|
73
|
+
- Copy the migration file
|
|
74
|
+
- Create an initializer at `config/initializers/binocs.rb`
|
|
75
|
+
- Add the route to mount the engine
|
|
76
|
+
|
|
77
|
+
### 4. Run migrations
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
bin/rails db:migrate
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 5. Ensure ActionCable is configured
|
|
84
|
+
|
|
85
|
+
If you haven't set up ActionCable yet, add to your `config/cable.yml`:
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
development:
|
|
89
|
+
adapter: async
|
|
90
|
+
|
|
91
|
+
test:
|
|
92
|
+
adapter: test
|
|
93
|
+
|
|
94
|
+
production:
|
|
95
|
+
adapter: redis
|
|
96
|
+
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 6. Start your Rails server
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
bin/rails server
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 7. Visit the dashboard
|
|
106
|
+
|
|
107
|
+
Open your browser and navigate to: `http://localhost:3000/binocs`
|
|
108
|
+
|
|
109
|
+
## Configuration
|
|
110
|
+
|
|
111
|
+
Customize Binocs behavior in `config/initializers/binocs.rb`:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
Binocs.configure do |config|
|
|
115
|
+
# Enable/disable Binocs (automatically disabled in production)
|
|
116
|
+
config.enabled = true
|
|
117
|
+
|
|
118
|
+
# How long to keep request records (default: 24 hours)
|
|
119
|
+
config.retention_period = 24.hours
|
|
120
|
+
|
|
121
|
+
# Maximum request/response body size to store (default: 64KB)
|
|
122
|
+
config.max_body_size = 64.kilobytes
|
|
123
|
+
|
|
124
|
+
# Paths to ignore (assets, cable, etc.)
|
|
125
|
+
config.ignored_paths = %w[/assets /packs /binocs /cable]
|
|
126
|
+
|
|
127
|
+
# Content types to ignore (images, videos, etc.)
|
|
128
|
+
config.ignored_content_types = %w[image/ video/ audio/ font/]
|
|
129
|
+
|
|
130
|
+
# Maximum number of requests to store (oldest are deleted)
|
|
131
|
+
config.max_requests = 1000
|
|
132
|
+
|
|
133
|
+
# Whether to record request/response bodies
|
|
134
|
+
config.record_request_body = true
|
|
135
|
+
config.record_response_body = true
|
|
136
|
+
|
|
137
|
+
# Optional: Protect the dashboard with basic auth
|
|
138
|
+
config.basic_auth_username = ENV['BINOCS_USERNAME']
|
|
139
|
+
config.basic_auth_password = ENV['BINOCS_PASSWORD']
|
|
140
|
+
|
|
141
|
+
# Swagger/OpenAPI integration (for TUI)
|
|
142
|
+
config.swagger_spec_url = '/api-docs/v1/swagger.yaml' # OpenAPI spec endpoint
|
|
143
|
+
config.swagger_ui_url = '/api-docs/index.html' # Swagger UI URL
|
|
144
|
+
|
|
145
|
+
# Devise authentication (recommended if using Devise with ActionCable)
|
|
146
|
+
# config.authentication_method = :authenticate_user!
|
|
147
|
+
|
|
148
|
+
# Login path for authentication prompts (auto-detected for Devise)
|
|
149
|
+
# config.login_path = '/users/sign_in'
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Devise Integration
|
|
154
|
+
|
|
155
|
+
If your application uses Devise for authentication, you can require users to be logged in before accessing Binocs. This ensures the ActionCable WebSocket connection works properly.
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
# config/initializers/binocs.rb
|
|
159
|
+
Binocs.configure do |config|
|
|
160
|
+
# Require Devise authentication (recommended)
|
|
161
|
+
config.authentication_method = :authenticate_user!
|
|
162
|
+
|
|
163
|
+
# Or for admin users:
|
|
164
|
+
# config.authentication_method = :authenticate_admin!
|
|
165
|
+
|
|
166
|
+
# Or use a custom proc for more control:
|
|
167
|
+
# config.authentication_method = -> { authenticate_user! || authenticate_admin! }
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
With this configured, unauthenticated users will be redirected to your login page, then back to `/binocs` after signing in.
|
|
172
|
+
|
|
173
|
+
**Fallback behavior**: If authentication is not configured but ActionCable requires it, Binocs will detect the WebSocket failure and display a banner prompting users to sign in. You can customize the login path:
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
config.login_path = '/users/sign_in' # Auto-detected from Devise if not set
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Swagger Deep Linking (rswag)
|
|
180
|
+
|
|
181
|
+
To enable jumping directly to specific endpoints in Swagger UI, add deep linking to your rswag configuration:
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
# config/initializers/rswag_ui.rb
|
|
185
|
+
Rswag::Ui.configure do |c|
|
|
186
|
+
c.swagger_endpoint '/api-docs/v1/swagger.yaml', 'API V1 Docs'
|
|
187
|
+
|
|
188
|
+
# Enable deep linking to specific operations
|
|
189
|
+
c.config_object['deepLinking'] = true
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
With this enabled, pressing `o` in the TUI detail view will open Swagger UI and expand the matching endpoint.
|
|
194
|
+
|
|
195
|
+
## Usage
|
|
196
|
+
|
|
197
|
+
### Dashboard Overview
|
|
198
|
+
|
|
199
|
+
The main dashboard shows a list of all recorded requests with:
|
|
200
|
+
|
|
201
|
+
- HTTP method (GET, POST, PUT, PATCH, DELETE)
|
|
202
|
+
- Status code (color-coded by type)
|
|
203
|
+
- Request path
|
|
204
|
+
- Controller#action
|
|
205
|
+
- Duration
|
|
206
|
+
- Timestamp
|
|
207
|
+
|
|
208
|
+
### Filtering Requests
|
|
209
|
+
|
|
210
|
+
Use the filter bar to narrow down requests:
|
|
211
|
+
|
|
212
|
+
- **Search**: Search by path, controller, or action
|
|
213
|
+
- **Method**: Filter by HTTP method
|
|
214
|
+
- **Status**: Filter by status code range (2xx, 3xx, 4xx, 5xx)
|
|
215
|
+
- **Controller**: Filter by controller name
|
|
216
|
+
- **Has Exception**: Show only requests with exceptions
|
|
217
|
+
|
|
218
|
+
### Request Details
|
|
219
|
+
|
|
220
|
+
Click on any request to see full details including:
|
|
221
|
+
|
|
222
|
+
- **Overview**: Method, path, status, duration, memory usage
|
|
223
|
+
- **Params**: Filtered request parameters
|
|
224
|
+
- **Headers**: Request and response headers
|
|
225
|
+
- **Body**: Request and response bodies (with JSON formatting)
|
|
226
|
+
- **Logs**: Captured log entries from the request
|
|
227
|
+
- **Exception**: Full exception details with backtrace (if applicable)
|
|
228
|
+
|
|
229
|
+
### Real-time Updates
|
|
230
|
+
|
|
231
|
+
Requests appear in the dashboard in real-time as they're made to your application. The dashboard uses Turbo Streams over ActionCable for instant updates without page refresh.
|
|
232
|
+
|
|
233
|
+
## How ActionCable Integration Works
|
|
234
|
+
|
|
235
|
+
Binocs uses Rails' ActionCable and Turbo Streams to provide real-time updates to the dashboard. Here's how the pieces fit together:
|
|
236
|
+
|
|
237
|
+
### Architecture Overview
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
241
|
+
│ Your App │ │ Binocs │ │ Dashboard │
|
|
242
|
+
│ Request │────▶│ Middleware │────▶│ (Browser) │
|
|
243
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
244
|
+
│ ▲
|
|
245
|
+
│ 1. Save to DB │
|
|
246
|
+
│ 2. Broadcast │
|
|
247
|
+
▼ │
|
|
248
|
+
┌─────────────────┐ │
|
|
249
|
+
│ Turbo Stream │─────────────┘
|
|
250
|
+
│ (ActionCable) │ WebSocket
|
|
251
|
+
└─────────────────┘
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Request Recording Flow
|
|
255
|
+
|
|
256
|
+
1. **Middleware Intercepts Request**: The `Binocs::Middleware::RequestRecorder` sits in your Rails middleware stack and captures every HTTP request (except ignored paths like `/assets`, `/cable`, etc.)
|
|
257
|
+
|
|
258
|
+
2. **Data Collection**: For each request, Binocs records:
|
|
259
|
+
- HTTP method, path, full URL
|
|
260
|
+
- Request/response headers and bodies
|
|
261
|
+
- Parameters (filtered for sensitive data)
|
|
262
|
+
- Controller and action names
|
|
263
|
+
- Duration and memory usage
|
|
264
|
+
- Any exceptions that occurred
|
|
265
|
+
- Log entries generated during the request
|
|
266
|
+
|
|
267
|
+
3. **Database Storage**: The request data is saved to the `binocs_requests` table
|
|
268
|
+
|
|
269
|
+
4. **Real-time Broadcast**: After saving, Binocs broadcasts the new request via Turbo Streams:
|
|
270
|
+
```ruby
|
|
271
|
+
Turbo::StreamsChannel.broadcast_prepend_to(
|
|
272
|
+
"binocs_requests",
|
|
273
|
+
target: "requests-list",
|
|
274
|
+
partial: "binocs/requests/request",
|
|
275
|
+
locals: { request: request }
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
5. **Dashboard Updates**: The dashboard subscribes to the `binocs_requests` stream via ActionCable. When a broadcast arrives, Turbo automatically prepends the new request to the list.
|
|
280
|
+
|
|
281
|
+
### ActionCable Connection
|
|
282
|
+
|
|
283
|
+
The dashboard establishes a WebSocket connection when you load the page:
|
|
284
|
+
|
|
285
|
+
```erb
|
|
286
|
+
<%= turbo_stream_from "binocs_requests" %>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This creates a subscription to the `binocs_requests` channel. The connection uses your application's existing ActionCable configuration (`config/cable.yml`).
|
|
290
|
+
|
|
291
|
+
### Authentication & WebSocket
|
|
292
|
+
|
|
293
|
+
If your application uses Devise (or similar) with ActionCable authentication, the WebSocket connection requires the user to be authenticated. Binocs handles this in two ways:
|
|
294
|
+
|
|
295
|
+
1. **Recommended**: Configure `authentication_method` to require login before accessing Binocs (see [Devise Integration](#devise-integration))
|
|
296
|
+
|
|
297
|
+
2. **Fallback**: If WebSocket fails to connect, Binocs displays a banner prompting the user to sign in. The dashboard still works without real-time updates - you can use the Refresh button.
|
|
298
|
+
|
|
299
|
+
### Disabling Real-time Updates
|
|
300
|
+
|
|
301
|
+
The dashboard includes a "Live/Paused" toggle. When paused:
|
|
302
|
+
- The Turbo Stream subscription is temporarily disabled
|
|
303
|
+
- No new requests appear automatically
|
|
304
|
+
- Click "Refresh" to manually load new requests
|
|
305
|
+
|
|
306
|
+
### Troubleshooting ActionCable
|
|
307
|
+
|
|
308
|
+
**WebSocket not connecting:**
|
|
309
|
+
- Check that ActionCable is configured in `config/cable.yml`
|
|
310
|
+
- Verify the `/cable` path is accessible
|
|
311
|
+
- Check browser console for WebSocket errors
|
|
312
|
+
- If using Devise, ensure you're authenticated
|
|
313
|
+
|
|
314
|
+
**Requests not appearing in real-time:**
|
|
315
|
+
- Verify `Turbo::StreamsChannel` is available (requires `turbo-rails` gem)
|
|
316
|
+
- Check Rails logs for `[Binocs] Broadcasting new request` messages
|
|
317
|
+
- Ensure the request path isn't in `config.ignored_paths`
|
|
318
|
+
|
|
319
|
+
**High latency or missed updates:**
|
|
320
|
+
- Consider using Redis adapter for ActionCable in production-like environments
|
|
321
|
+
- The async adapter (default for development) works fine for local debugging
|
|
322
|
+
|
|
323
|
+
## Terminal UI (TUI)
|
|
324
|
+
|
|
325
|
+
Binocs includes a full-featured terminal interface for monitoring requests directly from your console. Run it alongside your Rails server for a vim-style debugging experience.
|
|
326
|
+
|
|
327
|
+

|
|
328
|
+
|
|
329
|
+
### Starting the TUI
|
|
330
|
+
|
|
331
|
+
From your Rails application directory:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
bundle exec binocs
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Or if you're in the binocs gem directory:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
cd /path/to/your/rails/app
|
|
341
|
+
bundle exec binocs
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Keyboard Navigation
|
|
345
|
+
|
|
346
|
+
**List View:**
|
|
347
|
+
|
|
348
|
+
| Key | Action |
|
|
349
|
+
|-----|--------|
|
|
350
|
+
| `j` / `↓` | Move down |
|
|
351
|
+
| `k` / `↑` | Move up |
|
|
352
|
+
| `g` / `Home` | Go to top |
|
|
353
|
+
| `G` / `End` | Go to bottom |
|
|
354
|
+
| `Ctrl+d` / `PgDn` | Page down |
|
|
355
|
+
| `Ctrl+u` / `PgUp` | Page up |
|
|
356
|
+
| `Enter` / `l` | View request details |
|
|
357
|
+
| `/` | Search by path |
|
|
358
|
+
| `f` | Open filter menu |
|
|
359
|
+
| `c` | Clear all filters |
|
|
360
|
+
| `r` | Refresh list |
|
|
361
|
+
| `d` | Delete selected request |
|
|
362
|
+
| `D` | Delete all requests |
|
|
363
|
+
| `?` | Show help |
|
|
364
|
+
| `q` | Quit |
|
|
365
|
+
|
|
366
|
+
**Detail View:**
|
|
367
|
+
|
|
368
|
+
| Key | Action |
|
|
369
|
+
|-----|--------|
|
|
370
|
+
| `Tab` / `]` / `L` | Next tab |
|
|
371
|
+
| `Shift+Tab` / `[` / `H` | Previous tab |
|
|
372
|
+
| `1`-`8` | Jump to tab by number |
|
|
373
|
+
| `j` / `↓` | Scroll down |
|
|
374
|
+
| `k` / `↑` | Scroll up |
|
|
375
|
+
| `n` | Next request |
|
|
376
|
+
| `p` | Previous request |
|
|
377
|
+
| `o` | Open Swagger docs in browser |
|
|
378
|
+
| `h` / `Esc` | Go back to list |
|
|
379
|
+
|
|
380
|
+
### TUI Features
|
|
381
|
+
|
|
382
|
+
- **Split-screen layout**: List on left, detail on right when viewing a request
|
|
383
|
+
- **Tabbed detail view**: Overview, Params, Headers, Body, Response, Logs, Exception, Swagger, Agent
|
|
384
|
+
- **AI Agent integration**: Launch coding agents with request context directly from the TUI
|
|
385
|
+
- **Swagger integration**: View OpenAPI docs for any request and open in browser with `o`
|
|
386
|
+
- **Color-coded**: HTTP methods and status codes are highlighted by type
|
|
387
|
+
- **Auto-refresh**: List automatically updates every 2 seconds
|
|
388
|
+
- **Filtering**: Same filtering capabilities as the web interface
|
|
389
|
+
- **Responsive**: Adapts to terminal size changes
|
|
390
|
+
- **Easter egg**: Press `Space` then `s` in detail view to discover your request's spirit animal!
|
|
391
|
+
|
|
392
|
+

|
|
393
|
+
|
|
394
|
+

|
|
395
|
+
|
|
396
|
+
## AI Agent Integration
|
|
397
|
+
|
|
398
|
+
Binocs can launch AI coding agents (Claude Code or OpenCode) directly from the context of a captured request. This is useful when you want an AI to help debug or fix an issue based on the request data.
|
|
399
|
+
|
|
400
|
+

|
|
401
|
+
|
|
402
|
+
### Using AI Agents in the TUI
|
|
403
|
+
|
|
404
|
+
1. View a request's details and navigate to the **Agent** tab (press `a` or `9`)
|
|
405
|
+
2. Configure your agent settings (see below)
|
|
406
|
+
3. Type your prompt describing what you want the AI to do
|
|
407
|
+
4. Press `Enter` on an empty line to submit
|
|
408
|
+
5. Watch the AI's output in real-time
|
|
409
|
+
|
|
410
|
+
The agent receives full context about the request including the HTTP method, path, params, headers, request/response bodies, and any exceptions - giving it everything needed to understand and debug the issue.
|
|
411
|
+
|
|
412
|
+
### Agent Settings
|
|
413
|
+
|
|
414
|
+
While in the Agent tab, you can configure how the agent runs:
|
|
415
|
+
|
|
416
|
+
| Key | Setting | Description |
|
|
417
|
+
|-----|---------|-------------|
|
|
418
|
+
| `t` | **Toggle Tool** | Switch between Claude Code and OpenCode. Claude Code uses `claude` CLI with `--dangerously-skip-permissions` for autonomous operation. OpenCode uses the `opencode` CLI. |
|
|
419
|
+
| `w` | **Toggle Worktree** | Switch between working on your current branch or creating an isolated git worktree. |
|
|
420
|
+
|
|
421
|
+
**Current Branch Mode** (default): The agent makes changes directly on your current git branch. Quick and simple for small fixes.
|
|
422
|
+
|
|
423
|
+
**Worktree Mode**: Creates a new git worktree and branch (e.g., `agent/0117-1423-fix-auth`) for the agent to work in. This keeps your current branch clean and lets you review changes before merging. Press `w` to enable, then enter a name for the worktree/branch.
|
|
424
|
+
|
|
425
|
+
### Configuration
|
|
426
|
+
|
|
427
|
+
```ruby
|
|
428
|
+
# config/initializers/binocs.rb
|
|
429
|
+
Binocs.configure do |config|
|
|
430
|
+
config.agent_tool = :claude_code # or :opencode
|
|
431
|
+
config.agent_worktree_base = '../binocs-agents' # where worktrees are created
|
|
432
|
+
end
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Rake Tasks
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
# Clear all recorded requests
|
|
439
|
+
bin/rails binocs:clear
|
|
440
|
+
|
|
441
|
+
# Prune old requests (based on retention_period)
|
|
442
|
+
bin/rails binocs:prune
|
|
443
|
+
|
|
444
|
+
# Show statistics
|
|
445
|
+
bin/rails binocs:stats
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Security
|
|
449
|
+
|
|
450
|
+
### Production Safety
|
|
451
|
+
|
|
452
|
+
Binocs is automatically disabled in production environments. Even if mounted, accessing `/binocs` in production will return a 403 Forbidden response.
|
|
453
|
+
|
|
454
|
+
### Basic Authentication
|
|
455
|
+
|
|
456
|
+
For additional security in development/staging, enable basic auth:
|
|
457
|
+
|
|
458
|
+
```ruby
|
|
459
|
+
# config/initializers/binocs.rb
|
|
460
|
+
Binocs.configure do |config|
|
|
461
|
+
config.basic_auth_username = 'admin'
|
|
462
|
+
config.basic_auth_password = 'secret'
|
|
463
|
+
end
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Sensitive Data
|
|
467
|
+
|
|
468
|
+
Binocs uses Rails' parameter filtering, so sensitive params (like `password`) are automatically masked. Cookies are not stored for security reasons.
|
|
469
|
+
|
|
470
|
+
## Git Ignore
|
|
471
|
+
|
|
472
|
+
When using the AI Agent feature, Binocs creates temporary files in your project directory that should be added to your `.gitignore`:
|
|
473
|
+
|
|
474
|
+
```gitignore
|
|
475
|
+
# Binocs AI Agent files
|
|
476
|
+
.binocs-context.md
|
|
477
|
+
.binocs-prompt.md
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
If you use the worktree mode for agents, the default location is `../binocs-agents/` (a sibling directory to your project), so it won't affect your repo. However, if you configure a custom worktree path inside your project, add that path to `.gitignore` as well.
|
|
481
|
+
|
|
482
|
+
## Troubleshooting
|
|
483
|
+
|
|
484
|
+
### Requests not appearing
|
|
485
|
+
|
|
486
|
+
1. Ensure Binocs is enabled: Check `Binocs.enabled?` returns `true`
|
|
487
|
+
2. Check the path isn't ignored: Verify the path isn't in `config.ignored_paths`
|
|
488
|
+
3. Verify migrations ran: Check the `binocs_requests` table exists
|
|
489
|
+
|
|
490
|
+
### Real-time updates not working
|
|
491
|
+
|
|
492
|
+
1. Ensure ActionCable is configured and running
|
|
493
|
+
2. Check browser console for WebSocket errors
|
|
494
|
+
3. Verify you have `turbo_stream_from "binocs_requests"` in the layout
|
|
495
|
+
|
|
496
|
+
### High memory usage
|
|
497
|
+
|
|
498
|
+
1. Reduce `config.retention_period`
|
|
499
|
+
2. Lower `config.max_requests`
|
|
500
|
+
3. Set `config.record_response_body = false` if you don't need response bodies
|
|
501
|
+
|
|
502
|
+
## Development
|
|
503
|
+
|
|
504
|
+
### Running Tests
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
cd binocs
|
|
508
|
+
bundle install
|
|
509
|
+
bundle exec rspec
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Building the Gem
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
gem build binocs.gemspec
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
## License
|
|
519
|
+
|
|
520
|
+
MIT License. See [MIT-LICENSE](MIT-LICENSE) for details.
|
|
521
|
+
|
|
522
|
+
## Contributing
|
|
523
|
+
|
|
524
|
+
1. Fork the repository
|
|
525
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
526
|
+
3. Commit your changes (`git commit -am 'Add amazing feature'`)
|
|
527
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
528
|
+
5. Open a Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Binocs Application JavaScript
|
|
2
|
+
import "@hotwired/turbo-rails"
|
|
3
|
+
|
|
4
|
+
// Auto-scroll to top when new request is prepended
|
|
5
|
+
document.addEventListener("turbo:before-stream-render", (event) => {
|
|
6
|
+
const stream = event.target
|
|
7
|
+
if (stream.action === "prepend" && stream.target === "requests-list") {
|
|
8
|
+
// Highlight the new element briefly
|
|
9
|
+
const originalRender = event.detail.render
|
|
10
|
+
event.detail.render = (streamElement) => {
|
|
11
|
+
originalRender(streamElement)
|
|
12
|
+
const newElement = document.querySelector("#requests-list > :first-child")
|
|
13
|
+
if (newElement) {
|
|
14
|
+
newElement.classList.add("turbo-stream-prepend")
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// Auto-refresh toggle functionality
|
|
21
|
+
let autoRefreshInterval = null
|
|
22
|
+
|
|
23
|
+
function startAutoRefresh() {
|
|
24
|
+
if (autoRefreshInterval) return
|
|
25
|
+
autoRefreshInterval = setInterval(() => {
|
|
26
|
+
const frame = document.querySelector("#requests-list")
|
|
27
|
+
if (frame) {
|
|
28
|
+
Turbo.visit(window.location.href, { frame: "requests-list" })
|
|
29
|
+
}
|
|
30
|
+
}, 5000)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function stopAutoRefresh() {
|
|
34
|
+
if (autoRefreshInterval) {
|
|
35
|
+
clearInterval(autoRefreshInterval)
|
|
36
|
+
autoRefreshInterval = null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// WebSocket connection monitoring for authentication
|
|
41
|
+
let connectionAttempts = 0
|
|
42
|
+
let wasEverConnected = false
|
|
43
|
+
|
|
44
|
+
function setupConnectionMonitoring() {
|
|
45
|
+
if (typeof Turbo === 'undefined' || !Turbo.cable) {
|
|
46
|
+
// Turbo cable not available yet, retry
|
|
47
|
+
setTimeout(setupConnectionMonitoring, 100)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const consumer = Turbo.cable
|
|
52
|
+
|
|
53
|
+
// Monitor connection events
|
|
54
|
+
const originalOpen = consumer.connection.events.open
|
|
55
|
+
const originalClose = consumer.connection.events.close
|
|
56
|
+
|
|
57
|
+
consumer.connection.events.open = function() {
|
|
58
|
+
wasEverConnected = true
|
|
59
|
+
connectionAttempts = 0
|
|
60
|
+
hideAuthBanner()
|
|
61
|
+
if (originalOpen) originalOpen.call(this)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
consumer.connection.events.close = function(event) {
|
|
65
|
+
connectionAttempts++
|
|
66
|
+
// If we've never connected and have tried a few times, likely auth issue
|
|
67
|
+
if (!wasEverConnected && connectionAttempts >= 2) {
|
|
68
|
+
showAuthBanner()
|
|
69
|
+
}
|
|
70
|
+
if (originalClose) originalClose.call(this, event)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Also check initial state after a delay
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
if (!wasEverConnected && !consumer.connection.isOpen()) {
|
|
76
|
+
showAuthBanner()
|
|
77
|
+
}
|
|
78
|
+
}, 2000)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function showAuthBanner() {
|
|
82
|
+
const banner = document.getElementById('binocs-auth-banner')
|
|
83
|
+
if (banner) {
|
|
84
|
+
banner.classList.remove('hidden')
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function hideAuthBanner() {
|
|
89
|
+
const banner = document.getElementById('binocs-auth-banner')
|
|
90
|
+
if (banner) {
|
|
91
|
+
banner.classList.add('hidden')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Initialize connection monitoring when DOM is ready
|
|
96
|
+
document.addEventListener('DOMContentLoaded', setupConnectionMonitoring)
|
|
97
|
+
document.addEventListener('turbo:load', setupConnectionMonitoring)
|
|
98
|
+
|
|
99
|
+
// Expose to window for manual control
|
|
100
|
+
window.Binocs = {
|
|
101
|
+
startAutoRefresh,
|
|
102
|
+
stopAutoRefresh,
|
|
103
|
+
showAuthBanner,
|
|
104
|
+
hideAuthBanner
|
|
105
|
+
}
|