Hello, I'm Shrijith. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.
In this tutorial series, I am on a journey to build for myself DBChat - a simple tool for using AI chat to explore and evolve databases.See previous posts to get more context:
- Building DBChat - Explore and Evolve Your DB with Simple Chat (Part 1)
- DBChat: Getting a Toy REPL Going in Golang (Part 2)
- DBChat Part 3 - Configure , Connect & Dump Databases
- Chat With Your DB via DBChat & Gemini (Part 4)
- The Language Server Protocol - Building DBChat (Part 5)
- Making DBChat VSCode Extension - Ping Pong With LSP Backend (Part 6)
- Starting a VSCode Extension UI For DBChat (Part 7)
- Manage TOML Configuration From VSCode Extension - DBChat Part 8
Some screenshots of the working version
The default view for DBChat will look like this:
After selecting a database - we get a chat view:
Now, we will try to get "gmail users" vs "non-gmail users" with the simplest of prompts/requests:
The query is perfect. When I do exec 1 I get exactly the result expected in a table format.
Similar logic works for "get all non-gmail users" query as well.
A More Detailed View Into the DBChat Updates
This code handles communication with an LSP client, likely a language server protocol client in a code editor. Here's a breakdown:
1. Setting the Stage: Configuration and Initialization
- Loading the Config: The code starts by reading the configuration file. This file probably holds settings like database connection strings.
-
Creating the Query Handler: It then sets up the
queryHandler, which is likely responsible for understanding and executing user requests. -
Building the Handler: Finally, it creates the
DBChatHandler, a core component that manages the configuration, query handler, and potentially the database connection.
config, err := utils.LoadConfig()
if err != nil {
log.Printf("Warning: Could not load config: %v", err)
config = &utils.Config{Connections: make(map[string]string)}
}
queryHandler, err := query.NewHandler(config.LLM.GeminiKey)
if err != nil {
log.Printf("Warning: Could not create query handler: %v", err)
}
handler := &DBChatHandler{
config: config,
queryHandler: queryHandler,
}
2. LSP Communication: The Heartbeat
- The LSP Loop: The program enters a continuous loop, constantly listening for messages from the LSP client.
-
Reading Messages: It carefully reads messages from the client, paying close attention to the
Content-Lengthheader to know how much data to expect. - Parsing Messages: Once received, the raw data is transformed into a structured JSON-RPC message, making it easier to understand.
for {
// Read Content-Length header
// ... (code for reading header) ...
// Read message body
// ... (code for reading message body) ...
// Parse JSON-RPC message
var msg JSONRPCMessage
if err := json.Unmarshal(body, &msg); err != nil {
// ... (handle parsing error) ...
}
}
3. Handling Requests: What to Do?
- "ping" Requests: Simple! The program responds with a "pong" to acknowledge the client's ping.
-
"chat" Requests: This is where the action happens.
- The code extracts the user's chat message.
- It hands off this message to the
Evalmethod within theDBChatHandler. This method likely interacts with the database and thequeryHandlerto process the request. - The result of the processing is then packaged into a response and sent back to the client.
switch msg.Method {
case "ping":
response.Result = "pong"
case "chat":
var params struct {
Message string `json:"message"`
}
if err := json.Unmarshal(msg.Params, ¶ms); err != nil {
// ... (handle invalid params) ...
}
log.Printf("Processing chat message: %q", params.Message)
result := handler.Eval(params.Message)
log.Printf("Eval result: %q", result)
response.Result = map[string]interface{}{
"message": result,
}
// ... (handle other methods) ...
}
4. Error Handling and Responses
- Catching Errors: If anything goes wrong – like problems parsingthe message or issues with the database – the program gracefully handles the error and sends an appropriate error message back to the client.
- Sending Responses: Finally, the program crafts the response message in the correct JSON-RPC format and sends it back to the client.
if err := writeResponse(response); err != nil {
log.Printf("Error writing response: %v", err)
}
Conclusion
DBchat now is able to manage database connections, focus on any database, allow making queries in natural languages and finally get good responses in table format based on database contents.
*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.
git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*
Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.
⭐ Star it on GitHub:
HexmosTech
/
git-lrc
Free, Unlimited AI Code Reviews That Run on Commit
AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.
git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.
See It In Action
See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements
git-lrc-intro-60s.mp4
Why
- 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
- 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
- 🔁 Build a habit, ship better code. Regular review → fewer bugs → more robust code → better results in your team.
- 🔗 Why git? Git is universal. Every editor, every IDE, every AI…



Top comments (0)