Show HN: FileKitty – Combine and label text files for LLM prompt contexts

https://github.com/banagale/FileKitty

FileKitty Homebrew

A macOS utility for selecting, combining, and copying the contents of files — ideal for use with LLMs and generative AI tools. FileKitty lets you grab context from multiple files with one click and keeps a full history of your selections.


Why FileKitty?

LLM tools like Cursor, GitHub Copilot Chat, and Claude Code are powerful — but behind the scenes, they often make API completion requests using bloated, overstuffed prompts. These include entire repos, unrelated files, and boilerplate-heavy context, which can degrade the quality of even state-of-the-art models.

FileKitty gives you control over the prompt. It’s a lightweight tool for assembling precise, readable context that pairs perfectly with interactive (chat-based) LLM workflows — whether you're using ChatGPT, Claude, Gemini, or any number of local models.

FileKitty helps you:

  • For coding: Select only the files, classes, or functions you're working on — and get direct, targeted suggestions instead of vague completions.
  • For documentation and planning: Combine real code with Slack threads, meeting notes, or config files to produce accurate explanations, writeups, and planning docs.
  • For debugging and support: Isolate logs, config diffs, and source snippets into a focused prompt — no need to paste in your whole project.

Unlike IDE-native assistants that guess behind the scenes, FileKitty lets you see and shape exactly what the model sees. You get cleaner inputs, smarter outputs, and fewer wasted tokens.

What it lacks in IDE integration, it makes up for in speed, precision, and higher-quality problem solving.


Use Cases

  • Gather code snippets for LLM prompts (ChatGPT, Claude, Gemini, Copilot, etc.)
  • Provide precise multi-file context for generative AI tools
  • Combine logs, configs, or structured docs for inspection
  • Track and revisit prior file selections and outputs

Quick Install (macOS via Homebrew)

brew install banagale/filekitty/filekitty

Launch the App

  • From Terminal:
  • Or via Finder:
    open /opt/homebrew/opt/filekitty/FileKitty.app

Make it a Regular Mac App

To access via Spotlight or Launchpad, copy the app to /Applications:

ditto /opt/homebrew/opt/filekitty/FileKitty.app /Applications/FileKitty.app

Note: Using ditto rather than cp preserves the application bundle's icon and metadata.


Manual Build (Alternative)

Install Poetry and build locally:

git clone https://github.com/banagale/FileKitty.git
cd FileKitty
poetry install
poetry run python setup.py py2app

The app will be created in ./dist/. Copy it to /Applications for full integration.

Manual builds are useful for development or Linux/Windows adaptation.


Example Output

Here’s what FileKitty produces when you drop a folder or select multiple files. The result is a clean, timestamped view of file contents, optionally preceded by a project folder tree.

Below, we’ve selected three Python files from a project:

The output looks like this inside FileKitty’s preview pane:

