{"id":31736077,"url":"https://github.com/sontungexpt/witch-line","last_synced_at":"2026-01-22T05:09:34.839Z","repository":{"id":317662380,"uuid":"757245575","full_name":"sontungexpt/witch-line","owner":"sontungexpt","description":"A blazing fast statusline for neovim based on reference concept ","archived":false,"fork":false,"pushed_at":"2026-01-21T06:22:09.000Z","size":779,"stargazers_count":53,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-21T17:36:20.774Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sontungexpt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-14T04:59:14.000Z","updated_at":"2026-01-21T06:22:13.000Z","dependencies_parsed_at":"2025-10-02T09:29:07.591Z","dependency_job_id":null,"html_url":"https://github.com/sontungexpt/witch-line","commit_stats":null,"previous_names":["sontungexpt/witch-line"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/sontungexpt/witch-line","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sontungexpt%2Fwitch-line","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sontungexpt%2Fwitch-line/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sontungexpt%2Fwitch-line/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sontungexpt%2Fwitch-line/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sontungexpt","download_url":"https://codeload.github.com/sontungexpt/witch-line/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sontungexpt%2Fwitch-line/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28655242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-09T09:01:32.120Z","updated_at":"2026-01-22T05:09:34.833Z","avatar_url":"https://github.com/sontungexpt.png","language":"Lua","readme":"## witch-line\n\nThe best statusline plugin for neovim. It's very lightweight and super fast.\n\nThis plugin lazy load as much as possible\n\n## Navigation\n\n- 💬 [A Few Words to Say](#a-few-words-to-say)\n  - 💡 [Concept Ideas](#concept-ideas)\n- 🪄 [Preview](#preview)\n- ✨ [Features](#-features)\n  - 📝 [TODO](#todo)\n  - 📊 [Compare with other statusline plugins](#compare-with-other-statusline-plugins)\n  - 📈 [Benchmarks](#benchmarks)\n- ⚙️ [Installation](#installation)\n- 🚀 [Usage](#usage)\n  - 🧱 [Laststatus](#laststatus)\n  - 🧩 [Options](#options)\n  - 🪄 [Commands](#commands)\n- 🧾 [Default Components Reference](#-default-components-reference)\n  - 🔖 [Default Components](#-default-components)\n  - 🛠️ [Customizable Fields for Components](#️-customizable-fields-for-components)\n- 🧠 [Component Structure](#-component-structure)\n- 📚 [Public APIs](#-public-apis)\n- 🤝 [Community Help \u0026 Contributions Wanted](#-community-help--contributions-wanted)\n- 📜 [License](#-license)\n\n## A few words to say\n\n🎉 The default component is written for my personal use. So maybe you need to\ncreate your own component. I'm very happy to see your component. So if you have\nany idea to create a new component, please open an issue or pull request.\n\n### Concept ideas\n\n- I like the reference concept in any database structure based on id. So I use the same concept in this plugin for component system. You can reference other component by id to share some field like events, style, static, context, hidden, min_screen_width. This will help you to create a component based on other component without duplicate code.\n\n- Spoiler this plugin also provide nested tables to inherit from parent by recursively for anyone enjoy with creating a component based on other component by nested table like [heirline](https://github.com/rebelot/heirline.nvim). But I think the reference concept is better. And the statusline is a flat structure and readable.\n\n#### Understand Concept\n\nWhat's is the reference concept.\n\n- I assume that almost people know about [heirline](https://github.com/rebelot/heirline.nvim). It's a well-being statusline framework based on recursion with many nested tables to inherit the value. It's good. But to be honestly, i think it's quite redundant, and some time make the component biggest and hard to maintain. We always retain the deepest nested level is less than 3 for avoiding aweful behavior and hard to control. And almost popular component isn't necessary to create more than 2 level inheritance. So why not make some changes with a flatten component list. That's why reference concept appears.\n\nReference is not a new topic. You meet it in many cases such example: in database a document, a table reference to another by id. In rust we has borrowing, or in C/C++ we has pointer. And now, I move this concept to witch-line component.\n\nSee the magic:\n\n```lua\n  -- We move from\n  -- heirline\n  local Comp = {\n    style = {\n      fg= ...\n    },\n    {\n      provider= ...\n    },\n    {\n      provider= ...\n    },\n  }\n\n\n  -- to witch-line\n  -- You can see the difference and detail about ref field and inherit field in [COOKBOOK](./docs/COOKBOOK.md)\n  local Parent = {\n    id = \"A\"\n    style = ...\n  }\n  local Child1 = {\n    id = \"B\",\n    ref = { -- ref particular field only\n      style = \"A\"\n    }\n  }\n\n  local Child2 = {\n    id  = \"C\",\n    inherit = \"A\"\n  }\n\n\n\n```\n\n## Preview\n\n- Basic style (No separator, I aprreciate basic but you can create it or do many things else by yourself (like add separator) or you can create new PR for your feature you wantc)\n\n\u003cimg width=\"1920\" height=\"1047\" alt=\"image\" src=\"https://github.com/user-attachments/assets/87b8f955-34e6-4410-a2a0-83359f249cfc\" /\u003e\n\n- Individual statusline for each window.\n\n\u003cimg width=\"1918\" height=\"1013\" alt=\"image\" src=\"https://github.com/user-attachments/assets/3ef62280-500c-4266-91d4-2f03d9c08dfb\" /\u003e\n\n- Individual component value for each window.\n\n\u003cimg width=\"1917\" height=\"1041\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6a588a6b-df7b-4749-87c2-fb625133760a\" /\u003e\n\n- Video:\n\nhttps://github.com/user-attachments/assets/241d091f-bfdb-4935-b33d-8c8a2626c2a4\n\n## ✨ Features\n\n`witch-line` is a fast, lightweight, and fully customizable statusline plugin for Neovim. It focuses on modularity, caching, and performance. Below are the key features:\n\n- ⚡ **Blazing Fast**: Optimized with internal caching and minimal redraws to keep your statusline snappy and efficient. Just config for first time and **every thing** will be cache and run super fast later.\n\n- 🧩 **Modular Components**: Define reusable and nested components using a simple configuration format.\n\n- 🎛 **Abstract Components**: Support for abstract components that can be composed and reused without rendering directly.\n\n- 🎨 **Flexible Layouts**: Arrange statusline components in any order, across multiple layers or segments.\n\n- 🔁 **Reactive Updates**: Smart detection of buffer/file changes to update only when necessary.\n\n- 📁 **Context-Aware Disabling**: Automatically disable the statusline for specific `filetypes` or `buftypes` (e.g. terminal, help, etc).\n\n- 🧠 **Config Hashing**: Detect if user config has changed via xxh32 hashing, ensuring minimal reinitialization.\n\n- 💾 **Persistent Caching**: Cache user configurations and state across sessions using a simple key-value system.\n\n- 🧪 **Testable \u0026 Maintainable**: Designed with testability and clear API boundaries in mind.\n\n- 🛠 **Extensible**: Easily extend with custom components.\n\nThis plugin is ideal for developers who want full control over the look and feel of their statusline, without sacrificing performance or flexibility.\n\n---\n\n### TODO\n\n- Laststatus\n\n  - [x] Support for laststatus = 1\n  - [x] Support for laststatus = 2\n  - [x] Support for laststatus = 3\n  - [x] Support for laststatus = 0\n\n- Cache\n\n  - [x] Implement caching mechanism (serialization + deserialization)\n  - [x] Cache all needed data\n  - [x] Use checksum to detect config changes with xxh32\n  - [x] Lazy compile function of component\n  - [x] Detect default component changed automatically when plugin was updated\n  - [ ] Support up-value for component function caching\n  - [ ] Support paritial cache loading\n\n- Customization\n\n  - [x] Support user-defined component\n  - [x] Support override default component by user value\n\n- Component\n\n  - [x] Only update component when needed\n  - [x] Implement component system\n  - [x] Support abstract component\n  - [x] Support nested component\n  - [x] Support ref field to reference other component\n  - [x] Support inherit field to inherit from other component\n  - [x] Support static field to store static data\n  - [x] Support context field to store context data\n  - [x] Support events field to trigger component update\n  - [x] Support timing field to update component periodically\n  - [x] Support lazy field to lazy load component\n  - [x] Support padding field to add padding around component\n  - [x] Support style field to override component style\n  - [x] Support left_style field to override left part style\n  - [x] Support right_style field to override right part style\n  - [x] Support left field to add left content\n  - [x] Support right field to add right content\n  - [x] Support min_screen_width field to hide component if screen width is less than this value\n  - [x] Support hidden field to hide component based on condition\n  - [x] Support init function to initialize component\n  - [x] Support pre_update function to run before update function\n  - [x] Support post_update function to run after update function\n  - [x] Support update function to generate component content\n  - [x] Support ref field to reference other component fields (events, style, static, context, hidden, min_screen_width)\n  - [x] Support version field to manage component cache\n  - [x] Support flexible field to hide component based on priority when space is limited\n  - [x] Support on_click function to handle click events\n  - [x] Support win_individual field to enable individual value for each window\n  - [ ] Support coroutine for update function\n\n- Hide Automatically\n\n  - [x] Implement disable system\n  - [x] Support disable for specific filetypes\n  - [x] Support disable for specific buftypes\n  - [ ] Support for laststatus = 1, 2\n\n- Commands\n\n  - [x] Implement `:Witchline clear_cache` command to clear cache\n  - [x] Implement `:Witchline inspect` command to inspect some information\n\n- Testing\n\n  - [ ] Write unit tests for core functionality\n  - [ ] Write performance benchmarks\n\n- Themes\n\n  - [x] Auto adjust color of components based on theme\n\n- Bug fixs (Will fix soon this important)\n\n  - [x] A probably inheritance logic when conflicting between parent and child happens\n\n### Compare with other statusline plugins\n\n---\n\n### Benchmarks\n\nThe benchmarks of 30 runs:\n\nThis is just an example because I don't have much time to make each statusline with the same ui.\nAnd i'm not sure is it the best config for each statusline.\n\nI just run with the default config of each plugin.\n\nIf some one remake your current statusline with \"witch-line\", could you send me the config of each statusline to make it properly?\n\nThe benchmarks is run with `nvim -u` with only the statusline plugin loaded.\n\n| Plugin     | Load Time (ms)        | Avg Update Time (ms) |\n| ---------- | --------------------- | -------------------- |\n| witch-line | 3.4137 (cached: 2.22) |\n| lualine    | 4.4964                |                      |\n| heirline   | 6.3693                |                      |\n\n---\n\n## Installation\n\n```lua\n    -- lazy\n    {\n        \"sontungexpt/witch-line\",\n        dependencies = {\n            \"nvim-tree/nvim-web-devicons\",\n        },\n        lazy = false, -- Almost component is lazy load by default. So you can set lazy to false\n        opts = {},\n    },\n```\n\n## Usage\n\n### Laststatus\n\nYou should set `laststatus` by yourself. I recommend you set `laststatus` to `3` to be better.\n\n```lua\nvim.o.laststatus = 3\n```\n\n### Options\n\nYou can setup the plugin by calling the `setup` function and passing in a table of options.\n\n```lua\nrequire(\"witch-line\").setup({\n  --- @type CombinedComponent[]\n  abstracts = {\n    \"file.name\",\n    {\n      id = \"file\", -- Abstract component for file-related info\n      padding = { left = 1, right = 1 }, -- Padding around the component\n      static = { some_key = \"some_value\" }, -- Static metadata\n      style = { fg = \"#ffffff\", bg = \"#000000\", bold = true }, -- Style override\n      min_screen_width = 80,          -- Hide if screen width \u003c 80\n    },\n  },\n\n  --- @type CombinedComponent[]\n  statusline = {\n    --- The global statusline components\n    --- Set it to `nil` if you want to use default components in example\n    global = {\n        \"mode\",\n        \"file.name\",\n        \"git.branch\",\n        {\n          id = \"component_id\",               -- Unique identifier\n          padding = { left = 1, right = 1 }, -- Padding around the component\n          static = { some_key = \"some_value\" }, -- Static metadata\n          win_individual = false,\n          timing = false,                 -- No timing updates\n          style = { fg = \"#ffffff\", bg = \"#000000\", bold = true }, -- Style override\n          min_screen_width = 80,          -- Hide if screen width \u003c 80\n          hidden = function()               -- Hide condition\n            return vim.bo.buftype == \"nofile\"\n          end,\n          left_style = { fg = \"#ff0000\" }, -- Left style override\n          update = function(self, ctx, static, session_id) -- Main content generator\n            return vim.fn.expand(\"%:t\")\n          end,\n          ref = {                       -- References to other components\n            events = { \"file.name\" },\n            style = \"file.name\",\n            static = \"file.name\",\n          },\n        },\n    },\n\n    -- @type fun(winid): CombinedComponent[]|nil\n    win = nil\n  },\n\n  cache = {\n      -- You can disable cache here.\n      -- If you enable cache you can not use any up-value in your component functions otherwise your\n      -- cache will be broken.\n      enabled = true,\n      -- Show notification when cache is cleared. Default true.\n      notification = true,\n      -- Strip debug info when caching dumped functions. Default false. Faster but harder to debug.\n      func_strip = false,\n  },\n\n  disabled = {\n    filetypes = { \"help\", \"TelescopePrompt\" },\n    buftypes = { \"nofile\", \"terminal\" },\n  },\n\n  --- Whether to automatically adjust the theme.\n  --- If it is set to false the `auto_theme` field of the component will be ignored.\n  --- Default: true.\n  --- You can toggle it by `:Witchline toggle_auto_theme`\n  auto_theme = true\n\n})\n\n```\n\n#### Top level options\n\n| Field        | Type                                                                     | Description                                                                                                               |\n| ------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |\n| `abstracts`  | `CombinedComponent[]`                                                    | A list of abstract components registered before everything else. Used for component references and dependency resolution. |\n| `statusline` | `{ global: CombinedComponent[], win?: fun(winid): CombinedComponent[] }` | Defines the global statusline and optional per-window statusline overrides.                                               |\n| `cache`      | `{ full_scan: boolean, notification: boolean, func_strip: boolean }`     | Cache behavior and optimizations.                                                                                         |\n| `disabled`   | `{ filetypes: string[], buftypes: string[] }`                            | Filetypes/buftypes where the plugin should be disabled.                                                                   |\n\n#### statusline\n\n| Key      | Type                              | Description                                                                                                                                                                            |\n| -------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `global` | `CombinedComponent[]\\|nil`        | Global statusline components. Set to `nil` if you want to use default components in example.                                                                                           |\n| `win`    | `fun(winid): CombinedComponent[]` | Per-window statusline components. When using this field, you must set `laststatus` to `2` or `1`, and you must add all neccesary components to the `abstracts` field to let it's work. |\n\nExample config using `win` option\n\n```lua\nrequire(\"witch-line\").setup({\n    abstracts = {\n        \"battery\", -- pre register battery to use in win option\n        -- require(\"your custom component\")\n    }\n    statusline = {\n        global = {\n            \"file.name\",\n            \"git.branch\",\n            --- require(\"your custom component\")\n            --- Other components\n        }\n        win = function(winid\n          --- Only show battery in NvimTree window\n          local filetype = vim.bo[vim.api.nvim_win_get_buf(winid)].filetype\n          if filetype == \"NvimTree\" then\n            return {\n                \"battery\",\n                -- require(\"your custom component\")\n            }\n          end\n        end\n    }\n\n})\n```\n\n#### cache\n\n| Key            | Type      | Default | Description                                                   |\n| -------------- | --------- | ------- | ------------------------------------------------------------- |\n| `enabled`      | `boolean` | `true`  | Enable caching.                                               |\n| `notification` | `boolean` | `true`  | Shows a notification when the cache is cleared.               |\n| `func_strip`   | `boolean` | `false` | Strips debug info from dumped functions to reduce cache size. |\n\n#### disabled\n\n| Key         | Type       | Description                                    |\n| ----------- | ---------- | ---------------------------------------------- |\n| `filetypes` | `string[]` | Filetypes where the plugin should be disabled. |\n| `buftypes`  | `string[]` | Buftypes where the plugin should be disabled.  |\n\n### Commands\n\nThe plugin provides the following commands:\n\n- `:Witchline clear_cache` - Clear the plugin's cache.\n- `:Witchline inspect` - Use for debugging and inspecting internal state.\n- `:Witchline toggle_auto_theme` - Toggle automatic theme adjustment.\n\n## 🧾 Default Components Reference\n\nThis section describes the built-in components available in the plugin, their structure, and how to use them.\nEach component is referenced by name and can be composed to build a flexible and performant statusline.\n\n---\n\n### 🔖 Default Components\n\n| Name                  | Module File       | Description                               |\n| --------------------- | ----------------- | ----------------------------------------- |\n| `mode`                | `mode.lua`        | Shows the current Neovim mode             |\n| `file.name`           | `file.lua`        | Displays the filename                     |\n| `file.icon`           | `file.lua`        | Displays an icon for the file             |\n| `file.modifier`       | `file.lua`        | Indicates if the file has unsaved changes |\n| `file.size`           | `file.lua`        | Shows the file size                       |\n| `%=`                  | _(builtin)_       | Separator to align left/right components  |\n| `copilot`             | `ai/copilot.lua`  | Shows Copilot status (if available)       |\n| `windsurf`            | `ai/windsurf.lua` | Shows Codeium status (if available)       |\n| `windsurf.neocodeium` | `ai/windsurf.lua` | Shows Neocodium status (if available)     |\n| `diagnostic.error`    | `diagnostic.lua`  | Shows number of error diagnostics         |\n| `diagnostic.warn`     | `diagnostic.lua`  | Shows number of warning diagnostics       |\n| `diagnostic.info`     | `diagnostic.lua`  | Shows number of info diagnostics          |\n| `diagnostic.hint`     | `diagnostic.lua`  | Shows number of hint diagnostics          |\n| `encoding`            | `encoding.lua`    | Displays file encoding (e.g., utf-8)      |\n| `cursor.pos`          | `cursor.lua`      | Shows the current cursor line/column      |\n| `cursor.progress`     | `cursor.lua`      | Shows the cursor position as a % progress |\n| `lsp.clients`         | `lsp.lua`         | Lists active LSP clients                  |\n| `git.branch`          | `git.lua`         | Shows current Git branch                  |\n| `git.diff.added`      | `git.lua`         | Number of added lines in Git diff         |\n| `git.diff.removed`    | `git.lua`         | Number of removed lines in Git diff       |\n| `git.diff.modified`   | `git.lua`         | Number of changed lines in Git diff       |\n| `datetime`            | `datetime.lua`    | Displays current date and time            |\n| `battery`             | `battery.lua`     | Shows battery status (if applicable)      |\n| `os_uname`            | `os_uname.lua`    | Displays the operating system name        |\n| `nvim_dap`            | `nvim_dap.lua`    | Shows nvim-dap status (if available)      |\n| `search.count`        | `search.lua`      | Shows number of searching value           |\n| `selection.count`     | `selection.lua`   | Shows number of selection zone            |\n\n---\n\n### 🛠️ Customizable Fields for Components\n\nEach component accepts a set of customization fields to control its behavior, style, visibility, and layout.\n\nBelow is a table of all supported fields and their expected types:\n\n| Field              | Type(s)               | Description                                                                       |\n| ------------------ | --------------------- | --------------------------------------------------------------------------------- |\n| `padding`          | `number`, `table`     | Adds padding around the component. Can be a single number or `{ left, right }`.   |\n| `static`           | `any`                 | Any static value or metadata the component wants to keep.                         |\n| `timing`           | `boolean`, `number`   | Enables timing or sets a custom update interval for the component.                |\n| `style`            | `function`, `table`   | Style override for the entire component output (e.g., color, bold).               |\n| `min_screen_width` | `number`              | Hides the component if the screen width is below this threshold.                  |\n| `hidden`           | `function`, `boolean` | Hide condition. If `true` or a function that returns `true`, hides the component. |\n| `left_style`       | `function`, `table`   | Style override applied to the left part of the component.                         |\n| `left`             | `string`, `function`  | Left content to be rendered. Can be a string or a generator function.             |\n| `right_style`      | `function`, `table`   | Style override applied to the right part of the component.                        |\n| `right`            | `string`, `function`  | Right content to be rendered. Can be a string or a generator function.            |\n| `flexible`         | `number`              | Priority for hiding when space is limited. Lower numbers hide first.              |\n\n---\n\nYou can use the `require(\"witch-line.builtin\").comp` builtin function to create a customized version of any default component by specifying overrides for these fields.\n\n```lua\n\nlocal my_component = require(\"witch-line.builtin\").comp(\"file.name\", {\n  padding = { left = 2 },\n  min_screen_width = 60,\n  hidden = function()\n    return vim.bo.buftype == \"nofile\"\n  end,\n  style = { fg = \"#ffffff\", bg = \"#222222\", bold = true },\n})\n```\n\nOr you can also use the [0] field to override the default component.\n\n```lua\nlocal my_component = {\n  [0] = \"file.name\",  -- Inherit from the default file.name component\n  padding = { left = 2 },\n  min_screen_width = 60,\n  hidden = function()\n    return vim.bo.buftype == \"nofile\"\n  end,\n  style = { fg = \"#ffffff\", bg = \"#222222\", bold = true },\n}\n```\n\n---\n\n## 🧠 Component Structure\n\nEach component is represented as a Lua table with various fields that define its behavior, appearance, and interactions. You can read the [COOKBOOK](./docs/COOKBOOK.md) for more examples of component structure.\n\n## 📚 Public APIs\n\nThe plugin exposes a set of public APIs for advanced usage and customization. You can find the API reference in the [API.md](./docs/API.md) file.\n\n## 🤝 Community Help \u0026 Contributions Wanted\n\n`witch-line` is a flexible and powerful statusline plugin for Neovim, but there's still a lot of room to improve and grow. I'm actively seeking help and contributions from the community to make this project even better.\n\nHere are a few areas where your help would be especially appreciated:\n\n- 📘 **API Documentation**\n  Help rewrite and polish the API reference into clear and professional documentation. Better docs will make it easier for others to build powerful custom setups.\n\n- 🧬 **Serialization System**\n  Design and implement a robust system to serialize and deserialize component configurations. This would help cache system work better.\n\n- 🧪 **Component Testing Framework**\n  Improve or design an ergonomic and declarative way to test components individually and ensure they behave consistently in different contexts.\n\n- 📦 **Plugin Ecosystem**\n  You can create new plugin extensions built on top of `witch-line`—such as battery indicators, LSP diagnostics, Git integrations, and more.\n\n- 💡 **Ideas, Feedback, and Bug Reports**\n  Even if you’re not a coder, suggestions, feedback, and bug reports are very welcome.\n\nIf you’re interested in helping, feel free to open an issue, start a discussion, or submit a PR. Let's build something awesome together. 🙏\n\n## 📜 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n","funding_links":[],"categories":["Bars and Lines"],"sub_categories":["Statusline"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsontungexpt%2Fwitch-line","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsontungexpt%2Fwitch-line","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsontungexpt%2Fwitch-line/lists"}