{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreihbh5lu5wcpfgpl3yvz7zyrnrzadw6czscqmkziaceu6yb5t2dfk4",
    "uri": "at://did:plc:wszrgoqdwy3i2dfeub2mt3wf/app.bsky.feed.post/3lphlib5znej2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibk7ilcb5quri2t525amggpz4athfmo466xujf7qb2bl5tiggd75m"
    },
    "mimeType": "image/jpeg",
    "size": 26144
  },
  "description": "Creating a Terminal User Interface (TUI) application to improve the debugging experience with Renovate's debug logs.",
  "path": "/posts/2025/05/18/renovate-pretty-log/",
  "publishedAt": "2025-05-18T17:19:46.000Z",
  "site": "https://www.jvt.me",
  "tags": [
    "blogumentation",
    "renovate",
    "go",
    "ai",
    "Elastic",
    "dependency-management-data",
    "`renovate-graph`",
    "dry run a change locally",
    "the JSON Lines format",
    "`jjj`",
    "olimorris/codecompanion.nvim",
    "Mend",
    "on GitLab"
  ],
  "textContent": "## Renovate's debug logs\n\nI spend a _lot_ of my time working through Renovate's debug logs.\n\nThis may be through Running Renovate in a number of places, such as at work (Elastic), or during my work on dependency-management-data, of which the best data can be collected through `renovate-graph`, a wrapper on top of Renovate.\n\nSometimes it's a case of trying to dry run a change locally or it may be helping an internal customer debug why a PR isn't getting raised, and often requires delving into the debug logs.\n\nRenovate's debug logs are really great, and like many tools, once you've gotten used to reading them and understanding the flow of the tool, you can reason about how Renovate's running very consistently.\n\nThe debug logs are outputted in the JSON Lines format, which means you'll have lines like the following:\n\n\n    {\"name\":\"renovate\",\"hostname\":\"TheColonel\",\"pid\":92906,\"level\":20,\"logContext\":\"MuGSC6XgB19laFx8mGN5C\",\"config\":{},\"msg\":\"File config\",\"time\":\"2024-02-21T18:37:08.087Z\",\"v\":0}\n    // ...\n    {\"name\":\"renovate\",\"hostname\":\"TheColonel\",\"pid\":92906,\"level\":20,\"logContext\":\"MuGSC6XgB19laFx8mGN5C\",\"repository\":\"jamietanna/jamietanna\",\"baseBranch\":\"main\",\"config\":{\"github-actions\":[{\"deps\":[{\"depName\":\"actions/setup-go\",\"commitMessageTopic\":\"{{{depName}}} action\",\"datasource\":\"github-tags\",\"versioning\":\"docker\",\"depType\":\"action\",\"replaceString\":\"actions/setup-go@v2\",\"autoReplaceStringTemplate\":\"{{depName}}@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}\",\"currentValue\":\"v2\",\"updates\":[{\"bucket\":\"major\",\"newVersion\":\"v5\",\"newValue\":\"v5\",\"releaseTimestamp\":\"2023-12-05T16:50:42.000Z\",\"newMajor\":5,\"newMinor\":null,\"updateType\":\"major\",\"branchName\":\"renovate/actions-setup-go-5.x\"}],\"packageName\":\"actions/setup-go\",\"warnings\":[],\"sourceUrl\":\"https://github.com/actions/setup-go\",\"registryUrl\":\"https://github.com\",\"currentVersion\":\"v2\",\"isSingleVersion\":true,\"fixedVersion\":\"v2\"},{\"depName\":\"actions/checkout\",\"commitMessageTopic\":\"{{{depName}}} action\",\"datasource\":\"github-tags\",\"versioning\":\"docker\",\"depType\":\"action\",\"replaceString\":\"actions/checkout@v2\",\"autoReplaceStringTemplate\":\"{{depName}}@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}\",\"currentValue\":\"v2\",\"updates\":[{\"bucket\":\"major\",\"newVersion\":\"v4\",\"newValue\":\"v4\",\"releaseTimestamp\":\"2023-10-17T15:52:30.000Z\",\"newMajor\":4,\"newMinor\":null,\"updateType\":\"major\",\"branchName\":\"renovate/actions-checkout-4.x\"}],\"packageName\":\"actions/checkout\",\"warnings\":[],\"sourceUrl\":\"https://github.com/actions/checkout\",\"registryUrl\":\"https://github.com\",\"currentVersion\":\"v2\",\"isSingleVersion\":true,\"fixedVersion\":\"v2\"},{\"depName\":\"ubuntu\",\"currentValue\":\"latest\",\"replaceString\":\"ubuntu-latest\",\"depType\":\"github-runner\",\"datasource\":\"github-runners\",\"autoReplaceStringTemplate\":\"{{depName}}-{{newValue}}\",\"skipReason\":\"invalid-version\",\"updates\":[],\"packageName\":\"ubuntu\"}],\"packageFile\":\".github/workflows/rebuild.yml\"}]},\"msg\":\"packageFiles with updates\",\"time\":\"2024-02-21T18:37:12.009Z\",\"v\":0}\n    // ...\n    {\"name\":\"renovate\",\"hostname\":\"TheColonel\",\"pid\":92906,\"level\":20,\"logContext\":\"MuGSC6XgB19laFx8mGN5C\",\"repository\":\"deepmap/oapi-codegen\",\"msg\":\"32 flattened updates found: actions/checkout, actions/setup-go, actions/checkout, actions/setup-go, actions/checkout, actions/setup-go, actions/checkout, actions/setup-go, github.com/deepmap/oapi-codegen/v2, github.com/getkin/kin-openapi, github.com/go-chi/chi/v5, github.com/gofiber/fiber/v2, github.com/gorilla/mux, github.com/kataras/iris/v12, github.com/labstack/echo/v4, github.com/lestrrat-go/jwx, github.com/oapi-codegen/runtime, github.com/oapi-codegen/testutil, github.com/getkin/kin-openapi, golang.org/x/tools, gopkg.in/yaml.v2, github.com/deepmap/oapi-codegen/v2, github.com/getkin/kin-openapi, github.com/go-chi/chi/v5, github.com/gofiber/fiber/v2, github.com/gorilla/mux, github.com/kataras/iris/v12, github.com/labstack/echo/v4, github.com/oapi-codegen/nullable, github.com/oapi-codegen/runtime, github.com/oapi-codegen/testutil, gopkg.in/yaml.v2\",\"time\":\"2024-02-21T18:37:16.685Z\",\"v\":0}\n\n\nSo how do you go about trying to read these more human-ly?\n\nWhen I'm dry running locally, I'll start by reaching for a tool I've written, `jjj`, which converts a JSON Lines format to an array of JSON objects, each of which are pretty-printed.\n\nFrom there, I'll read through them with Neovim, with JSON syntax highlighting on, and that seems to work for me.\n\nNaturally at work, we have our Renovate logs ingested into the Elastic Stack, so that'll be my \"first port of call\" to check in on the logs, and do some additional filtering I may need to find what I'm looking for.\n\nBut one thing that I do find slightly annoying with our logs at work is that they include information about things like the Kubernetes cluster Renovate is running on, as well as other information that isn't relevant _in this case_ where I'm trying to debug what's going on.\n\nSo if I'm finding it hard to filter down what I'm looking for, and get the raw metadata that's interesting, I'll end up grabbing a copy of the debug logs for local usage.\n\n## Vibe coding 🤖✨\n\nOn Friday afternoon - after a busy, productive week - I wanted something low-energy to round out the week, and thought that trying to semi-vibe-code something may be a fun way of learning some more about LLMs, as well as getting something productive done.\n\nI'd been looking around for some good Neovim plugins and found olimorris/codecompanion.nvim, and this was in particular a strong contender for getting a chance to see how I could more heavily embed LLMs into my workflow.\n\nSo I ended up thinking - what could I do to make it easier to read through these logs?\n\nOne thing I've very much liked for some time is the way that Mend, the company behind Renovate, has designed the log interface on the Mend Renovate Community Cloud:\n\nFor instance:\n\nI like the way this is presented, and wondered if maybe I could go about building a command-line tool to do effectively the same, with some help from some LLMs 🤖?\n\n## What did I build?\n\nI set about building a CLI tool that would take in a log file, and output each line in a similar means to how Mend Renovate Community Cloud does it.\n\nHowever, as I started working on it, I realised that maybe a standalone tool that spat out the logs to the terminal may not be _as_ useful when there are hundreds of lines of logs.\n\nAs well as the CLI, I set about building a Terminal User Interface (TUI) which would provide more interactive log viewing.\n\nYou can find the final result on GitLab.\n\n## Terminal User Interface\n\n~~There's a lot more scope for what I want the TUI to be able to do, but as a starting point, it can take a log file, output the log lines, and if there's any additional context, allow you to toggle display using the` Enter` key.~~\n\n**Update 2026-03-06** : I've since rewritten this interface, which is demo'd below.\n\nYou can see this in action here:\n\nNotice that when a log line's extra content is expanded, we can scroll in that, too.\n\n## CLI\n\nThis was the first iteration, and it works quite well too, albeit not as helpful when there are lots of logs.\n\nI've left it in the repository, but I'm unlikely to invest as much time in it compared to the TUI, which I feel will have much more value.\n\nYou can see this in action here:\n\n(notice that all the output speeds past!)\n\n## Happy?\n\nIt's taken a bit longer than I'd hoped - partly because of the human involved in the loop - but I am.\n\nAs I started prototyping it, I already found it very useful, and a better way of visualising what's going on - and it even helped me find some interesting things in the debug logs I'd not seen before 😅",
  "title": "Improving the experience of browsing Renovate debug logs",
  "updatedAt": "2026-03-06T15:06:11.000Z"
}