# Folder Tree of ~/code/…/FileKitty/src/filekitty
```text
filekitty/
├── core/
│   ├── qt_imports.py
├── resources/
├── ui/
│   ├── __pycache__/
│   ├── components/
│   ├── dialogs.py
│   ├── main_window.py
│   ├── qt_widgets.py
│   ├── text_output_area.py
│   └── tree_settings_dialog.py
├── __main__.py
├── app_logic.py
├── constants.py
└── ...
```
# \~/code/…/filekitty/**main**.py
**Last modified: May 20, 2025 5:07 PM**
```python
from filekitty.app_logic import main
if __name__ == "__main__":
    main()
```
# \~/code/…/filekitty/constants.py
**Last modified: Jun 3, 2025 10:26 AM**
```python
from pathlib import Path
ICON_PATH = str((Path(__file__).parent / "resources/icon/FileKitty-icon.png").resolve())
SETTINGS_FILE_IGNORE_KEY = "mainOutputIgnoreRegex"
...
```
# ~/code/…/filekitty/ui/main_window.py
**Last modified: Jun 5, 2025 12:54 PM**
```python
class FilePicker(QWidget):
    def __init__(self, initial_files=None):
        ...

How to Use

  1. Open the app
  2. Select Files or drag-and-drop files from Finder, PyCharm, etc.
  3. Combined contents will appear, grouped in Markdown code blocks.
  4. Click Copy to Clipboard and paste into your LLM or chat.

History Navigation

  • Back/Forward buttons let you navigate prior selections
  • Changes to file contents are detected and marked as (Modified) or (Missing Files)

Python Symbol Mode

  • When .py files are selected, use Select Classes/Functions to target specific symbols and relevant imports.

Refreshing

  • Click Refresh to reload the current selection, useful after editing source files.

Preferences

Access via FileKitty → Preferences (Cmd+,):

  • Default Select Directory – sets initial folder for file dialog
  • History Location – controls where snapshot state is stored

Developer & Contributor Guide

Local Setup

git clone https://github.com/banagale/FileKitty.git
cd FileKitty
poetry install
  • The app can be manually built using:

    poetry run python setup.py py2app

    The resulting .app bundle appears in ./dist/.

  • Run the app directly with:


Prerequisites

Before building or releasing, make sure you have:

  • macOS (required for app build)
  • Poetry installed
  • Homebrew - only required for formula validation using filekitty-validate. Must be available in your PATH.

Release & Validation helpers

FileKitty ships two developer tools for publishing new versions:

Command What it does
poetry run filekitty-release Interactive release assistant: verifies version consistency, builds the app, zips it, generates a .sha256, shows a changelog, tags the release, and outputs GitHub/Homebrew update instructions.
poetry run filekitty-validate Post-release checker: ensures the pushed tag exists, the ZIP file matches the hash, and the Homebrew formula matches the release metadata.

Tip: Add --dry-run to simulate the release without making changes.


Linting & Formatting

Run linting and formatting tools:

Or directly with Poetry:

poetry run ruff check .
poetry run ruff format .

Pre-commit Hooks

Set up automatic checks before commits:

pre-commit install
pre-commit run --all-files

Continuous Integration

  • GitHub Actions validate builds and style checks on each push.
  • See .github/workflows/ for automation details.

License

MIT License © Rob Banagale

{
"by": "bredren",
"descendants": 21,
"id": 40226976,
"kids": [
40230373,
40231132,
40232792,
40235036,
40253694,
40231422,
40230233,
40230855,
40226992
],
"score": 69,
"time": 1714587003,
"title": "Show HN: FileKitty – Combine and label text files for LLM prompt contexts",
"type": "story",
"url": "https://github.com/banagale/FileKitty"
}
{
"author": "banagale",
"date": null,
"description": "GUI for selecting text files for concatenation and submission to LLMs - banagale/FileKitty",
"image": "https://opengraph.githubassets.com/c9314c145b58b2ce2be314ea733c52b248d143a7945d74362f388a9562acb146/banagale/FileKitty",
"logo": "https://logo.clearbit.com/github.com",
"publisher": "GitHub",
"title": "GitHub - banagale/FileKitty: GUI for selecting text files for concatenation and submission to LLMs",
"url": "https://github.com/banagale/FileKitty"
}
{
"url": "https://github.com/banagale/FileKitty",
"title": "GitHub - banagale/FileKitty: GUI for selecting text files for concatenation and submission to LLMs",
"description": "FileKitty A macOS utility for selecting, combining, and copying the contents of files — ideal for use with LLMs and generative AI tools. FileKitty lets you grab context from multiple files with one click...",
"links": [
"https://github.com/banagale/FileKitty"
],
"image": "https://opengraph.githubassets.com/c9314c145b58b2ce2be314ea733c52b248d143a7945d74362f388a9562acb146/banagale/FileKitty",
"content": "<div><article><div><h2>FileKitty <a target=\"_blank\" href=\"https://github.com/banagale/filekitty#quick-install-macos-via-homebrew\"><img src=\"https://camo.githubusercontent.com/df7ae05690f131a490997a7fa0499adfc87300486059ddcb3b1a24fffd2709df/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f627265772d696e7374616c6c2d677265656e\" alt=\"Homebrew\" /></a></h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#filekitty-\"></a></div>\n<a target=\"_blank\" href=\"https://private-user-images.githubusercontent.com/1409710/327196008-d7c68e71-5245-499b-8be9-3ca1f88adc1b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTA1ODY1NjcsIm5iZiI6MTc1MDU4NjI2NywicGF0aCI6Ii8xNDA5NzEwLzMyNzE5NjAwOC1kN2M2OGU3MS01MjQ1LTQ5OWItOGJlOS0zY2ExZjg4YWRjMWIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA2MjJUMDk1NzQ3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZjQ5ZTI1ZTZlZDgyYzUxYmI4ZjM3N2U4ZGNmYTcxYWIxMjQ4M2JjMjY0OGEzMWZjM2UzOGI5YjlhZDVmZGMwNSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.0nnvglCj47iD6zXCl1Q6rT4ilfXEmPHugo9aJfDuT94\"><img src=\"https://private-user-images.githubusercontent.com/1409710/327196008-d7c68e71-5245-499b-8be9-3ca1f88adc1b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTA1ODY1NjcsIm5iZiI6MTc1MDU4NjI2NywicGF0aCI6Ii8xNDA5NzEwLzMyNzE5NjAwOC1kN2M2OGU3MS01MjQ1LTQ5OWItOGJlOS0zY2ExZjg4YWRjMWIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA2MjJUMDk1NzQ3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZjQ5ZTI1ZTZlZDgyYzUxYmI4ZjM3N2U4ZGNmYTcxYWIxMjQ4M2JjMjY0OGEzMWZjM2UzOGI5YjlhZDVmZGMwNSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.0nnvglCj47iD6zXCl1Q6rT4ilfXEmPHugo9aJfDuT94\" /></a>\n<p>A macOS utility for selecting, combining, and copying the contents of files — ideal for use with <strong>LLMs and generative AI tools</strong>. FileKitty lets you\ngrab context from multiple files with one click and keeps a full history of your selections.</p>\n<hr />\n<p></p><h2>Why FileKitty?</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#why-filekitty\"></a><p></p>\n<p>LLM tools like <strong>Cursor</strong>, <strong>GitHub Copilot Chat</strong>, and <strong>Claude Code</strong> are powerful — but behind the scenes, they often make API completion requests\nusing <strong>bloated, overstuffed prompts</strong>. These include entire repos, unrelated files, and boilerplate-heavy context, which can <strong>degrade the quality of\neven state-of-the-art models.</strong></p>\n<p><strong>FileKitty gives you control over the prompt.</strong> It’s a lightweight tool for assembling precise, readable context that pairs perfectly with\ninteractive (chat-based) LLM workflows — whether you're using <strong>ChatGPT</strong>, <strong>Claude</strong>, <strong>Gemini</strong>, or any number of <strong>local models</strong>.</p>\n<p></p><h3>FileKitty helps you:</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#filekitty-helps-you\"></a><p></p>\n<ul>\n<li><strong>For coding:</strong> Select only the files, classes, or functions you're working on — and get direct, targeted suggestions instead of vague completions.</li>\n<li><strong>For documentation and planning:</strong> Combine real code with Slack threads, meeting notes, or config files to produce accurate explanations, writeups,\nand planning docs.</li>\n<li><strong>For debugging and support:</strong> Isolate logs, config diffs, and source snippets into a focused prompt — no need to paste in your whole project.</li>\n</ul>\n<p>Unlike IDE-native assistants that guess behind the scenes, FileKitty lets you <strong>see and shape exactly what the model sees.</strong> You get cleaner inputs,\nsmarter outputs, and fewer wasted tokens.</p>\n<p>What it lacks in IDE integration, it makes up for in <strong>speed, precision, and higher-quality problem solving.</strong></p>\n<hr />\n<p></p><h2>Use Cases</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#use-cases\"></a><p></p>\n<ul>\n<li>Gather code snippets for LLM prompts (ChatGPT, Claude, Gemini, Copilot, etc.)</li>\n<li>Provide precise multi-file context for generative AI tools</li>\n<li>Combine logs, configs, or structured docs for inspection</li>\n<li>Track and revisit prior file selections and outputs</li>\n</ul>\n<hr />\n<p></p><h2>Quick Install (macOS via Homebrew)</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#quick-install-macos-via-homebrew\"></a><p></p>\n<div><pre>brew install banagale/filekitty/filekitty</pre></div>\n<p></p><h3>Launch the App</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#launch-the-app\"></a><p></p>\n<ul>\n<li>From Terminal:\n</li>\n<li>Or via Finder:\n<div><pre>open /opt/homebrew/opt/filekitty/FileKitty.app</pre></div>\n</li>\n</ul>\n<p></p><h3>Make it a Regular Mac App</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#make-it-a-regular-mac-app\"></a><p></p>\n<p>To access via Spotlight or Launchpad, copy the app to <code>/Applications</code>:</p>\n<div><pre>ditto /opt/homebrew/opt/filekitty/FileKitty.app /Applications/FileKitty.app</pre></div>\n<p><strong>Note:</strong> Using <code>ditto</code> rather than <code>cp</code> preserves the application bundle's icon and metadata.</p>\n<hr />\n<p></p><h2>Manual Build (Alternative)</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#manual-build-alternative\"></a><p></p>\n<p>Install <a target=\"_blank\" href=\"https://python-poetry.org/\">Poetry</a> and build locally:</p>\n<div><pre>git clone https://github.com/banagale/FileKitty.git\n<span>cd</span> FileKitty\npoetry install\npoetry run python setup.py py2app</pre></div>\n<p>The app will be created in <code>./dist/</code>. Copy it to <code>/Applications</code> for full integration.</p>\n<p>Manual builds are useful for development or Linux/Windows adaptation.</p>\n<hr />\n<p></p><h2>Example Output</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#example-output\"></a><p></p>\n<p>Here’s what FileKitty produces when you drop a folder or select multiple files. The result is a clean, timestamped view of file contents, optionally\npreceded by a project folder tree.</p>\n<p>Below, we’ve selected three Python files from a project:</p>\n<a target=\"_blank\" href=\"https://private-user-images.githubusercontent.com/1409710/451993444-a03bce43-0924-4d95-a91b-84b6c66ccb4a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTA1ODY1NjcsIm5iZiI6MTc1MDU4NjI2NywicGF0aCI6Ii8xNDA5NzEwLzQ1MTk5MzQ0NC1hMDNiY2U0My0wOTI0LTRkOTUtYTkxYi04NGI2YzY2Y2NiNGEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA2MjJUMDk1NzQ3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NDIxN2E0Y2M0NjdlYzRlMjQwZjE2Nzc3Y2I3M2YzODk1MTA3NzVhYzFiOWU0MmNjYmIxZWE5OThhYWExZTkyNiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.cdptmzTetZmj-nR17_BUepZ5B8jZuh9qeoNlIPIyOqk\"><img src=\"https://private-user-images.githubusercontent.com/1409710/451993444-a03bce43-0924-4d95-a91b-84b6c66ccb4a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTA1ODY1NjcsIm5iZiI6MTc1MDU4NjI2NywicGF0aCI6Ii8xNDA5NzEwLzQ1MTk5MzQ0NC1hMDNiY2U0My0wOTI0LTRkOTUtYTkxYi04NGI2YzY2Y2NiNGEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDYyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA2MjJUMDk1NzQ3WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NDIxN2E0Y2M0NjdlYzRlMjQwZjE2Nzc3Y2I3M2YzODk1MTA3NzVhYzFiOWU0MmNjYmIxZWE5OThhYWExZTkyNiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.cdptmzTetZmj-nR17_BUepZ5B8jZuh9qeoNlIPIyOqk\" /></a>\n<p>The output looks like this inside FileKitty’s preview pane:</p>\n<div><pre><span># <span>Folder Tree of <span>~</span>/code/…/FileKitty/src/filekitty</span></span>\n<span>```</span><span>text</span><span></span>\n<span>filekitty/</span>\n<span>├── core/</span>\n<span>│ ├── qt_imports.py</span>\n<span>├── resources/</span>\n<span>├── ui/</span>\n<span>│ ├── __pycache__/</span>\n<span>│ ├── components/</span>\n<span>│ ├── dialogs.py</span>\n<span>│ ├── main_window.py</span>\n<span>│ ├── qt_widgets.py</span>\n<span>│ ├── text_output_area.py</span>\n<span>│ └── tree_settings_dialog.py</span>\n<span>├── __main__.py</span>\n<span>├── app_logic.py</span>\n<span>├── constants.py</span>\n<span>└── ...</span>\n<span></span><span>```</span>\n<span># <span><span>\\~</span>/code/…/filekitty/<span>**</span>main<span>**</span>.py</span></span>\n<span>**</span>Last modified: May 20, 2025 5:07 PM<span>**</span>\n<span>```</span><span>python</span>\n<span>from</span> filekitty.app_logic <span>import</span> main\n<span>if</span> <span>__name__</span> <span>==</span> <span><span>\"</span>__main__<span>\"</span></span>:\n main()\n<span>```</span>\n<span># <span><span>\\~</span>/code/…/filekitty/constants.py</span></span>\n<span>**</span>Last modified: Jun 3, 2025 10:26 AM<span>**</span>\n<span>```</span><span>python</span>\n<span>from</span> pathlib <span>import</span> Path\n<span>ICON_PATH</span> <span>=</span> <span>str</span>((Path(<span>__file__</span>).parent <span>/</span> <span><span>\"</span>resources/icon/FileKitty-icon.png<span>\"</span></span>).resolve())\n<span>SETTINGS_FILE_IGNORE_KEY</span> <span>=</span> <span><span>\"</span>mainOutputIgnoreRegex<span>\"</span></span>\n<span>...</span>\n<span>```</span>\n<span># <span><span>~</span>/code/…/filekitty/ui/main_window.py</span></span>\n<span>**</span>Last modified: Jun 5, 2025 12:54 PM<span>**</span>\n<span>```</span><span>python</span>\n<span>class</span> <span>FilePicker</span>(<span>QWidget</span>):\n <span>def</span> <span>__init__</span>(<span><span>self</span></span>, <span>initial_files</span><span>=</span><span>None</span>):\n <span>...</span></pre></div>\n<p></p><h2>How to Use</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#how-to-use\"></a><p></p>\n<ol>\n<li><strong>Open the app</strong></li>\n<li><strong>Select Files</strong> or drag-and-drop files from Finder, PyCharm, etc.</li>\n<li>Combined contents will appear, grouped in Markdown code blocks.</li>\n<li>Click <strong>Copy to Clipboard</strong> and paste into your LLM or chat.</li>\n</ol>\n<p></p><h3>History Navigation</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#history-navigation\"></a><p></p>\n<ul>\n<li>Back/Forward buttons let you navigate prior selections</li>\n<li>Changes to file contents are detected and marked as <code>(Modified)</code> or <code>(Missing Files)</code></li>\n</ul>\n<p></p><h3>Python Symbol Mode</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#python-symbol-mode\"></a><p></p>\n<ul>\n<li>When <code>.py</code> files are selected, use <strong>Select Classes/Functions</strong> to target specific symbols and relevant imports.</li>\n</ul>\n<p></p><h3>Refreshing</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#refreshing\"></a><p></p>\n<ul>\n<li>Click <strong>Refresh</strong> to reload the current selection, useful after editing source files.</li>\n</ul>\n<p></p><h3>Preferences</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#preferences\"></a><p></p>\n<p>Access via <strong>FileKitty → Preferences</strong> (<code>Cmd+,</code>):</p>\n<ul>\n<li><strong>Default Select Directory</strong> – sets initial folder for file dialog</li>\n<li><strong>History Location</strong> – controls where snapshot state is stored</li>\n</ul>\n<hr />\n<p></p><h2>Developer &amp; Contributor Guide</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#developer--contributor-guide\"></a><p></p>\n<p></p><h3>Local Setup</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#local-setup\"></a><p></p>\n<div><pre>git clone https://github.com/banagale/FileKitty.git\n<span>cd</span> FileKitty\npoetry install</pre></div>\n<ul>\n<li>\n<p>The app can be manually built using:</p>\n<div><pre>poetry run python setup.py py2app</pre></div>\n<p>The resulting <code>.app</code> bundle appears in <code>./dist/</code>.</p>\n</li>\n<li>\n<p>Run the app directly with:</p>\n</li>\n</ul>\n<hr />\n<p></p><h3>Prerequisites</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#prerequisites\"></a><p></p>\n<p>Before building or releasing, make sure you have:</p>\n<ul>\n<li>macOS (required for app build)</li>\n<li><a target=\"_blank\" href=\"https://python-poetry.org/\">Poetry</a> installed</li>\n<li><strong>Homebrew</strong> - only required for formula validation using filekitty-validate. Must be available in your PATH.</li>\n</ul>\n<hr />\n<p></p><h3>Release &amp; Validation helpers</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#release--validation-helpers\"></a><p></p>\n<p>FileKitty ships two developer tools for publishing new versions:</p>\n<table>\n<thead>\n<tr>\n<th>Command</th>\n<th>What it does</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>poetry run filekitty-release</code></td>\n<td>Interactive release assistant: verifies version consistency, builds the app, zips it, generates a <code>.sha256</code>, shows a changelog, tags the release, and outputs GitHub/Homebrew update instructions.</td>\n</tr>\n<tr>\n<td><code>poetry run filekitty-validate</code></td>\n<td>Post-release checker: ensures the pushed tag exists, the ZIP file matches the hash, and the Homebrew formula matches the release metadata.</td>\n</tr>\n</tbody>\n</table>\n<blockquote>\n<p>Tip: Add <code>--dry-run</code> to simulate the release without making changes.</p>\n</blockquote>\n<hr />\n<p></p><h3>Linting &amp; Formatting</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#linting--formatting\"></a><p></p>\n<p>Run linting and formatting tools:</p>\n<p>Or directly with Poetry:</p>\n<div><pre>poetry run ruff check <span>.</span>\npoetry run ruff format <span>.</span></pre></div>\n<hr />\n<p></p><h3>Pre-commit Hooks</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#pre-commit-hooks\"></a><p></p>\n<p>Set up automatic checks before commits:</p>\n<div><pre>pre-commit install\npre-commit run --all-files</pre></div>\n<hr />\n<p></p><h3>Continuous Integration</h3><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#continuous-integration\"></a><p></p>\n<ul>\n<li>GitHub Actions validate builds and style checks on each push.</li>\n<li>See <code>.github/workflows/</code> for automation details.</li>\n</ul>\n<p></p><h2>License</h2><a target=\"_blank\" href=\"https://github.com/banagale/FileKitty#license\"></a><p></p>\n<p>MIT License © Rob Banagale</p>\n</article></div>",
"author": "",
"favicon": "https://github.githubassets.com/favicons/favicon.svg",
"source": "github.com",
"published": "",
"ttr": 170,
"type": "object"
}