tablogger
v0.1.7
Published
Universal logging function — tablog() works on frontend, backend, any language
Maintainers
Readme
tablogger
One function. Every language. One terminal.
tablog() is a drop-in replacement for console.log / print() that routes all logs — frontend, backend, any framework — to a single unified terminal. Run npx tablogger once and see everything in one place: colored source labels, network request tracking, log levels, split view, and a full HTTP API for querying your logs programmatically.
npx tablogger[React] button clicked (×3)
[React] out GET /api/users 200 22ms 1.2kB
[FastAPI] in GET /api/users 200 18ms 1.2kB <> React
[FastAPI] fetching users from db main.py:42
[FastAPI] returning 3 users main.py:45Claude Code integration
When you run npx tablogger, it automatically writes a live API reference into your project's CLAUDE.md. Claude Code reads this on every prompt — so Claude and its agents can query your logs, errors, traces, and slow requests directly as part of debugging, without any extra setup.
You: "why is /api/users slow?"
Claude: [curls localhost:4242/slow]
[curls localhost:4242/trace?url=/api/users]
"The FastAPI handler is taking 1.2s — tablog shows it's the db query on main.py:38"When you Ctrl+C tablogger, the section is removed and CLAUDE.md is restored.
Installation
JavaScript / TypeScript
npm install tabloggerPython
pip install tablogQuick start
1. Start the terminal
npx tablogger2. Add to your JS app
import { tablog } from 'tablogger'
tablog('user logged in')
tablog('query result:', { rows: 42 })3. Add to your Python app
from tablog import tablog
tablog('server started')
tablog('query result:', {'rows': 42})Everything streams to the same terminal, labeled by source.
Features
Unified terminal for every service
All logs from React, Express, FastAPI, Flask, or any Node/Python service appear in one place with colored [Source] labels — no tab-switching.
Network request tracking
Frontend outgoing requests and backend incoming requests are captured automatically and shown in a compact line:
[React] out GET /api/users 200 22ms 1.2kB
[FastAPI] in GET /api/users 200 18ms <> ReactStatus codes are color-coded (green/cyan/yellow/red) and slow requests (>500ms) are highlighted in red.
Request correlation
When a React fetch() and a FastAPI handler serve the same request, tablogger links them with <> React — no headers injected, no CORS issues. Matched by METHOD + path within a 3-second window.
Caller file + line (Python)
Every Python tablog() call shows the file and line number it was called from:
[FastAPI] fetching users from db main.py:38
[FastAPI] returning 3 users main.py:41Log levels
tablog('all good') # default
tablog('cache miss rate high', level='warn') # yellow
tablog('payment failed', level='error') # red ●Split view
/split 2Shows two services side-by-side in the terminal. Use Tab to switch focus, arrow keys to scroll each column independently.
┌── React ─────────────────┬── FastAPI ────────────────┐
│ button clicked (×1) │ fetching users from db │
│ out GET /api/users 200 │ in GET /api/users 200 │
│ button clicked (×2) │ returning 3 users │
└──────────────────────────┴───────────────────────────┘HTTP log API
Query your live log stream from any tool — curl, LLM, CI script:
curl localhost:4242/logs # all recent logs
curl localhost:4242/errors # errors + 5xx only
curl localhost:4242/slow?ms=200 # requests over 200ms
curl localhost:4242/search?q=userId # full-text search
curl localhost:4242/trace?url=/api/users # full request trace
curl localhost:4242/sources # per-source health
curl localhost:4242/timeline?since=5m
curl localhost:4242/repeat?min=3 # repeated messagesAdd ?format=text to any endpoint for plain-text output (no ANSI codes).
RAG / LLM pipeline visibility
from tablog.langchain import TablogCallbackHandler
handler = TablogCallbackHandler()[RAGApp] retrieve "what is the refund policy?" 5 results top=0.91 38ms
[RAGApp] rerank 10→3 results 12ms
[RAGApp] prompt 2100 tokens 3 chunks
[RAGApp] generate gpt-4o 1240ms 2100→187 tokensQuery quality issues via the API:
curl localhost:4242/rag/quality # low scores, truncated context, slow generation
curl localhost:4242/rag/slow # slowest pipeline stepsSession export
/exportSaves the full session to tablog-YYYYMMDD-HHMMSS.json (structured) and .log (human-readable, ANSI stripped).
Usage
JavaScript / TypeScript
import { tablog } from 'tablogger'
tablog('user logged in')
tablog('query result:', { rows: 42 })React / browser
import { tablog, init } from 'tablogger'
// Call once at app entry point
init({ source: 'React', network: true })
tablog('component mounted')network: true intercepts all fetch and XHR calls automatically.
Express / Node.js
import { tablog, expressMiddleware } from 'tablogger'
app.use(expressMiddleware()) // captures all incoming requests
app.get('/api/users', (req, res) => {
tablog('fetching users')
res.json({ users })
})Python
from tablog import tablog
tablog('server started')
tablog('query result:', {'rows': 42})FastAPI
from tablog import tablog
from tablog.middleware import TablogMiddleware
app.add_middleware(TablogMiddleware, source='FastAPI')
@app.get('/api/users')
async def get_users():
tablog('fetching users')
return {'users': users}Flask
from tablog.middleware import TablogFlaskMiddleware
TablogFlaskMiddleware(app)LangChain
from tablog.langchain import TablogCallbackHandler
handler = TablogCallbackHandler(source='MyRAGApp')
chain = RetrievalQA.from_chain_type(llm=llm, callbacks=[handler])CLI commands
Start the server:
npx tablogger| Command | Description |
|---------|-------------|
| /tab 1 | Focus on service 1 only |
| /tab 2 | Focus on service 2 only |
| /tab all | Show all sources |
| /split 2 | Side-by-side split view |
| /split off | Exit split view |
| /change | Interactive filter menu (toggle sources, log/network) |
| /copy | Copy recent logs to clipboard |
| /export | Save session to .json + .log |
How it works
┌─────────────┐ tablog() ┌──────────────────────┐
│ React app │ ──────────────► │ │
│ (browser) │ WebSocket │ tablogger terminal │
└─────────────┘ │ ws://localhost:4242 │
│ http://localhost:4242│
┌─────────────┐ tablog() │ │
│ FastAPI │ ──────────────► │ [React] click │
│ (Python) │ WebSocket │ [FastAPI] query │
└─────────────┘ └──────────────────────┘npx tabloggerstarts a WebSocket + HTTP server on port 4242- Every
tablog()call sends a JSON message over WebSocket - The CLI renders messages with colored
[Source]labels - Network middleware captures HTTP request/response metadata on both sides
- Frontend
outrequests are correlated with backendinresponses
Configuration
tablog.config.json is auto-generated on first run (gitignored):
{
"services": [
{ "name": "Vite", "port": 5173, "role": "frontend" },
{ "name": "FastAPI", "port": 8000, "role": "backend" }
]
}Delete it and re-run npx tablogger to re-detect services.
Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| TABLOG_PORT | 4242 | WebSocket + HTTP server port |
| TABLOG_SOURCE | auto-detected | Override source label |
License
MIT
