{"id":28939231,"url":"https://github.com/macropower/kat","last_synced_at":"2026-01-21T13:25:36.878Z","repository":{"id":294101587,"uuid":"985006485","full_name":"MacroPower/kat","owner":"MacroPower","description":"TUI and rule-based rendering engine for Kubernetes manifests","archived":false,"fork":false,"pushed_at":"2026-01-19T18:19:11.000Z","size":20773,"stargazers_count":155,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-19T22:54:20.215Z","etag":null,"topics":["devops","helm","kubernetes","kustomize"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MacroPower.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":"2025-05-16T22:28:32.000Z","updated_at":"2026-01-19T18:19:15.000Z","dependencies_parsed_at":"2026-01-09T05:11:23.972Z","dependency_job_id":null,"html_url":"https://github.com/MacroPower/kat","commit_stats":null,"previous_names":["macropower/kat"],"tags_count":49,"template":false,"template_full_name":"MacroPower/go_template","purl":"pkg:github/MacroPower/kat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MacroPower%2Fkat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MacroPower%2Fkat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MacroPower%2Fkat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MacroPower%2Fkat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MacroPower","download_url":"https://codeload.github.com/MacroPower/kat/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MacroPower%2Fkat/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28633757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["devops","helm","kubernetes","kustomize"],"created_at":"2025-06-23T00:07:19.774Z","updated_at":"2026-01-21T13:25:36.860Z","avatar_url":"https://github.com/MacroPower.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"docs/assets/logo.svg\" width=\"200px\"\u003e\u003c/a\u003e\n  \u003ch1 align=\"center\"\u003ekat\u003c/h1\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pkg.go.dev/github.com/macropower/kat\"\u003e\u003cimg alt=\"Go Reference\" src=\"https://pkg.go.dev/badge/github.com/macropower/kat.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/macropower/kat\"\u003e\u003cimg alt=\"Go Report Card\" src=\"https://goreportcard.com/badge/github.com/macropower/kat\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/macropower/kat\"\u003e\u003cimg src=\"https://codecov.io/gh/macropower/kat/graph/badge.svg?token=4TNYTL2WXV\"/\u003e\u003c/a\u003e\n  \u003ca href=\"#-installation\"\u003e\u003cimg alt=\"GitHub Downloads\" src=\"https://img.shields.io/github/downloads/macropower/kat/total\"\u003e\u003c/a\u003e\n  \u003ca href=\"#-installation\"\u003e\u003cimg alt=\"Latest tag\" src=\"https://img.shields.io/github/v/tag/macropower/kat?label=version\u0026sort=semver\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/macropower/kat/blob/main/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/macropower/kat\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n`kat` automatically invokes manifest generators like `helm` or `kustomize`, and provides a persistent, navigable view of rendered resources, with support for live reloading, integrated validation, and more.\n\nIt is made of two main components, which can be used together or independently:\n\n1. A **rule-based engine** for automatically rendering and validating manifests\n2. A **terminal UI** for browsing and debugging rendered Kubernetes manifests\n\nTogether, these deliver a seamless development experience that maintains context and focus while iterating on Helm charts, Kustomize overlays, and other manifest generators.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/assets/demo.gif\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  ❤️ Made with \u003ca href=\"https://github.com/charmbracelet/bubbletea\"\u003ebubble tea\u003c/a\u003e, \u003ca href=\"https://github.com/alecthomas/chroma/\"\u003echroma\u003c/a\u003e, and \u003ca href=\"#-dependencies\"\u003eother amazing libraries\u003c/a\u003e.\n\u003c/p\u003e\n\n## ✨ Features\n\n**🔍️ Manifest browsing**\n\n- Navigate hundreds of resources with fuzzy search and filtering\n- View individual resources in your terminal with syntax highlighting\n\n**⚡️ Live reload**\n\n- Monitor source files with `--watch` for automatic re-rendering\n- Maintain your current context between reloads so you don't lose your place\n- Highlight changes with diff visualization between renders\n\n**🐛 Error handling**\n\n- Surface rendering and validation errors as overlays\n- Works with reload; fix source files and watch errors disappear instantly\n\n**🧪 Tool integration**\n\n- Define profiles for any manifest generator (Helm, Kustomize, CUE, KCL, Jsonnet, etc.)\n- Run tools like `kubeconform` or `kyverno` automatically on rendered manifests\n- Chain multiple tools together with pre and post-render hooks\n\n**🎯 Project detection**\n\n- Select your defined profiles automatically using CEL expressions\n- Match projects based on file contents, structure, or naming patterns\n- Support for project-specific runtime configs via `.katrc.yaml` files\n\n**🔌 Plugin system**\n\n- Add custom keybind-triggered commands for your specific workflows\n- Execute dry-runs, deployments, or any custom tooling without leaving kat\n\n**🤖 MCP server** (Experimental)\n\n- Limit access to irrelevant context, improving performance and reducing cost\n- Force your AI to always follow the same rendering and validation pipeline\n- Enable iterative testing _without_ handing over cluster or command-line access\n\n**🎨 Fully customizable**\n\n- Choose from any available Chroma themes, or define your own\n- Remap any keybinding to match your preferences\n\n## 📦 Installation\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHomebrew\u003c/strong\u003e\u003c/summary\u003e\n\nYou can install `kat` using my [tap](https://github.com/MacroPower/homebrew-tap).\n\nWith `brew`:\n\n```sh\nbrew install macropower/tap/kat --cask\n```\n\nWith your `Brewfile`:\n\n```sh\ntap \"macropower/tap\"\ncask \"kat\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eGo\u003c/strong\u003e\u003c/summary\u003e\n\n```sh\ngo install github.com/macropower/kat/cmd/kat@latest\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDocker\u003c/strong\u003e\u003c/summary\u003e\n\nDocker images are published to [ghcr.io/macropower](https://github.com/MacroPower/kat/pkgs/container/kat).\n\nAll images are configured with `WORKDIR=/data`, so you can mount your current directory there to run `kat` against your local files.\n\nRun the latest alpine image:\n\n```sh\ndocker run -it -v .:/data -e TERM=$TERM ghcr.io/macropower/kat:latest-alpine\n```\n\nThe default config is located at `/config/kat/config.yaml`, and you can override it by mounting your own configuration file at that path.\n\nThere is also a scratch image that contains only the `kat` binary, which is useful when you want to build your own image (which I generally recommend doing):\n\n```dockerfile\nFROM alpine:latest\nCOPY --from=ghcr.io/macropower/kat:latest /kat /usr/local/bin/kat\n# Add whatever customization you need here.\nENTRYPOINT [\"/usr/local/bin/kat\"]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eNix (NUR)\u003c/strong\u003e\u003c/summary\u003e\n\nYou can install `kat` using my [NUR](https://github.com/MacroPower/nur-packages).\n\nWith `nix-env`:\n\n```sh\nnix-env -iA kat -f https://github.com/macropower/nur-packages/archive/main.tar.gz\n```\n\nWith `nix-shell`:\n\n```sh\nnix-shell -A kat https://github.com/macropower/nur-packages/archive/main.tar.gz\n```\n\nWith your `flake.nix`:\n\n```nix\n{\n  inputs = {\n    macropower.url = \"github:macropower/nur-packages\";\n  };\n  # Reference the package as `inputs.macropower.packages.\u003csystem\u003e.kat`\n}\n```\n\nWith [`devbox`](https://www.jetify.com/docs/devbox/):\n\n```sh\ndevbox add github:macropower/nur-packages#kat\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eGitHub CLI\u003c/strong\u003e\u003c/summary\u003e\n\n```sh\ngh release download -R macropower/kat -p \"kat_$(uname -s)_$(uname -m).tar.gz\" -O - | tar -xz\n```\n\nAnd then move `kat` to a directory in your `PATH`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCurl\u003c/strong\u003e\u003c/summary\u003e\n\n```sh\ncurl -s https://api.github.com/repos/macropower/kat/releases/latest | \\\n  jq -r \".assets[] |\n    select(.name | test(\\\"kat_$(uname -s)_$(uname -m).tar.gz\\\")) |\n    .browser_download_url\" | \\\n  xargs curl -L | tar -xz\n```\n\nAnd then move `kat` to a directory in your `PATH`.\n\n\u003c/details\u003e\n\nOr, download a binary from [releases](https://github.com/macropower/kat/releases).\n\n\u003e Note: The default `kat` configuration contains references to `helm`, `kustomize`, and `yq`. If you want to use `kat` with these tools, you will need to install them separately.\n\n## 🔏 Verification\n\nYou can verify the authenticity and integrity of `kat` releases.\n\nSee [verification](docs/verification.md) for more details.\n\n## 🚀 Usage\n\nShow help:\n\n```sh\nkat --help\n```\n\nRender a project in the current directory:\n\n```sh\nkat\n```\n\nRender a project and enable watch (live reloading):\n\n```sh\nkat -w\n```\n\nRender a project in a specific directory:\n\n```sh\nkat ./example/helm\n```\n\nRender a project in a specific directory using the `ks` profile:\n\n```sh\nkat ./example/kustomize ks\n```\n\nRender a project with custom profile arguments:\n\n```sh\nkat ./example/helm -- -g -f prod-values.yaml\n\nkat ./example/kustomize ks -- --enable-helm\n```\n\nRender a project with command passthrough:\n\n```sh\nkat ./example/helm task -- helm:render\n```\n\nRead from stdin (disables rendering engine):\n\n```sh\ncat ./example/kustomize/resources.yaml | kat -\n```\n\nSend output to a file (disables TUI):\n\n```sh\nkat ./example/helm \u003e manifest.yaml\n```\n\nYou can optionally start `kat` with an MCP server by using the `--serve-mcp` flag:\n\n```sh\nkat --serve-mcp :50165\n```\n\n\u003e See [MCP Server](docs/mcp.md) for more details.\n\n## ⚙️ Configuration\n\nWhen you first run `kat`, it will attempt to add default configuration files to `$XDG_CONFIG_HOME/kat/` (or `~/.config/kat/`). This configuration allows you to customize the behavior of `kat`, such as the UI style, keybindings, rules for project detection, and profiles for rendering different types of projects.\n\nNote that JSON schemas are also included in the configuration directory, which can be used by your editor's YAML language server.\n\n\u003e Some of the default behavior around loading configuration can be overridden with command line flags or environment variables. See `kat --help` for details.\n\nOver time, the default configuration may change, and the schema is currently still evolving. If you want to reset your configuration to the latest defaults, you can use `kat --write-config`, which will move your existing configuration to a backup file and generate a new default configuration.\n\n\u003e You can find the default configuration file as well as JSON schemas in [api](api).\n\n## 🛠️ Rules and Profiles\n\nYou can customize how `kat` detects and renders different types of projects using **rules** and **profiles** in the configuration file. This system uses [CEL (Common Expression Language)](https://cel.dev/) expressions to provide flexible file matching and processing.\n\n### 🎯 Rules\n\n**Rules determine which profile should be used.** Each rule contains:\n\n- `match` (required): A CEL expression that returns `true` if the rule should be applied\n- `profile` (required): The name of the profile to use when this rule matches\n\nRules use boolean CEL expressions with access to:\n\n- `files` (list\u003cstring\u003e): All file paths in the directory\n- `dir` (string): The directory path being processed\n\n```yaml\nrules:\n  - # Select the Helm profile if any Helm chart files exist\n    match: \u003e-\n      files.exists(f, pathBase(f) in [\"Chart.yaml\", \"Chart.yml\"])\n    profile: helm\n\n  - # Select the Kustomize profile if any Kustomization files exist\n    match: \u003e-\n      files.exists(f, pathBase(f) in [\"kustomization.yaml\", \"kustomization.yml\"])\n    profile: ks\n\n  - # Fallback: select the YAML profile if any YAML files exist\n    match: \u003e-\n      files.exists(f, pathExt(f) in [\".yaml\", \".yml\"])\n    profile: yaml\n```\n\n### 🎭 Profiles\n\n**Profiles define how to render projects.** They can be automatically selected by rules, or manually specified when `kat` is invoked. Each profile contains:\n\n- `command` (required): The command to execute\n- `args`: Arguments to pass to the command\n- `extraArgs`: Arguments that can be overridden from the CLI\n- `env`: List of environment variables for the command\n- `envFrom`: List of sources for environment variables\n- `source`: Define which files to watch for changes (when watch is enabled)\n- `reload`: Define conditions for when events should trigger a reload\n- `ui`: UI configuration overrides\n- `hooks`: Initialization and rendering hooks\n  - `init` hooks are executed once when `kat` is initialized\n  - `preRender` hooks are executed before the profile's command is run\n  - `postRender` hooks are executed after the profile's command has run, and are provided the rendered output via stdin\n- `plugins`: Custom commands that can be executed on-demand with keybinds\n  - `description` (required): Human-readable description of what the plugin does\n  - `keys` (required): Array of key bindings that trigger the plugin\n  - `command` (required): The command to execute\n  - `args`: Arguments to pass to the command\n\n```yaml\nprofiles:\n  helm:\n    command: helm\n    args: [template, .]\n    extraArgs: [-g]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\", \".tpl\"])\n    reload: \u003e-\n      fs.event.has(fs.WRITE, fs.CREATE, fs.REMOVE)\n    envFrom:\n      - callerRef:\n          pattern: \"^HELM_.+\"\n    ui:\n      theme: dracula\n    hooks:\n      init:\n        - command: helm\n          args: [version, --short]\n      preRender:\n        - command: helm\n          args: [dependency, build]\n          envFrom:\n            - callerRef:\n                pattern: \"^HELM_.+\"\n      postRender:\n        # Pass the rendered manifest via stdin to `kubeconform`.\n        - command: kubeconform\n          args: [-strict, -summary]\n    plugins:\n      dry-run:\n        command: helm\n        args: [install, ., -g, --dry-run]\n        envFrom:\n          - callerRef:\n              pattern: \"^HELM_.+\"\n        description: invoke helm dry-run\n        keys:\n          - code: ctrl+r\n            alias: ⌃r\n\n  ks:\n    command: kustomize\n    args: [build, .]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\"])\n    reload: \u003e-\n      fs.event.has(fs.WRITE, fs.CREATE, fs.REMOVE)\n    env:\n      - name: KUSTOMIZE_ENABLE_ALPHA_COMMANDS\n        value: \"true\"\n    ui:\n      compact: true\n      theme: tokyonight-storm\n    hooks:\n      init:\n        - command: kustomize\n          args: [version]\n```\n\n### 🧩 CEL Functions\n\n`kat` provides custom CEL functions for use in rules and profiles:\n\n**Path Functions:**\n\n- `pathBase(string)`: Returns the filename (e.g., `\"Chart.yaml\"`)\n- `pathExt(string)`: Returns the file extension (e.g., `\".yaml\"`)\n- `pathDir(string)`: Returns the directory path\n\n**YAML Functions:**\n\n- `yamlPath(file, path)`: Reads a YAML file and extracts a value using a JSONPath expression\n\n**Event Functions:**\n\n- `has(event, flag...)`: Checks if a file system event contains specific flags\n\n**File System Constants:**\n\n- `fs.CREATE`, `fs.WRITE`, `fs.REMOVE`, `fs.RENAME`, `fs.CHMOD`: File system event types\n\n**Render Status Constants:**\n\n- `render.STAGE_NONE`, `render.STAGE_PRE_RENDER`, `render.STAGE_RENDER`, `render.STAGE_POST_RENDER`: Render stages\n- `render.RESULT_NONE`, `render.RESULT_OK`, `render.RESULT_ERROR`, `render.RESULT_CANCEL`: Render results\n\nYou can combine these with CEL's built-in functions like `exists()`, `filter()`, `in`, `contains()`, `matches()`, and logical operators.\n\nExample:\n\n```yaml\nrules:\n  - match: \u003e-\n      files.exists(f,\n        pathBase(f) == \"Chart.yaml\" \u0026\u0026\n        yamlPath(f, \"$.apiVersion\") == \"v2\")\n    profile: helm\n\nprofiles:\n  helm:\n    command: helm\n    args: [template, .]\n    extraArgs: [-g]\n    source: \u003e-\n      files.filter(f,\n        pathExt(f) in [\".yaml\", \".yml\", \".tpl\"])\n    reload: \u003e-\n      fs.event.has(fs.WRITE, fs.RENAME) \u0026\u0026\n      render.result != render.RESULT_CANCEL\n```\n\nFor more details on CEL expressions and examples, see the [CEL documentation](docs/CEL.md).\n\n### 🪄 Project Configuration\n\nProjects can include their own `.katrc.yaml` file to define project-specific rules and profiles. For example, you can include a `.katrc.yaml` file at the root of your git repository to share and/or version your project-specific runtime config. When `kat` runs, it searches for this file starting from the target path and walking up the directory tree. If found, the config is merged with your global runtime config, meaning that you can define overrides or extend your global config on a per-project basis.\n\n```yaml\n# yaml-language-server: $schema=https://jacobcolvin.com/kat/schemas/runtimeconfigs.v1beta1.json\napiVersion: kat.jacobcolvin.com/v1beta1\nkind: RuntimeConfig\nprofiles:\n  helm:\n    command: my-custom-helm-wrapper\n    args: [template, .]\n```\n\n\u003e For your safety, when you execute `kat` in a location where a runtime configuration exists, you will be prompted to trust the project. This trust is maintained in a separate `policy.yaml` file in your config directory.\n\nSee the [katrc documentation](docs/katrc.md) for more details.\n\n### 🔥 DRY Configuration\n\nThe `kat` configuration supports YAML [anchor nodes](https://yaml.org/spec/1.2.2/#692-node-anchors), [alias nodes](https://yaml.org/spec/1.2.2/#71-alias-nodes), and [merge keys](https://yaml.org/type/merge.html). You can define common settings once and reuse them across the configuration.\n\n```yaml\nprofiles:\n  ks: \u0026ks\n    command: kustomize\n    args: [build, .]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\"])\n    hooks:\n      postRender:\n        - \u0026kubeconform\n          command: kubeconform\n          args: [-strict, -summary]\n\n  ks-helm:\n    \u003c\u003c: *ks\n    args: [build, ., --enable-helm]\n\n  helm:\n    command: helm\n    args: [template, .]\n    extraArgs: [-g]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\", \".tpl\"])\n    envFrom:\n      - callerRef:\n          pattern: \"^HELM_.+\"\n    hooks:\n      postRender:\n        - *kubeconform\n```\n\n\u003e ❤️ Thanks to [goccy/go-yaml](https://github.com/goccy/go-yaml).\n\n### 📖 Examples\n\n**Default config** - By default, `kat` includes a configuration that supports `helm`, `kustomize`, and generic YAML files. This is a great starting point for writing your own custom config:\n\n- See [`pkg/config/config.yaml`](pkg/config/config.yaml) for the default configuration.\n\n**Support for custom tools** - You can add support for other languages/tools like [`kcl`](https://www.kcl-lang.io/), [`jsonnet`](https://jsonnet.org/), [`flux-local`](https://github.com/allenporter/flux-local), [`cue`](https://cuelang.org/), and so on:\n\n```yaml\nrules:\n  - match: \u003e-\n      files.exists(f, pathExt(f) == \".k\")\n    profile: kcl\nprofiles:\n  kcl:\n    command: kcl\n    args: [run, .]\n    source: \u003e-\n      files.filter(f, pathExt(f) == \".k\")\n    envFrom:\n      - callerRef:\n          pattern: \"^KCL_.+\"\n```\n\n**Content-based detection** - Match based on file content, not just names:\n\n```yaml\nrules:\n  - # Match Helm v3 specifically\n    match: \u003e-\n      files.exists(f,\n        pathBase(f) == \"Chart.yaml\" \u0026\u0026\n        yamlPath(f, \"$.apiVersion\") == \"v2\")\n    profile: helm-v3\n  - # Match Kubernetes resources with specific API versions\n    match: \u003e-\n      files.exists(f,\n        pathExt(f) in [\".yaml\", \".yml\"] \u0026\u0026\n        yamlPath(f, \"$.apiVersion\") in [\"apps/v1\", \"v1\"])\n    profile: yaml\n```\n\n**Reload filtering** - Control when file changes trigger reloads using CEL expressions:\n\n```yaml\nprofiles:\n  helm:\n    command: helm\n    args: [template, .]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\", \".tpl\"])\n    reload: \u003e-\n      fs.event.has(fs.WRITE, fs.RENAME) \u0026\u0026\n      render.result != render.RESULT_CANCEL\n```\n\n**Using Task** - If you use [`task`](https://taskfile.dev), you can use your tasks in the `kat` config:\n\n```yaml\nrules:\n  - match: \u003e-\n      files.exists(f, pathBase(f) in [\"Taskfile.yml\", \"Taskfile.yaml\"])\n    profile: task\nprofiles:\n  task:\n    command: task\n    args: [render]\n    source: \u003e-\n      files.filter(f, pathExt(f) in [\".yaml\", \".yml\"])\n    hooks:\n      postRender:\n        - command: task\n          args: [validate]\n```\n\n\u003e Note that you should write your `task` to:\n\u003e\n\u003e - Output the rendered manifest to stdout, and anything else to stderr.\n\u003e - Tolerate being called from any directory in the project.\n\u003e   - E.g., instead of `./folder`, use `{{joinPath .ROOT_DIR \"folder\"}}`.\n\u003e - Not require any additional arguments to run.\n\u003e   - You can reference `{{.USER_WORKING_DIR}}` to obtain the path that the user invoked `kat` from/with.\n\u003e   - E.g., `vars: { PATH: \"{{.PATH | default .USER_WORKING_DIR}}\" }`\n\u003e\n\u003e If you are concerned about safety (i.e. accidentally calling a task defined by someone else), you can consider not including a rule for `task` and only allowing it to be invoked manually via the CLI args, or you could write a more narrow match expression (e.g. `f.contains(\"/my-org/\")`).\n\n## 🌈 Themes\n\n![Themes](./docs/assets/themes.gif)\n\nConfigure a theme with `--ui-theme`, `KAT_UI_THEME`, or via config:\n\n```yaml\nui:\n  theme: \"dracula\"\n```\n\nYou can optionally set different themes for different profiles:\n\n```yaml\nprofiles:\n  helm:\n    ui:\n      theme: \"dracula\"\n      # ...\n  ks:\n    ui:\n      theme: \"tokyonight-storm\"\n      # ...\n```\n\nWe use [Chroma](https://github.com/alecthomas/chroma/) for theming, so you can use any styles from the [Chroma Style Gallery](https://xyproto.github.io/splash/docs/).\n\nYou can also add your own themes in the config:\n\n```yaml\nui:\n  theme: \"my-custom-theme\"\n  themes:\n    my-custom-theme:\n      styles:\n        background: \"#abb2bf bg:#282c34\"\n        punctuation: \"#abb2bf\"\n        keyword: \"#c678dd\"\n        name: \"bold #e06c75\"\n        comment: \"italic #8b949e\"\n        commentSpecial: \"bold italic #8b949e\"\n        # ...\n```\n\nChroma uses the same syntax as Pygments. Define `ui.themes.[name].styles` as a map of Pygments [Tokens](https://pygments.org/docs/tokens/) to [Styles](http://pygments.org/docs/styles/). You can then reference any theme in `ui.theme` (or by using the corresponding flag / env var).\n\n## 🔍️ Similar Tools\n\nThese projects provided a lot of inspiration (and snippets) for `kat`:\n\n- [k9s](https://github.com/derailed/k9s) - _A terminal UI to interact with your Kubernetes clusters._\n- [bat](https://github.com/sharkdp/bat) - _A `cat(1)` clone with wings._\n- [task](https://github.com/go-task/task) - _A task runner for Go._\n- [glow](https://github.com/charmbracelet/glow) - _Render markdown on the CLI, with pizzazz!_\n- [soft-serve](https://github.com/charmbracelet/soft-serve) - _The mighty, self-hostable Git server for the command line._\n- [wishlist](https://github.com/charmbracelet/wishlist) - _The SSH directory._\n- [viddy](https://github.com/sachaos/viddy) - _A modern `watch` command._\n\n## ❤️ Dependencies\n\n`kat` is built on top of a number of libraries. Here are some of its key dependencies:\n\n- [charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) - _A powerful TUI framework for Go._\n  - ...plus many other fantastic libraries from [_charm_](https://github.com/charmbracelet)\n- [alecthomas/chroma](https://github.com/alecthomas/chroma) - _A general-purpose syntax highlighter in pure Go._\n- [google/cel-go](https://github.com/google/cel-go) - _A fast, portable, and safe expression evaluation engine._\n- [goccy/go-yaml](https://github.com/goccy/go-yaml) - _YAML support for Go._\n- [fsnotify](https://github.com/fsnotify/fsnotify) - _Cross-platform filesystem notifications._\n- [invopop/jsonschema](https://github.com/invopop/jsonschema) - _JSON Schema generation._\n- [santhosh-tekuri/jsonschema](https://github.com/santhosh-tekuri/jsonschema) - _JSON Schema validation._\n- And [more](https://github.com/MacroPower/kat/blob/main/go.mod).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacropower%2Fkat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacropower%2Fkat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacropower%2Fkat/lists"}