{"owner":"txn2","repo":"kubefwd","hasSkills":true,"totalSkillsCount":6,"totalTokensCount":13151,"categories":["project-spec","root-instruction","mcp-config","claude-rule"],"hasMcp":true,"mcpConfig":{"mcpServers":{"kubefwd":{"command":"npx","args":["-y","@modelcontextprotocol/server-kubefwd"]}}},"found":["DESIGN.md","docs/llms.txt","smithery.yaml","docs/architecture.md","docs/llms-full.txt","CLAUDE.md"],"skills":{"DESIGN.md":"---\nversion: alpha\nspec: https://github.com/google-labs-code/design.md\nname: kubefwd-docs\ndescription: Local design adoption record for the kubefwd.com documentation site. References txn2/www DESIGN.md as the canonical visual identity for tokens, typography, components, copyright voice, and accessibility rules. Records only the decisions and MkDocs Material learnings that the canonical does not cover.\nupstream:\n  design: https://github.com/txn2/www/blob/master/DESIGN.md\n  tokens: https://github.com/txn2/www/blob/master/tokens.json\nadoption: token-alignment\nstack:\n  generator: MkDocs\n  theme: Material for MkDocs\n  templates: docs/overrides/\n  styles: docs/stylesheets/extra.css\n---\n\n## What is canonical\n\nThe canonical visual identity for txn2 lives in [`txn2/www/DESIGN.md`](https://github.com/txn2/www/blob/master/DESIGN.md) with tokens in [`txn2/www/tokens.json`](https://github.com/txn2/www/blob/master/tokens.json). This file defers to those for everything below. If a value here disagrees with upstream, upstream wins.\n\n| Concern              | Source of truth |\n|----------------------|-----------------|\n| Color palette        | upstream `tokens.json` `color.*` |\n| Typography stack     | upstream `tokens.json` `font.*` |\n| Type scale           | upstream `DESIGN.md` Typography table |\n| Spacing / measure    | upstream `tokens.json` `size.*` |\n| Component contracts  | upstream `DESIGN.md` Components |\n| Voice / copy rules   | upstream `DESIGN.md` Voice and Copy |\n| Accessibility rules  | upstream `DESIGN.md` Do's and Don'ts |\n| Mermaid theme        | upstream `DESIGN.md` `mcp__card--feature` block |\n\nTokens are mirrored as CSS custom properties in `docs/stylesheets/extra.css` `:root`. They are duplicated for runtime use, not as a divergence point. When upstream changes a token, update the value in `extra.css` and ship.\n\n## Adoption level: token alignment\n\nPer the upstream downstream contract, three levels are valid:\n\n1. Reference. Link to upstream, no visual changes.\n2. Token alignment. Keep MkDocs Material, re-skin via `extra.css` against upstream tokens.\n3. Full re-skin. Replace MkDocs Material with custom layouts.\n\nkubefwd runs at **level 2**. The site keeps Material's instant nav, search, sidebar, version selector, code copy, and content extensions. The visual layer is replaced. The homepage is a custom Material template that takes over `block header`, `block container`, and `block footer` for full-bleed treatment.\n\n## File map\n\n| Path | Role |\n|------|------|\n| `mkdocs.yml`                   | Single dark `slate` palette. `font: false` so CSS loads the upstream Google Fonts URL with trimmed axes. |\n| `docs/index.md`                | Stub front matter with `template: home.html`. All homepage HTML lives in the template. |\n| `docs/overrides/main.html`     | Adds the upstream Google Fonts `<link>` plus OG and Twitter meta. Inherited by every page. |\n| `docs/overrides/home.html`     | Custom homepage template. Overrides `block header` (rail), `block tabs` (empty), `block container` (page--home shell with hero, sections, flagship cards, stack, coda), `block footer` (home-footer). |\n| `docs/stylesheets/extra.css`   | All design rules. Two halves: homepage components scoped under `.page--home`, and Material chrome restyle for inner pages via `[data-md-color-scheme=\"slate\"]` variable overrides. |\n\n## Project-specific components\n\nComponents ported from upstream verbatim, with kubefwd content:\n\n- `.rail` (replaces Material `.md-header` on the homepage). Brand links to `./`. Live UTC clock in meta. txn2.com link in meta as `part of <em class=\"serif\">txn2</em> ↗`.\n- `.hero` with three Fraunces rows (kubefwd / kubernetes / port forwards.).\n- `.section`, `.section__index`, `.section__title`.\n- `.flagship__card`. Two cards: `--kubefwd` (TUI mode demo) and a second variant for the API + MCP surfaces. Top accent line animates on hover per upstream spec.\n- `.terminal`, `.terminal__bar`, `.terminal__body` with `.t-prompt`, `.t-ok`, `.t-mute` classes. The only block with shadow.\n- `.stack`, `.stack__row`. Each row links to a real anchor in the docs (architecture/#ip-allocation, advanced-usage/#custom-hosts-file-path, user-guide/#auto-reconnect, user-guide/#interface-overview, api-reference/, mcp-integration/).\n- `.coda` and `.home-footer` (renamed from upstream `.footer` to avoid collision with markdown that uses `class=\"footer\"`; see Learning #5).\n\nComponents from upstream **not used** here, with reason:\n\n- `.mcp__card--feature` and the MCP grid. kubefwd is a single project, not an MCP catalog.\n- The `mcp-data-platform` mermaid hero. Not relevant.\n- The 5-column footer's `sponsors / craig` columns. The kubefwd home-footer has `about / docs / interfaces / code / txn2 / org` columns instead, since this site is project-scoped.\n\nCustom additions specific to kubefwd:\n\n- `home-footer__col--meta` includes a `txn2 / org` panel that backlinks to txn2.com explicitly. Per the org-wide rule that every sister project must clearly link home.\n- All CNCF Landscape mentions on the homepage and in `docs/attributions.md` link to the kubefwd entry on `landscape.cncf.io`. The Landscape listing is a load-bearing credential and earns a real link wherever it appears.\n\n## MkDocs Material learnings\n\nThe upstream is built with Hugo. kubefwd is built with MkDocs Material. The two have different override surfaces, so the same visual outcome requires different mechanics. These are the lessons worth carrying forward when re-skinning the next sister project.\n\n### 1. Override the homepage via a separate template, not via CSS hacks\n\nMkDocs Material's content pipeline wraps every page body in `.md-content__inner` with hard-coded max-widths. Trying to break out with `:has()` selectors or full-bleed hacks inside the markdown body is fragile and fights Material's own layout.\n\nThe pattern that works: create `docs/overrides/home.html` that extends Material's `main.html` and overrides `block container`, `block header`, `block footer`. Set `template: home.html` in `docs/index.md` front matter. Material then renders the homepage with the custom blocks instead of the standard layout. The homepage gets full viewport control without any width-fighting.\n\n```yaml\n# docs/index.md\n---\ntitle: kubefwd\ntemplate: home.html\nhide:\n  - navigation\n  - toc\n  - footer\n---\n```\n\n### 2. Re-skin inner pages via Material variable overrides\n\nMaterial exposes its own design tokens as CSS custom properties on `[data-md-color-scheme=\"slate\"]`. Mapping these to upstream tokens re-skins every inner page automatically without touching their markdown:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-default-bg-color:        var(--ink);\n  --md-default-fg-color:        var(--paper);\n  --md-typeset-a-color:         var(--signal);\n  --md-text-font:               var(--sans);\n  --md-code-font:               var(--mono);\n  /* ...etc */\n}\n```\n\nVerify the body actually carries the attribute (`grep data-md-color-scheme site/getting-started/index.html`). Single-scheme palettes (`palette: scheme: slate`) do emit it. If they ever stop, fall back to `:root`.\n\n### 3. `font: false` to load fonts directly from CSS\n\nMaterial's `font:` directive loads fonts through Google Fonts but without axis control. To get the upstream's exact trimmed payload (Fraunces with `opsz/wght` italic axis, Instrument Sans roman 400-700, JetBrains Mono roman 400-700, **no SOFT axis**), set `font: false` in `mkdocs.yml` and load the upstream Google Fonts URL via a `<link>` in `main.html`'s `extrahead` block. Verify a single `fonts.googleapis.com` request in DevTools.\n\n### 4. Scope every homepage component class under `.page--home`\n\nThe upstream uses `<main class=\"page page--home\">` on its index page and inner pages don't inherit those classes. In MkDocs the same component class names will collide if any markdown happens to use `class=\"terminal\"`, `class=\"footer\"`, `class=\"section\"`, etc. Material's admonitions, tabbed content, and `md_in_html` all generate divs with predictable class names, and contributors will write more.\n\nDiscipline: every homepage component rule must include `.page--home` as an ancestor, OR rename the class with a project-specific prefix (e.g., `home-footer`). The cost of getting this wrong is silent visual breakage on inner pages weeks later when someone uses one of the colliding names.\n\n### 5. Rename `.footer` → `.home-footer`\n\nThe single most common collision. Markdown that includes a literal `<div class=\"footer\">` is plausible and will inherit the homepage's 60px-padded, 5-column-grid footer styling. Rename rather than scope.\n\n### 6. h3 and h4 are technical reference, not display type\n\nInner pages like `api-reference.md` use `### GET /api/health` and `### POST /api/v1/services` as section headings. Rendering these in Fraunces italic display style (the obvious choice for a \"serif headings\" design) makes the API reference unreadable.\n\nThe rule: h1 and h2 stay Fraunces italic for page and section titles. h3 and h4 switch to Instrument Sans bold so technical reference reads as text, not as type. Add a `:has(code)` block that flips any heading containing inline code to JetBrains Mono with signal-orange code text. Add a `@supports not selector(:has(*))` fallback for older browsers.\n\n```css\n.md-typeset h3 {\n  font-family: var(--sans);\n  font-weight: 700;\n  font-size: clamp(18px, 1.6vw, 22px);\n}\n.md-typeset h1:has(code),\n.md-typeset h2:has(code),\n.md-typeset h3:has(code),\n.md-typeset h4:has(code) {\n  font-family: var(--mono);\n  font-style: normal;\n  font-weight: 700;\n}\n```\n\n### 7. Tabbed content nests boxes, fix it\n\nMaterial's `.md-typeset .tabbed-set` defaults to a bordered, backgrounded box. Code blocks inside also default to bordered backgrounded boxes. The result is nested rectangles with cluttered visual hierarchy.\n\nThe fix: strip the `.tabbed-set` background and border. Leave only a bottom underline on `.tabbed-labels`. Let the inner code blocks be the visual statement. Tighten `pre > code` padding to ~14px so single-line install commands don't render as 70px-tall rectangles.\n\n### 8. Mermaid via Material's CSS variables, not via separate init\n\nMkDocs Material includes a Mermaid integration that reads `--md-mermaid-*` CSS variables. Don't bring in `mermaid.esm.mjs` separately like the upstream Hugo site does. Instead, set the variables in the slate scheme block:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-mermaid-node-bg-color:   var(--ink-3);\n  --md-mermaid-node-fg-color:   var(--paper);\n  --md-mermaid-edge-color:      var(--mute);\n  /* ...full list in extra.css */\n}\n```\n\nPlus a `.md-typeset .mermaid` container restyle (dashed border, ink-3 background) for the diagram block itself.\n\n### 9. Guard inline scripts against `navigation.instant`\n\n`navigation.instant` is enabled (`mkdocs.yml`). On every navigation back to the homepage, Material rehydrates the body. Any `setInterval`, `setTimeout`, or event listener registered in an inline `<script>` will register **again**, leaking handles indefinitely.\n\nPattern for the live UTC clock used in the rail and footer:\n\n```html\n<script>\n  (function () {\n    if (window.__kubefwdClock) {\n      window.__kubefwdClock.tick();\n      return;\n    }\n    function tick() { /* ... */ }\n    tick();\n    var handle = setInterval(tick, 30 * 1000);\n    window.__kubefwdClock = { tick: tick, handle: handle };\n  })();\n</script>\n```\n\nThe `tick()` call on re-entry refreshes the displayed time without registering a new interval.\n\n### 10. Drop the light/dark toggle\n\nThe canonical txn2 identity is dark only. Collapse `palette` to a single `scheme: slate`. Remove the `toggle:` blocks. Audit `extra.css` and `index.md` for orphan light-mode references (`hero-logo-light`, `prefers-color-scheme: light`, `kf-green` etc).\n\n### 11. Atmospheric overlays at low z-index\n\n`body::before` (grain) and `body::after` (vignette) are fixed viewport overlays. Place them at `z-index: 1` so they sit above the page background but below the rail (z-50) and skiplink (z-200). Vignette has no blend mode, so a higher z-index would darken interactive chrome.\n\n### 12. What Hugo does that MkDocs cannot match\n\nFor reference when the next sister project chooses its adoption level:\n\n- Hugo can compile tokens.json into CSS custom properties at build time via `resources.Get` + `transform.Unmarshal`. MkDocs has no equivalent. We hand-mirror the tokens in `extra.css` `:root` and update them when upstream changes.\n- Hugo can subscribe to upstream tokens through a small extra.css that imports a generated `:root { --... }` block. MkDocs cannot. Token sync is a manual PR.\n- Hugo's partial system handles header/footer composition naturally. MkDocs uses Material template `{% block %}` overrides, which is similar but constrained to Material's block names (`announce`, `header`, `tabs`, `container`, `content`, `footer`, `scripts`).\n\n## Voice and copy\n\nDefers to upstream. Briefly:\n\n- No em-dashes (U+2014) or en-dashes (U+2013) anywhere, including code comments and template comments. Use commas, periods, colons, parentheses, slashes, hyphens.\n- No AI-tell vocabulary: `seamless`, `leverage`, `comprehensive`, `robust`, `delve`, `unleash`, `elevate`, `embark`, `tapestry`, `not just X but Y`, `as an AI`, `let me X`.\n- Sentence case for body. Lowercase for rail and label text. Title case rare.\n- Section indices: `§ 01 / title` with slash, never an em-dash.\n- Year ranges use a hyphen: `2017-2026`.\n- Verify before commit: `grep -RE \"—|–\" docs/ mkdocs.yml`.\n\n## Updating\n\nWhen the upstream `txn2/www/DESIGN.md` or `tokens.json` changes:\n\n1. Read the upstream diff. Identify which tokens, components, or rules changed.\n2. Update the matching CSS variables in `docs/stylesheets/extra.css` `:root`.\n3. If a component contract changed (padding, border, hover behavior), update the homepage template in `docs/overrides/home.html` and the matching CSS rules.\n4. Update this file's File map / Project-specific components / MkDocs Material learnings sections if a new learning emerges.\n5. Run `mkdocs build --strict` and verify in the browser before committing. Verify the home page hero, flagship cards, terminal, stack, coda, and home-footer. Verify an inner page (`/getting-started/`, `/api-reference/`) still inherits the look.\n\nKeep this file thin. If a section grows past 30 lines, ask whether it belongs upstream instead.\n\n## Downstream contract for sister projects\n\nThis file is canonical only for kubefwd.com. Other sister projects (txeh, mcp-s3, mcp-trino, mcp-datahub, mcp-data-platform) considering the same adoption should:\n\n1. Use this file as a template for their own thin local DESIGN.md.\n2. Reference upstream `txn2/www/DESIGN.md` as the source of truth for tokens, typography, components, voice.\n3. Replace the kubefwd-specific sections (project-specific components, file paths, custom additions) with their own.\n4. Keep the MkDocs Material learnings section. Those apply to every MkDocs Material project.\n5. Update upstream's downstream-contract list when adding a new project.\n","docs/llms.txt":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n## Documentation\n\n- [Getting Started](https://kubefwd.com/getting-started/): Installation, prerequisites, and first forward\n- [User Guide](https://kubefwd.com/user-guide/): Interactive TUI interface and keyboard shortcuts\n- [Configuration](https://kubefwd.com/configuration/): CLI flags, IP reservations, and port mapping\n- [REST API](https://kubefwd.com/api-reference/): Programmatic control via 40+ HTTP endpoints\n- [MCP Integration](https://kubefwd.com/mcp-integration/): AI assistant integration (Claude, Cursor, VS Code)\n\n## Key Features\n\n- **Unique IP per service**: Multiple databases on port 3306 work without conflicts\n- **Auto-reconnect**: Reconnects automatically when pods restart\n- **Interactive TUI**: Browse namespaces, monitor traffic, stream logs\n- **Service name resolution**: Updates /etc/hosts so apps connect by service name\n- **REST API**: Add/remove services dynamically\n- **MCP support**: Natural language control via AI assistants\n\n## Quick Start\n\n```bash\n# Install (macOS)\nbrew install txn2/tap/kubefwd\n\n# Forward services with TUI\nsudo -E kubefwd svc -n my-namespace --tui\n```\n\n## Optional\n\n- [Troubleshooting](https://kubefwd.com/troubleshooting/): Common issues and solutions\n- [Architecture](https://kubefwd.com/architecture/): Technical implementation details\n- [Comparison](https://kubefwd.com/comparison/): vs kubectl port-forward, Telepresence, mirrord\n- [GitHub Repository](https://github.com/txn2/kubefwd): Source code, issues, releases\n","smithery.yaml":"# Smithery.ai MCP Server Configuration\n# https://smithery.ai/docs\n\nstartCommand:\n  type: stdio\n  configSchema:\n    type: object\n    properties:\n      apiUrl:\n        type: string\n        description: \"URL of the kubefwd REST API\"\n        default: \"http://kubefwd.internal/api\"\n    required: []\n  commandFunction: |\n    (config) => ({\n      command: 'kubefwd',\n      args: ['mcp', ...(config.apiUrl ? ['--api-url', config.apiUrl] : [])],\n      env: {}\n    })\n","docs/architecture.md":"# Architecture\n\nHow kubefwd works under the hood.\n\n## Overview\n\nkubefwd establishes port forwards to Kubernetes services by:\n\n1. Discovering services in specified namespaces\n2. Allocating unique local IP addresses (127.x.x.x)\n3. Updating `/etc/hosts` with service hostnames\n4. Creating SPDY connections through the Kubernetes API\n5. Monitoring pod lifecycle for automatic reconnection\n\n```mermaid\nflowchart TB\n    subgraph workstation[\"Your Workstation\"]\n        subgraph kubefwd[\"kubefwd\"]\n            sw[Service Watcher]\n            ip[IP Allocator]\n            hm[Hosts Manager]\n\n            subgraph pfm[\"Port Forward Manager\"]\n                pf1[\"127.1.27.1:8080\"]\n                pf2[\"127.1.27.2:3306\"]\n                pf3[\"127.1.27.3:6379\"]\n            end\n        end\n    end\n\n    subgraph cluster[\"Kubernetes Cluster\"]\n        api[\"api-pod :8080\"]\n        mysql[\"mysql-pod :3306\"]\n        redis[\"redis-pod :6379\"]\n    end\n\n    pf1 -->|SPDY via K8s API| api\n    pf2 -->|SPDY via K8s API| mysql\n    pf3 -->|SPDY via K8s API| redis\n```\n\n## Key Components\n\n### Service Discovery\n\nkubefwd uses Kubernetes **informers** to watch for service events:\n\n- **Add**: New service discovered → start port forward\n- **Update**: Service modified → update port forward if needed\n- **Delete**: Service removed → stop port forward, cleanup hosts\n\nThis event-driven approach means kubefwd reacts in real-time to cluster changes.\n\n### IP Allocation\n\nEach service receives a unique loopback IP address:\n\n```\n127.[1+cluster].[27+namespace].[service_count]\n```\n\n| Component | Base | Range |\n|-----------|------|-------|\n| First octet | 127 | Fixed |\n| Second octet | 1 | 1-255 (cluster index) |\n| Third octet | 27 | 27-255 (namespace index) |\n| Fourth octet | 1 | 1-255 (service count) |\n\n**Why unique IPs?**\n\nUnlike `kubectl port-forward` which uses `localhost:port`, kubefwd assigns each service its own IP. This allows:\n\n- Multiple services on the same port (e.g., several databases on 3306)\n- Realistic service topology matching in-cluster behavior\n- No port conflict management needed\n\n### Hosts File Management\n\nkubefwd modifies `/etc/hosts` to map service names to allocated IPs:\n\n```\n# Before kubefwd\n127.0.0.1       localhost\n\n# After kubefwd starts\n127.0.0.1       localhost\n127.1.27.1      api-service\n127.1.27.2      database\n127.1.27.3      cache\n```\n\n**Safety measures:**\n- Original hosts file backed up to `~/hosts.original`\n- Entries removed on clean shutdown\n- Mutex locking prevents race conditions\n- Stale entry purging available (`-p` flag)\n\n### Port Forwarding\n\nkubefwd creates SPDY connections through the Kubernetes API server:\n\n1. **Pod Selection**: Find pods backing the service\n2. **Connection**: Establish SPDY tunnel via API server\n3. **Local Binding**: Bind to allocated IP and service port(s)\n4. **Data Transfer**: Proxy traffic bidirectionally\n\n```mermaid\nflowchart LR\n    app[Local App] --> ip[\"127.1.27.1:8080\"] --> kf[kubefwd] --> api[K8s API] --> pod[\"Pod:8080\"]\n```\n\n### Pod Lifecycle Monitoring\n\nkubefwd watches pod events to maintain forwarding:\n\n- **Pod deleted**: Stop forward, trigger reconnection\n- **Pod recreated**: Auto-reconnect (if enabled)\n- **Pod crash**: Detect via connection loss, reconnect\n\nThe auto-reconnect feature uses exponential backoff:\n- Initial: 1 second\n- Maximum: 5 minutes\n- Reset on successful connection\n\n## Service Types\n\n### Normal Services (ClusterIP)\n\nFor services with selectors:\n\n1. Query pods matching the selector\n2. Select first available Running pod\n3. Forward to that single pod\n4. Hostname: `service-name`\n\n### Headless Services (ClusterIP: None)\n\nFor services without cluster IP:\n\n1. Query all pods matching the selector\n2. Forward to ALL pods\n3. Hostnames:\n   - `service-name` → first pod\n   - `pod-name.service-name` → each specific pod\n\nThis is essential for StatefulSets and databases requiring pod-specific addressing.\n\n### Services Without Selectors\n\n**Not supported.** kubefwd requires pod selectors to discover backing pods. Services with manually managed Endpoints are skipped.\n\n## TUI Architecture\n\nThe Terminal User Interface uses the [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework:\n\n```mermaid\nflowchart LR\n    subgraph core[\"Core Services\"]\n        eb[Event Bus]\n        ss[State Store]\n        mr[Metrics Registry]\n    end\n\n    subgraph views[\"View Models\"]\n        sm[Services]\n        lm[Logs]\n        dm[Detail]\n    end\n\n    core --> views\n```\n\n### Event Bus\n\nDecoupled communication between components:\n- Service status changes\n- Metrics updates\n- Log messages\n- User actions\n\n### State Store\n\nCentralized, thread-safe state management:\n- Forward status for all services\n- Metrics data (bytes, rates)\n- Filter/sort state\n\n### Metrics Collection\n\nTraffic monitoring with:\n- Byte counters (atomic operations)\n- Rate calculations (rolling window)\n- HTTP request/response detection\n- Sparkline visualization\n\n## Thread Safety\n\nkubefwd handles concurrent operations carefully:\n\n| Resource | Protection |\n|----------|------------|\n| Service registry | RWMutex |\n| IP allocation | Per-namespace mutex |\n| Hosts file | Global mutex with file locking |\n| Metrics | Atomic operations + RWMutex |\n| Event bus | Channel-based with buffer |\n\n## Shutdown Sequence\n\nClean shutdown ensures no leftover state:\n\n1. User signal (q, Ctrl+C) → stop listening\n2. Close service watchers\n3. Stop all port forwards\n4. Remove hosts file entries\n5. Remove network interface aliases\n\nIf shutdown is interrupted, use `-p` to purge stale entries on next run.\n\n## Network Interface Management\n\nkubefwd creates loopback aliases:\n\n**macOS (lo0):**\n```bash\nifconfig lo0 alias 127.1.27.1\n```\n\n**Linux (lo):**\n```bash\nip addr add 127.1.27.1/8 dev lo\n```\n\nThese aliases allow binding to unique IPs while keeping traffic local.\n\n## Security Considerations\n\nkubefwd requires elevated privileges for:\n\n1. **Network interface modification**: Adding IP aliases\n2. **Hosts file modification**: DNS resolution\n3. **Low port binding**: Ports below 1024\n\n**Recommendations:**\n- Run only in development environments\n- Don't run in production workstations with sensitive data\n- Review services before forwarding from production clusters\n- Use label selectors to limit scope\n\n## Performance Characteristics\n\n| Operation | Complexity |\n|-----------|------------|\n| Service discovery | O(services) per namespace |\n| Port forward setup | O(1) per service |\n| Metrics sampling | O(forwards) per second |\n| Hosts file update | O(forwards) per change |\n\nkubefwd is designed for development use with dozens to hundreds of services. For very large clusters, use selectors to limit scope.\n","docs/llms-full.txt":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n---\n\n# Getting Started\n\nThis guide covers installation and your first steps with kubefwd. By the end, you'll have cluster services accessible locally by name.\n\n## Prerequisites\n\n- **kubectl configured** with access to a Kubernetes cluster\n- **Root/sudo access** (required for `/etc/hosts` and network interface modifications)\n\nkubefwd reads your kubeconfig (`~/.kube/config` or `KUBECONFIG` environment variable) and connects directly to the Kubernetes API.\n\n## Installation\n\n### macOS\n\nUsing Homebrew:\n\n```bash\nbrew install txn2/tap/kubefwd\n```\n\n### Windows\n\nUsing Scoop:\n\n```powershell\nscoop install kubefwd\n```\n\nRun as Administrator for hosts file access.\n\n### Linux (Debian/Ubuntu)\n\nDownload the `.deb` package from GitHub Releases:\n\n```bash\nsudo dpkg -i kubefwd_*_amd64.deb\n```\n\n### Linux (RHEL/Fedora)\n\nDownload the `.rpm` package from GitHub Releases:\n\n```bash\nsudo rpm -i kubefwd_*_amd64.rpm\n```\n\n### Docker\n\n```bash\ndocker run -it --rm --privileged \\\n    -v \"$HOME/.kube:/root/.kube:ro\" \\\n    txn2/kubefwd --tui\n```\n\nVerify installation:\n\n```bash\nkubefwd version\n```\n\n## Operating Modes\n\n### Idle Mode (Recommended)\n\nStart without pre-specified services and add them interactively:\n\n```bash\nsudo -E kubefwd --tui\n```\n\nIn Idle Mode:\n- REST API is enabled by default\n- Auto-reconnect is enabled by default\n- Use TUI to browse namespaces, select services, forward them\n- Or use API to add services dynamically\n\n### Classic Mode\n\nSpecify namespaces upfront. All services forwarded immediately:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n## Your First Forward\n\n1. Start kubefwd in Idle Mode:\n   ```bash\n   sudo -E kubefwd --tui\n   ```\n\n2. Browse namespaces: Press `f` to open the service browser, then select a namespace.\n\n3. Forward services: Select individual services or press `a` to forward all.\n\n4. Use your services:\n   ```bash\n   curl http://my-api:8080/health\n   psql -h postgres -U admin -d mydb\n   redis-cli -h redis ping\n   ```\n\n5. Quit: Press `q` to exit. kubefwd cleans up automatically.\n\n## What Happens Under the Hood\n\nWhen kubefwd forwards a service:\n\n1. **IP Allocation**: Each service gets a unique loopback IP (e.g., `127.1.27.1`)\n2. **Hosts File Update**: Service names added to `/etc/hosts`\n3. **Port Forwarding**: Creates port forwards to pods backing each service\n4. **Ready to Use**: Applications connect using service names\n\n### Cleanup\n\nWhen kubefwd exits:\n- `/etc/hosts` entries are removed\n- Network interface aliases are cleaned up\n- All port forward connections are closed\n\nOriginal hosts file backed up to `~/hosts.original`.\n\n## Why sudo -E?\n\nkubefwd requires root privileges for:\n- Modifying `/etc/hosts`\n- Creating loopback IP aliases\n- Binding to ports below 1024\n\nThe `-E` flag preserves environment variables, especially `KUBECONFIG`:\n\n```bash\n# Correct - preserves KUBECONFIG\nsudo -E kubefwd --tui\n\n# Wrong - may fail to find cluster config\nsudo kubefwd --tui\n```\n\n## Enabling the REST API\n\n**Idle Mode** (API enabled by default):\n```bash\nsudo -E kubefwd\nsudo -E kubefwd --tui\n```\n\n**Classic Mode** (add `--api` flag):\n```bash\nsudo -E kubefwd svc -n default --api\n```\n\nAPI available at:\n- `http://kubefwd.internal/api` - REST endpoints\n- `http://kubefwd.internal/docs` - Interactive API documentation\n\n---\n\n# User Guide\n\nThe Terminal User Interface (TUI) transforms kubefwd into an interactive development companion.\n\n## Interface Overview\n\n### Main View\n\n| Panel | Description |\n|-------|-------------|\n| **Services** | All forwarded services with status, namespace, local address, traffic |\n| **Logs** | Real-time kubefwd activity, connection events, errors |\n| **Status Bar** | Service counts, current filter, keyboard hints |\n\n### Service Status Indicators\n\n| Indicator | Meaning |\n|-----------|---------|\n| Green dot | Active and forwarding |\n| Yellow dot | Connecting or reconnecting |\n| Red dot | Error state |\n\n## Keyboard Shortcuts\n\n### Global\n\n| Key | Action |\n|-----|--------|\n| `q` | Quit kubefwd |\n| `?` | Toggle help overlay |\n| `f` | Open namespace/service browser |\n| `x` | Switch Kubernetes context |\n| `/` | Filter services |\n| `Esc` | Clear filter / Close modal |\n\n### Navigation\n\n| Key | Action |\n|-----|--------|\n| `j` / `↓` | Move down |\n| `k` / `↑` | Move up |\n| `g` / `Home` | Go to first item |\n| `G` / `End` | Go to last item |\n| `Tab` | Switch focus (services ↔ logs) |\n\n### Service Actions\n\n| Key | Action |\n|-----|--------|\n| `Enter` | Open detail view for selected service |\n| `d` | Remove forward for selected service |\n| `r` | Reconnect all errored services |\n| `R` | Force reconnect selected service |\n\n### Detail View\n\n| Key | Action |\n|-----|--------|\n| `1` - `9` | Copy connection string #N to clipboard |\n| `y` | Copy first connection string |\n| `Tab` | Next tab |\n| `Esc` / `q` | Close detail view |\n\n## Auto-Reconnect\n\nTUI enables auto-reconnect by default with exponential backoff:\n\n```\n1s → 2s → 4s → 8s → 16s → 32s → 64s → 128s → 256s → 300s (max)\n```\n\nPress `r` to force immediate reconnection of all errored services.\n\n---\n\n# Configuration\n\nComplete reference for kubefwd command line flags.\n\n## Essential Flags\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--namespace` | `-n` | Namespace(s) to forward services from |\n| `--tui` | | Enable interactive terminal user interface |\n| `--selector` | `-l` | Label selector to filter services |\n| `--field-selector` | `-f` | Field selector to filter services |\n| `--all-namespaces` | `-A` | Forward services from all namespaces |\n\n## TUI and Behavior Flags\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--tui` | | false | Enable interactive TUI mode |\n| `--auto-reconnect` | `-a` | true (TUI) | Automatically reconnect lost port forwards |\n| `--verbose` | `-v` | false | Enable debug logging |\n\n## Network Configuration\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--mapping` | `-m` | Port mapping (e.g., `-m 80:8080`) |\n| `--reserve` | `-r` | Reserve specific IP for service |\n| `--fwd-conf` | `-z` | Path to IP reservation config file |\n| `--domain` | `-d` | Append domain suffix to hostnames |\n\n## Examples\n\n```bash\n# Forward all services in a namespace with TUI\nsudo -E kubefwd svc -n default --tui\n\n# Multiple namespaces\nsudo -E kubefwd svc -n frontend,backend,data --tui\n\n# Filter by label\nsudo -E kubefwd svc -n default -l app=api --tui\n\n# Port mapping (80 → 8080)\nsudo -E kubefwd svc -n default -m 80:8080 --tui\n\n# IP reservation\nsudo -E kubefwd svc -n default -r my-service.default:127.3.3.1 --tui\n```\n\n---\n\n# REST API\n\nkubefwd's REST API enables programmatic control over port forwarding.\n\n## Quick Start\n\n```bash\n# Idle mode - API enabled by default\nsudo -E kubefwd\n\n# Test the API\ncurl http://kubefwd.internal/api/health\n```\n\nBase URL: `http://kubefwd.internal/api`\n\n## Key Endpoints\n\n### Health & Info\n\n- `GET /api/health` - Health check\n- `GET /api/info` - Server information\n\n### Services\n\n- `GET /api/v1/services` - List forwarded services\n- `GET /api/v1/services/:key` - Get specific service\n- `POST /api/v1/services` - Add service to forward\n- `DELETE /api/v1/services/:key` - Stop forwarding\n- `POST /api/v1/services/:key/reconnect` - Reconnect service\n\n### Namespaces\n\n- `GET /api/v1/namespaces` - List namespace watchers\n- `POST /api/v1/namespaces` - Add namespace (forward all services)\n- `DELETE /api/v1/namespaces/:key` - Remove namespace\n\n### Kubernetes Discovery\n\n- `GET /api/v1/kubernetes/contexts` - List kubeconfig contexts\n- `GET /api/v1/kubernetes/namespaces` - List namespaces\n- `GET /api/v1/kubernetes/services` - List services in namespace\n- `GET /api/v1/kubernetes/pods/:namespace` - List pods\n- `GET /api/v1/kubernetes/pods/:namespace/:pod/logs` - Get pod logs\n\n### Metrics & Diagnostics\n\n- `GET /api/v1/metrics` - Summary metrics\n- `GET /api/v1/diagnostics` - Diagnostics summary\n- `GET /api/v1/diagnostics/errors` - Current errors\n\n### Events (SSE)\n\n- `GET /api/v1/events` - Real-time event stream\n\n---\n\n# MCP Integration\n\n## What is MCP?\n\nThe Model Context Protocol (MCP) lets AI assistants connect to external tools. kubefwd's MCP integration gives AI assistants full access to Kubernetes port forwarding.\n\n## Platform Support\n\n| Platform | Support |\n|----------|---------|\n| Claude Code | Full |\n| Claude Desktop | Full |\n| Cursor | Full |\n| Windsurf | Full |\n| VS Code Copilot | Full |\n| Zed | Full |\n| JetBrains IDEs | Full |\n\n## Setup\n\n### 1. Start kubefwd\n\n```bash\nsudo -E kubefwd --tui\n```\n\n### 2. Configure AI Client\n\n**Claude Code:**\n```bash\nclaude mcp add --transport stdio kubefwd -- kubefwd mcp\n```\n\n**Cursor/Windsurf/VS Code:**\nAdd to MCP config:\n```json\n{\n  \"mcpServers\": {\n    \"kubefwd\": {\n      \"command\": \"kubefwd\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n## What Your AI Can Do\n\n### Service Forwarding\n- Forward entire namespaces\n- Forward individual services\n- Remove forwards\n- Multi-context support\n\n### Discovery & Connection\n- List Kubernetes contexts\n- List namespaces and services\n- Get connection info (IPs, hostnames, env vars)\n- Find services by name/port\n\n### Pod Debugging\n- List pods with status\n- Get pod details and logs\n- View Kubernetes events\n- Check service endpoints\n\n### Monitoring & Troubleshooting\n- Quick status checks\n- Traffic metrics\n- Error diagnosis\n- Reconnect services\n\n## Example Conversations\n\n**You:** \"I need to connect to PostgreSQL in kft1\"\n**AI:** \"Connected. Use: `psql -h postgres -U admin -d mydb`\"\n\n**You:** \"Set up my environment for the checkout service\"\n**AI:** \"Ready. Services available: cart-service:8080, payment-service:443, user-db:5432\"\n\n**You:** \"My API calls to auth-service are failing\"\n**AI:** \"The auth-service pod restarted. I've reconnected it. Try again.\"\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nkubefwd is a popular command-line utility for bulk Kubernetes port forwarding, featured in \"essential k8s developer tools\" lists. It forwards multiple services from one or more namespaces, adding corresponding entries to `/etc/hosts` for local development.\n\n**Key Differentiator from `kubectl port-forward`**: Each service gets its own unique loopback IP address (127.x.x.x), allowing multiple services to use the same port simultaneously (e.g., multiple databases on port 3306, or multiple web services on port 80). This mirrors how services work in the cluster, enabling truly cluster-like local development.\n\nThe tool automatically monitors service and pod lifecycle events, starting/stopping port forwards as services are created, deleted, or pods are rescheduled.\n\n## Integration and Usage Patterns\n\nkubefwd is commonly integrated into development workflows:\n\n- **With Tilt**: Blog posts document using kubefwd with Tilt for automated local development setups\n- **Development Environment Setup**: Teams use kubefwd to mirror production-like service topologies locally\n- **Microservices Development**: Allows developers to run one service locally while accessing dependencies in the cluster via service names\n- **Database Access**: Popular for forwarding multiple databases (MySQL, PostgreSQL, MongoDB) on their native ports without port conflicts\n\nThe typical workflow: `sudo -E kubefwd svc -n <namespace> --tui` runs in a dedicated terminal while developers work in their IDE, accessing cluster services as if running in-cluster.\n\n## TUI (Terminal User Interface)\n\nkubefwd includes an interactive TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), enabled with `--tui`:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n### TUI Features\n- **Real-time service monitoring**: See all forwarded services with connection status\n- **Traffic metrics**: Bytes in/out with sparkline graphs\n- **Pod log streaming**: View container logs directly in the TUI\n- **HTTP activity detection**: Monitor HTTP requests/responses flowing through forwards\n- **Auto-reconnect**: Enabled by default in TUI mode, with exponential backoff (1s → 5min max)\n- **Keyboard-driven**: Full keyboard navigation (j/k, Enter, Tab, /, ?, q)\n\n### TUI Architecture\n\nThe TUI follows the Model-View-Update (MVU) pattern:\n\n- **Event Bus** (`pkg/fwdtui/events`): Decoupled pub/sub communication between components\n- **State Store** (`pkg/fwdtui/state`): Centralized, thread-safe state management for all forwards\n- **Metrics Registry** (`pkg/fwdtui/metrics`): Traffic counters with atomic operations\n- **Components** (`pkg/fwdtui/components`): UI models for services list, logs, detail view\n\n### TUI Keyboard Shortcuts\n- `j/k` or arrows: Navigate\n- `Enter`: Open detail view\n- `Tab`: Switch panels/tabs\n- `/`: Filter services\n- `r`: Reconnect errored services\n- `b`: Toggle bandwidth columns\n- `?`: Help overlay\n- `q`: Quit\n\n## Git Policy\n\n**All commits require explicit human approval.** Do not run `git commit` unless the user explicitly asks you to commit. Always show the diff or summarize changes and wait for approval first.\n\n## Verification\n\n**\"Testing\" means `make verify`, not `go test ./...`.** Run it before handing work back; it runs every check CI runs, with the same pinned tools, and a change isn't done until it passes.\n\nThe gates (details in CONTRIBUTING.md, \"Quality Gates\"):\n\n- **Formatting**: gofmt, goimports (`github.com/txn2/kubefwd` local prefix), gofumpt over the whole tree. Fix with `make fmt`.\n- **Lint**: every linter in `.golangci.yml` applies to lines changed since the merge base with `origin/master` (`make lint`, CI `--new-from-rev`). Pre-existing issues elsewhere don't fail; anything touched must pass. `make lint-full` shows the backlog. A `//nolint` or `#nosec` needs a reason.\n- **Complexity** (production code): gocyclo 10, gocognit 15, nestif 5, dupl 150, nakedret 30. Split functions rather than suppressing.\n- **Layering**: depguard rules in `.golangci.yml`; `pkg/` never imports `cmd/`, leaf packages import nothing first-party, the forwarding core never imports `fwdapi`/`fwdmcp`.\n- **Coverage**: total ≥ 80% (`make coverage-check`); changed lines ≥ 80% (`make patch-coverage`). Both block, here and in codecov. Root-only or cluster-only code is made testable by injecting the OS call (see `runCommand` and `goos` in `pkg/fwdapi/network.go`), not left uncovered.\n- **Security**: `make security` runs gosec, govulncheck on both modules (gated by `scripts/govulncheck-gate.py` against `.govulncheck-allow.txt`), and osv-scanner (against `osv-scanner.toml`). Upgrade rather than accept; an accepted advisory needs a reason and expires.\n- **SAST**: `make semgrep` (p/golang, whole tree) and `make semgrep-diff` (`.semgrep-diff/` rules, changed lines). CodeQL runs `security-and-quality` in CI.\n- **Mutation**: `make mutate` (gremlins, 60% efficacy), weekly in CI. Too slow for every change.\n- **Toolchain**: Go is pinned by the `toolchain` line in go.mod; CI's setup-go reads the same line. Tool versions are pinned in the Makefile and installed into `.tools/`.\n\n## Build and Development Commands\n\n### Building\n```bash\n# Build the project (uses goreleaser)\ngo build -o kubefwd ./cmd/kubefwd/kubefwd.go\n\n# Build with version information\ngo build -ldflags \"-X main.Version=dev\" -o kubefwd ./cmd/kubefwd/kubefwd.go\n```\n\n### Testing\n```bash\n# Run all tests\ngo test ./...\n\n# Run tests for a specific package\ngo test ./pkg/fwdport\n\n# Run tests with verbose output\ngo test -v ./pkg/fwdport\n```\n\n### Running Locally\n```bash\n# Requires root/sudo for network interface management and /etc/hosts modification\nsudo ./kubefwd svc -n <namespace>\n\n# Use -E flag to preserve environment (especially KUBECONFIG)\nsudo -E ./kubefwd svc -n <namespace>\n\n# With interactive TUI (recommended for development)\nsudo -E ./kubefwd svc -n <namespace> --tui\n```\n\n### Dependencies\n```bash\n# Download dependencies\ngo mod download\n\n# Update dependencies\ngo mod tidy\n```\n\n### Debugging and Development\n\n```bash\n# Enable verbose logging\nsudo -E ./kubefwd svc -n <namespace> -v\n\n# Test with a single service using field selector\nsudo -E ./kubefwd svc -n <namespace> -f metadata.name=<service-name>\n\n# Test with label selector\nsudo -E ./kubefwd svc -n <namespace> -l app=myapp\n\n# Use IP reservation config for reproducible testing\nsudo -E ./kubefwd svc -n <namespace> -z example.fwdconf.yml\n```\n\nThe verbose flag (`-v`) enables debug-level logging (logrus.DebugLevel), which shows:\n- Service registry operations\n- Pod sync events\n- IP allocation details\n- Port forwarding lifecycle events\n\n### Demo Environment\n\nA comprehensive demo manifest is available for testing:\n\n```bash\n# Deploy 60 services across 2 namespaces\nkubectl apply -f test/manifests/demo-microservices.yaml\n\n# Forward all demo services with TUI\nsudo -E ./kubefwd svc -n kft1,kft2 --tui\n\n# Cleanup\nkubectl delete -f test/manifests/demo-microservices.yaml\n```\n\n## Architecture\n\n### Core Components Flow\n\n1. **Entry Point** (`cmd/kubefwd/kubefwd.go`): CLI entry, delegates to services command\n2. **Services Command** (`cmd/kubefwd/services/services.go`): Main orchestration logic\n   - Validates cluster connectivity and RBAC permissions\n   - Creates Kubernetes informers to watch Service events (Add/Delete/Update)\n   - Spawns namespace watchers for each namespace×context combination\n3. **Service Registry** (`pkg/fwdsvcregistry`): Central registry of all forwarded services\n   - Thread-safe map of active ServiceFWD instances\n   - Handles lifecycle (add, remove, shutdown all)\n4. **Service Forwarding** (`pkg/fwdservice`): Per-service forwarding logic\n   - Queries pods backing each service\n   - Manages pod selection (single pod for normal services, all pods for headless)\n   - Debounces pod sync operations to avoid hammering k8s API\n   - Maintains map of active port forwards per pod\n5. **Port Forwarding** (`pkg/fwdport`): Individual pod port forwarding\n   - Creates SPDY connection to k8s API server\n   - Manages port forward lifecycle with watch for pod deletion\n   - Updates `/etc/hosts` file with service hostnames\n6. **Network/IP Management** (`pkg/fwdnet`, `pkg/fwdIp`): Loopback interface management\n   - Allocates unique 127.x.x.x IPs for each service\n   - Manages IP aliases on loopback interface (macOS: lo0, Linux: lo)\n   - Supports IP reservation via config file or CLI flags\n\n### Key Architectural Patterns\n\n**Event-Driven Architecture**: Uses Kubernetes informers to react to service/pod lifecycle events in real-time.\n\n**Headless vs Normal Services**:\n- Normal services forward the first available pod using the service name\n- Headless services (ClusterIP: None) forward all pods, with first pod as service name and rest as pod-name.service-name\n\n**Debouncing**: Uses 5-second debouncer for pod sync operations to handle rapid pod changes (e.g., rolling deployments) without excessive k8s API calls.\n\n**Thread Safety**: Extensive use of mutexes for:\n- Per-namespace IP allocation (`NamespaceIPLock`)\n- Service registry access\n- Hosts file modifications\n\n**Shutdown Orchestration**: Clean shutdown cascade:\n1. User signal → stopListenCh\n2. Namespace watchers stop\n3. Service registry shutdown\n4. Individual pod port forwards stop\n5. Hosts file cleanup and network alias removal\n\n### Package Responsibilities\n\n- `fwdservice`: Service-level forwarding orchestration and pod management\n- `fwdport`: Individual pod port forwarding via k8s API\n- `fwdsvcregistry`: Global service registry and lifecycle management\n- `fwdnet`: Network interface management (IP aliasing)\n- `fwdIp`: IP allocation logic and reservation handling\n- `fwdhost`: Hosts file backup management\n- `fwdcfg`: Kubernetes client configuration\n- `fwdpub`: Publisher interface for output\n- `fwdtui`: Terminal User Interface (Bubble Tea)\n  - `fwdtui/components`: UI view models (services list, logs, detail, help, status bar)\n  - `fwdtui/events`: Event bus with panic recovery for decoupled pub/sub\n  - `fwdtui/state`: Thread-safe state store with RWMutex protection\n  - `fwdtui/metrics`: Traffic metrics with atomic counters and rate calculation\n  - `fwdtui/portforward`: Port forward wrapper that emits metrics events\n- `utils`: Root permission checks (OS-specific)\n\n## Important Implementation Details\n\n### Root Permissions and Security\n\nkubefwd requires superuser privileges for:\n- Adding IP aliases to loopback interface\n- Binding to low-numbered ports\n- Modifying `/etc/hosts`\n\nAlways run with `sudo -E` to preserve environment variables (KUBECONFIG).\n\n**Security Considerations**: kubefwd is considered a \"powerful but potentially dangerous tool\" because it:\n- Modifies system-level network configuration\n- Changes `/etc/hosts` which affects DNS resolution system-wide\n- Requires root access which can impact system stability if misused\n- Opens network connections to cluster services\n\nThe tool backs up the original hosts file to `~/hosts.original` before making modifications, but improper shutdown can leave the system in an inconsistent state.\n\n### Hostname Generation\nHostnames follow pattern based on cluster and namespace indices:\n- Namespace 0, Cluster 0: `service-name`\n- Namespace >0: `service-name.namespace`\n- Cluster >0: `service-name.context` or `service-name.namespace.context`\n\nFor headless services, pods get: `pod-name.service-name[.namespace][.context]`\n\n### IP Allocation\nBase IP is 127.1.x.x with incremental allocation. Can be customized via:\n- `--fwd-conf` YAML config file (see `example.fwdconf.yml`)\n- `--reserve` CLI flag for individual reservations\n\n### Port Mapping\nSupports port remapping with `-m` flag (e.g., `-m 80:8080` maps service port 80 to local 8080).\n\n### UDP Limitation\nUDP port forwarding is not supported (Kubernetes API limitation: kubernetes/kubernetes#47862).\n\n## Code Organization\n\n```\ncmd/kubefwd/           # CLI entry point\n  kubefwd.go          # Main entry, root command\n  services/\n    services.go       # Services subcommand, namespace watchers\npkg/\n  fwdservice/         # Service forwarding logic\n  fwdport/            # Pod port forwarding\n  fwdsvcregistry/     # Service registry\n  fwdnet/             # Network interface management\n  fwdIp/              # IP allocation\n  fwdhost/            # Hosts file operations\n  fwdcfg/             # K8s config\n  fwdpub/             # Publisher\n  fwdtui/             # Terminal User Interface\n    components/       # UI models (services, logs, detail, help)\n    events/           # Event bus for decoupled communication\n    state/            # Centralized state store\n    metrics/          # Traffic metrics with atomic counters\n    portforward/      # Port forward wrapper with metrics\n  utils/              # Utilities (root check)\ntest/\n  integration/        # Integration tests (require KIND cluster)\n  manifests/          # Test Kubernetes manifests\n  scripts/            # Test setup/teardown scripts\n```\n\n## Contribution Policy\n\n**Public Contributions**: The project welcomes pull requests from the community for:\n- Bug fixes\n- Tests\n- Documentation\n- Stability and compatibility enhancements\n\n**Feature Development**: New features are developed by select contributors only. Public feature PRs are discouraged due to past experience with contributions that introduced drastic codebase changes, were difficult to review and test, and added significant technical debt. This policy is documented in the README.\n\n**Internal Development**: Maintainers and trusted contributors are welcome to develop new features. If you're working on this codebase with direct access, feature development is encouraged.\n\n## Release Process\n\nUses GoReleaser (`.goreleaser.yml`):\n- Builds for Linux, macOS, Windows (multiple architectures)\n- Creates Docker images (Alpine and Ubuntu variants)\n- Publishes to GitHub releases\n- Updates Homebrew tap (txn2/homebrew-tap)\n- Generates RPM, DEB, APK packages\n\nThe version is set via ldflags during build: `-ldflags \"-X main.Version={{.Version}}\"`\n\n## Testing\n\n### Unit Tests\n\n`make verify` is the full check (see Verification above). For quicker loops:\n\n```bash\n# Run all unit tests\ngo test ./...\n\n# Run with coverage\ngo test -cover ./...\n\n# Run specific package tests\ngo test -v ./pkg/fwdtui/events/...     # Event bus tests (100% coverage)\ngo test -v ./pkg/fwdtui/components/... # UI component tests\ngo test -v ./pkg/fwdtui/state/...      # State store tests\ngo test -v ./pkg/fwdport/...           # Port forwarding tests\n```\n\n### Integration Tests\n\nLocated in `test/integration/`, these require a KIND cluster:\n\n```bash\n# Setup KIND cluster\n./test/scripts/setup-kind.sh\n./test/scripts/deploy-test-services.sh test/manifests\n\n# Run integration tests (requires sudo)\nsudo -E go test -tags=integration -v ./test/integration/...\n\n# Teardown\n./test/scripts/teardown-kind.sh\n```\n\nIntegration tests cover: basic forwarding, headless services, auto-reconnect, multi-namespace, port mapping, and cleanup verification.\n\n### Areas for Additional Testing\n- Hosts file race condition scenarios (Issue #74)\n- Cleanup/restore logic for error conditions (Issue #5)\n- Pod state filtering for evicted/completed pods (Issues #34, #114)\n\n## Areas for Improvement\n\nBased on known issues, these areas would benefit from development:\n\n### Auto-Reconnect Enhancement\nAuto-reconnect is now implemented (`-a` flag, enabled by default in TUI mode) with exponential backoff. However, edge cases may still exist:\n- Very rapid pod cycling during rolling deployments\n- Network partitions vs pod deletion detection\n- Reconnection priority when multiple pods are available\n\n### Hosts File Synchronization (Issues #74, #79)\nThe `HostFileWithLock` mutex in `pkg/fwdport` may not be sufficient for all race conditions. Consider:\n- Batching hosts file updates\n- Implementing retry logic for failed updates\n- Adding verification that all services are actually written\n\n### Graceful Shutdown (Issue #5)\nEnhance the shutdown cascade to guarantee hosts file restoration even on signal interruption. Consider using `defer` more extensively or implementing a signal handler with guaranteed cleanup.\n\n### Pod State Filtering (Issues #34, #114)\nThe pod filtering in `fwdservice.GetPodsForService()` should be more defensive:\n- Handle additional pod phases gracefully\n- Add better error handling for watch events with non-pod objects\n- Consider ignoring evicted pods earlier in the pipeline\n\n### Services Without Selectors (Issue #35)\nCould potentially support endpoint-based services by querying Endpoints resources directly instead of relying on pod selectors.\n\n## Known Limitations and Active Issues\n\nBased on community feedback and GitHub issues, developers should be aware of:\n\n### Architectural Limitations\n\n**Services Without Selectors** (Issue #35): kubefwd does not support ClusterIP services without selectors (services backed by manually created Endpoints). The code assumes services have pod selectors and will skip services with empty selector strings.\n\n**Auto-Reconnect Available** (Issue #21 resolved): Auto-reconnect is now implemented with the `-a` flag (enabled by default in TUI mode). When pods restart, kubefwd automatically re-establishes port forwards with exponential backoff (1s → 5min max).\n\n**UDP Protocol Not Supported**: Kubernetes port-forwarding API limitation (kubernetes/kubernetes#47862).\n\n### Race Conditions and Edge Cases\n\n**Hosts File Race Condition** (Issue #74): When forwarding multiple services simultaneously, especially on Windows with Docker Desktop, race conditions can occur during hosts file updates, leading to DNS resolution errors.\n\n**Hosts File Not Fully Restored** (Issue #5): On certain error conditions or unclean shutdowns (Ctrl-C timing), the original `/etc/hosts` may not be fully restored. Always check `~/hosts.original` backup.\n\n**Incomplete Hosts File Updates** (Issue #79): Some services may be assigned IPs and be accessible but not appear in the hosts file. This appears related to timing in the hosts file update logic.\n\n### Pod State Handling\n\n**Evicted/Completed Pods** (Issues #34, #114): Starting from v1.11.0, interface conversion errors occur with evicted pods or completed jobs. The code in `pkg/fwdservice` filters for `PodPending` and `PodRunning` states, but watch events for other states can cause errors.\n\n**Pod Status Assumptions**: The code assumes pods are either Pending, Running, Succeeded, Failed, or Unknown. Edge cases with custom pod conditions may not be handled gracefully.\n\n## Common Issues and Troubleshooting\n\n**Permission Errors**: Always use `sudo -E` to preserve KUBECONFIG.\n\n**IP/Port Conflicts**: Use IP reservations (`-r` or `-z`) to avoid conflicts.\n\n**Stale /etc/hosts Entries**: Original hosts file backed up to `~/hosts.original`. Check this file if DNS resolution is broken after kubefwd exits.\n\n**Pod Watch Failures**: Check RBAC permissions (list/get/watch pods, get services).\n\n**Connection Refused (localhost:8080)**: This usually means kubectl is not properly configured or KUBECONFIG was not preserved (missing `-E` flag with sudo).\n"},"files":{"DESIGN.md":"---\nversion: alpha\nspec: https://github.com/google-labs-code/design.md\nname: kubefwd-docs\ndescription: Local design adoption record for the kubefwd.com documentation site. References txn2/www DESIGN.md as the canonical visual identity for tokens, typography, components, copyright voice, and accessibility rules. Records only the decisions and MkDocs Material learnings that the canonical does not cover.\nupstream:\n  design: https://github.com/txn2/www/blob/master/DESIGN.md\n  tokens: https://github.com/txn2/www/blob/master/tokens.json\nadoption: token-alignment\nstack:\n  generator: MkDocs\n  theme: Material for MkDocs\n  templates: docs/overrides/\n  styles: docs/stylesheets/extra.css\n---\n\n## What is canonical\n\nThe canonical visual identity for txn2 lives in [`txn2/www/DESIGN.md`](https://github.com/txn2/www/blob/master/DESIGN.md) with tokens in [`txn2/www/tokens.json`](https://github.com/txn2/www/blob/master/tokens.json). This file defers to those for everything below. If a value here disagrees with upstream, upstream wins.\n\n| Concern              | Source of truth |\n|----------------------|-----------------|\n| Color palette        | upstream `tokens.json` `color.*` |\n| Typography stack     | upstream `tokens.json` `font.*` |\n| Type scale           | upstream `DESIGN.md` Typography table |\n| Spacing / measure    | upstream `tokens.json` `size.*` |\n| Component contracts  | upstream `DESIGN.md` Components |\n| Voice / copy rules   | upstream `DESIGN.md` Voice and Copy |\n| Accessibility rules  | upstream `DESIGN.md` Do's and Don'ts |\n| Mermaid theme        | upstream `DESIGN.md` `mcp__card--feature` block |\n\nTokens are mirrored as CSS custom properties in `docs/stylesheets/extra.css` `:root`. They are duplicated for runtime use, not as a divergence point. When upstream changes a token, update the value in `extra.css` and ship.\n\n## Adoption level: token alignment\n\nPer the upstream downstream contract, three levels are valid:\n\n1. Reference. Link to upstream, no visual changes.\n2. Token alignment. Keep MkDocs Material, re-skin via `extra.css` against upstream tokens.\n3. Full re-skin. Replace MkDocs Material with custom layouts.\n\nkubefwd runs at **level 2**. The site keeps Material's instant nav, search, sidebar, version selector, code copy, and content extensions. The visual layer is replaced. The homepage is a custom Material template that takes over `block header`, `block container`, and `block footer` for full-bleed treatment.\n\n## File map\n\n| Path | Role |\n|------|------|\n| `mkdocs.yml`                   | Single dark `slate` palette. `font: false` so CSS loads the upstream Google Fonts URL with trimmed axes. |\n| `docs/index.md`                | Stub front matter with `template: home.html`. All homepage HTML lives in the template. |\n| `docs/overrides/main.html`     | Adds the upstream Google Fonts `<link>` plus OG and Twitter meta. Inherited by every page. |\n| `docs/overrides/home.html`     | Custom homepage template. Overrides `block header` (rail), `block tabs` (empty), `block container` (page--home shell with hero, sections, flagship cards, stack, coda), `block footer` (home-footer). |\n| `docs/stylesheets/extra.css`   | All design rules. Two halves: homepage components scoped under `.page--home`, and Material chrome restyle for inner pages via `[data-md-color-scheme=\"slate\"]` variable overrides. |\n\n## Project-specific components\n\nComponents ported from upstream verbatim, with kubefwd content:\n\n- `.rail` (replaces Material `.md-header` on the homepage). Brand links to `./`. Live UTC clock in meta. txn2.com link in meta as `part of <em class=\"serif\">txn2</em> ↗`.\n- `.hero` with three Fraunces rows (kubefwd / kubernetes / port forwards.).\n- `.section`, `.section__index`, `.section__title`.\n- `.flagship__card`. Two cards: `--kubefwd` (TUI mode demo) and a second variant for the API + MCP surfaces. Top accent line animates on hover per upstream spec.\n- `.terminal`, `.terminal__bar`, `.terminal__body` with `.t-prompt`, `.t-ok`, `.t-mute` classes. The only block with shadow.\n- `.stack`, `.stack__row`. Each row links to a real anchor in the docs (architecture/#ip-allocation, advanced-usage/#custom-hosts-file-path, user-guide/#auto-reconnect, user-guide/#interface-overview, api-reference/, mcp-integration/).\n- `.coda` and `.home-footer` (renamed from upstream `.footer` to avoid collision with markdown that uses `class=\"footer\"`; see Learning #5).\n\nComponents from upstream **not used** here, with reason:\n\n- `.mcp__card--feature` and the MCP grid. kubefwd is a single project, not an MCP catalog.\n- The `mcp-data-platform` mermaid hero. Not relevant.\n- The 5-column footer's `sponsors / craig` columns. The kubefwd home-footer has `about / docs / interfaces / code / txn2 / org` columns instead, since this site is project-scoped.\n\nCustom additions specific to kubefwd:\n\n- `home-footer__col--meta` includes a `txn2 / org` panel that backlinks to txn2.com explicitly. Per the org-wide rule that every sister project must clearly link home.\n- All CNCF Landscape mentions on the homepage and in `docs/attributions.md` link to the kubefwd entry on `landscape.cncf.io`. The Landscape listing is a load-bearing credential and earns a real link wherever it appears.\n\n## MkDocs Material learnings\n\nThe upstream is built with Hugo. kubefwd is built with MkDocs Material. The two have different override surfaces, so the same visual outcome requires different mechanics. These are the lessons worth carrying forward when re-skinning the next sister project.\n\n### 1. Override the homepage via a separate template, not via CSS hacks\n\nMkDocs Material's content pipeline wraps every page body in `.md-content__inner` with hard-coded max-widths. Trying to break out with `:has()` selectors or full-bleed hacks inside the markdown body is fragile and fights Material's own layout.\n\nThe pattern that works: create `docs/overrides/home.html` that extends Material's `main.html` and overrides `block container`, `block header`, `block footer`. Set `template: home.html` in `docs/index.md` front matter. Material then renders the homepage with the custom blocks instead of the standard layout. The homepage gets full viewport control without any width-fighting.\n\n```yaml\n# docs/index.md\n---\ntitle: kubefwd\ntemplate: home.html\nhide:\n  - navigation\n  - toc\n  - footer\n---\n```\n\n### 2. Re-skin inner pages via Material variable overrides\n\nMaterial exposes its own design tokens as CSS custom properties on `[data-md-color-scheme=\"slate\"]`. Mapping these to upstream tokens re-skins every inner page automatically without touching their markdown:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-default-bg-color:        var(--ink);\n  --md-default-fg-color:        var(--paper);\n  --md-typeset-a-color:         var(--signal);\n  --md-text-font:               var(--sans);\n  --md-code-font:               var(--mono);\n  /* ...etc */\n}\n```\n\nVerify the body actually carries the attribute (`grep data-md-color-scheme site/getting-started/index.html`). Single-scheme palettes (`palette: scheme: slate`) do emit it. If they ever stop, fall back to `:root`.\n\n### 3. `font: false` to load fonts directly from CSS\n\nMaterial's `font:` directive loads fonts through Google Fonts but without axis control. To get the upstream's exact trimmed payload (Fraunces with `opsz/wght` italic axis, Instrument Sans roman 400-700, JetBrains Mono roman 400-700, **no SOFT axis**), set `font: false` in `mkdocs.yml` and load the upstream Google Fonts URL via a `<link>` in `main.html`'s `extrahead` block. Verify a single `fonts.googleapis.com` request in DevTools.\n\n### 4. Scope every homepage component class under `.page--home`\n\nThe upstream uses `<main class=\"page page--home\">` on its index page and inner pages don't inherit those classes. In MkDocs the same component class names will collide if any markdown happens to use `class=\"terminal\"`, `class=\"footer\"`, `class=\"section\"`, etc. Material's admonitions, tabbed content, and `md_in_html` all generate divs with predictable class names, and contributors will write more.\n\nDiscipline: every homepage component rule must include `.page--home` as an ancestor, OR rename the class with a project-specific prefix (e.g., `home-footer`). The cost of getting this wrong is silent visual breakage on inner pages weeks later when someone uses one of the colliding names.\n\n### 5. Rename `.footer` → `.home-footer`\n\nThe single most common collision. Markdown that includes a literal `<div class=\"footer\">` is plausible and will inherit the homepage's 60px-padded, 5-column-grid footer styling. Rename rather than scope.\n\n### 6. h3 and h4 are technical reference, not display type\n\nInner pages like `api-reference.md` use `### GET /api/health` and `### POST /api/v1/services` as section headings. Rendering these in Fraunces italic display style (the obvious choice for a \"serif headings\" design) makes the API reference unreadable.\n\nThe rule: h1 and h2 stay Fraunces italic for page and section titles. h3 and h4 switch to Instrument Sans bold so technical reference reads as text, not as type. Add a `:has(code)` block that flips any heading containing inline code to JetBrains Mono with signal-orange code text. Add a `@supports not selector(:has(*))` fallback for older browsers.\n\n```css\n.md-typeset h3 {\n  font-family: var(--sans);\n  font-weight: 700;\n  font-size: clamp(18px, 1.6vw, 22px);\n}\n.md-typeset h1:has(code),\n.md-typeset h2:has(code),\n.md-typeset h3:has(code),\n.md-typeset h4:has(code) {\n  font-family: var(--mono);\n  font-style: normal;\n  font-weight: 700;\n}\n```\n\n### 7. Tabbed content nests boxes, fix it\n\nMaterial's `.md-typeset .tabbed-set` defaults to a bordered, backgrounded box. Code blocks inside also default to bordered backgrounded boxes. The result is nested rectangles with cluttered visual hierarchy.\n\nThe fix: strip the `.tabbed-set` background and border. Leave only a bottom underline on `.tabbed-labels`. Let the inner code blocks be the visual statement. Tighten `pre > code` padding to ~14px so single-line install commands don't render as 70px-tall rectangles.\n\n### 8. Mermaid via Material's CSS variables, not via separate init\n\nMkDocs Material includes a Mermaid integration that reads `--md-mermaid-*` CSS variables. Don't bring in `mermaid.esm.mjs` separately like the upstream Hugo site does. Instead, set the variables in the slate scheme block:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-mermaid-node-bg-color:   var(--ink-3);\n  --md-mermaid-node-fg-color:   var(--paper);\n  --md-mermaid-edge-color:      var(--mute);\n  /* ...full list in extra.css */\n}\n```\n\nPlus a `.md-typeset .mermaid` container restyle (dashed border, ink-3 background) for the diagram block itself.\n\n### 9. Guard inline scripts against `navigation.instant`\n\n`navigation.instant` is enabled (`mkdocs.yml`). On every navigation back to the homepage, Material rehydrates the body. Any `setInterval`, `setTimeout`, or event listener registered in an inline `<script>` will register **again**, leaking handles indefinitely.\n\nPattern for the live UTC clock used in the rail and footer:\n\n```html\n<script>\n  (function () {\n    if (window.__kubefwdClock) {\n      window.__kubefwdClock.tick();\n      return;\n    }\n    function tick() { /* ... */ }\n    tick();\n    var handle = setInterval(tick, 30 * 1000);\n    window.__kubefwdClock = { tick: tick, handle: handle };\n  })();\n</script>\n```\n\nThe `tick()` call on re-entry refreshes the displayed time without registering a new interval.\n\n### 10. Drop the light/dark toggle\n\nThe canonical txn2 identity is dark only. Collapse `palette` to a single `scheme: slate`. Remove the `toggle:` blocks. Audit `extra.css` and `index.md` for orphan light-mode references (`hero-logo-light`, `prefers-color-scheme: light`, `kf-green` etc).\n\n### 11. Atmospheric overlays at low z-index\n\n`body::before` (grain) and `body::after` (vignette) are fixed viewport overlays. Place them at `z-index: 1` so they sit above the page background but below the rail (z-50) and skiplink (z-200). Vignette has no blend mode, so a higher z-index would darken interactive chrome.\n\n### 12. What Hugo does that MkDocs cannot match\n\nFor reference when the next sister project chooses its adoption level:\n\n- Hugo can compile tokens.json into CSS custom properties at build time via `resources.Get` + `transform.Unmarshal`. MkDocs has no equivalent. We hand-mirror the tokens in `extra.css` `:root` and update them when upstream changes.\n- Hugo can subscribe to upstream tokens through a small extra.css that imports a generated `:root { --... }` block. MkDocs cannot. Token sync is a manual PR.\n- Hugo's partial system handles header/footer composition naturally. MkDocs uses Material template `{% block %}` overrides, which is similar but constrained to Material's block names (`announce`, `header`, `tabs`, `container`, `content`, `footer`, `scripts`).\n\n## Voice and copy\n\nDefers to upstream. Briefly:\n\n- No em-dashes (U+2014) or en-dashes (U+2013) anywhere, including code comments and template comments. Use commas, periods, colons, parentheses, slashes, hyphens.\n- No AI-tell vocabulary: `seamless`, `leverage`, `comprehensive`, `robust`, `delve`, `unleash`, `elevate`, `embark`, `tapestry`, `not just X but Y`, `as an AI`, `let me X`.\n- Sentence case for body. Lowercase for rail and label text. Title case rare.\n- Section indices: `§ 01 / title` with slash, never an em-dash.\n- Year ranges use a hyphen: `2017-2026`.\n- Verify before commit: `grep -RE \"—|–\" docs/ mkdocs.yml`.\n\n## Updating\n\nWhen the upstream `txn2/www/DESIGN.md` or `tokens.json` changes:\n\n1. Read the upstream diff. Identify which tokens, components, or rules changed.\n2. Update the matching CSS variables in `docs/stylesheets/extra.css` `:root`.\n3. If a component contract changed (padding, border, hover behavior), update the homepage template in `docs/overrides/home.html` and the matching CSS rules.\n4. Update this file's File map / Project-specific components / MkDocs Material learnings sections if a new learning emerges.\n5. Run `mkdocs build --strict` and verify in the browser before committing. Verify the home page hero, flagship cards, terminal, stack, coda, and home-footer. Verify an inner page (`/getting-started/`, `/api-reference/`) still inherits the look.\n\nKeep this file thin. If a section grows past 30 lines, ask whether it belongs upstream instead.\n\n## Downstream contract for sister projects\n\nThis file is canonical only for kubefwd.com. Other sister projects (txeh, mcp-s3, mcp-trino, mcp-datahub, mcp-data-platform) considering the same adoption should:\n\n1. Use this file as a template for their own thin local DESIGN.md.\n2. Reference upstream `txn2/www/DESIGN.md` as the source of truth for tokens, typography, components, voice.\n3. Replace the kubefwd-specific sections (project-specific components, file paths, custom additions) with their own.\n4. Keep the MkDocs Material learnings section. Those apply to every MkDocs Material project.\n5. Update upstream's downstream-contract list when adding a new project.\n","docs/llms.txt":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n## Documentation\n\n- [Getting Started](https://kubefwd.com/getting-started/): Installation, prerequisites, and first forward\n- [User Guide](https://kubefwd.com/user-guide/): Interactive TUI interface and keyboard shortcuts\n- [Configuration](https://kubefwd.com/configuration/): CLI flags, IP reservations, and port mapping\n- [REST API](https://kubefwd.com/api-reference/): Programmatic control via 40+ HTTP endpoints\n- [MCP Integration](https://kubefwd.com/mcp-integration/): AI assistant integration (Claude, Cursor, VS Code)\n\n## Key Features\n\n- **Unique IP per service**: Multiple databases on port 3306 work without conflicts\n- **Auto-reconnect**: Reconnects automatically when pods restart\n- **Interactive TUI**: Browse namespaces, monitor traffic, stream logs\n- **Service name resolution**: Updates /etc/hosts so apps connect by service name\n- **REST API**: Add/remove services dynamically\n- **MCP support**: Natural language control via AI assistants\n\n## Quick Start\n\n```bash\n# Install (macOS)\nbrew install txn2/tap/kubefwd\n\n# Forward services with TUI\nsudo -E kubefwd svc -n my-namespace --tui\n```\n\n## Optional\n\n- [Troubleshooting](https://kubefwd.com/troubleshooting/): Common issues and solutions\n- [Architecture](https://kubefwd.com/architecture/): Technical implementation details\n- [Comparison](https://kubefwd.com/comparison/): vs kubectl port-forward, Telepresence, mirrord\n- [GitHub Repository](https://github.com/txn2/kubefwd): Source code, issues, releases\n","smithery.yaml":"# Smithery.ai MCP Server Configuration\n# https://smithery.ai/docs\n\nstartCommand:\n  type: stdio\n  configSchema:\n    type: object\n    properties:\n      apiUrl:\n        type: string\n        description: \"URL of the kubefwd REST API\"\n        default: \"http://kubefwd.internal/api\"\n    required: []\n  commandFunction: |\n    (config) => ({\n      command: 'kubefwd',\n      args: ['mcp', ...(config.apiUrl ? ['--api-url', config.apiUrl] : [])],\n      env: {}\n    })\n","docs/architecture.md":"# Architecture\n\nHow kubefwd works under the hood.\n\n## Overview\n\nkubefwd establishes port forwards to Kubernetes services by:\n\n1. Discovering services in specified namespaces\n2. Allocating unique local IP addresses (127.x.x.x)\n3. Updating `/etc/hosts` with service hostnames\n4. Creating SPDY connections through the Kubernetes API\n5. Monitoring pod lifecycle for automatic reconnection\n\n```mermaid\nflowchart TB\n    subgraph workstation[\"Your Workstation\"]\n        subgraph kubefwd[\"kubefwd\"]\n            sw[Service Watcher]\n            ip[IP Allocator]\n            hm[Hosts Manager]\n\n            subgraph pfm[\"Port Forward Manager\"]\n                pf1[\"127.1.27.1:8080\"]\n                pf2[\"127.1.27.2:3306\"]\n                pf3[\"127.1.27.3:6379\"]\n            end\n        end\n    end\n\n    subgraph cluster[\"Kubernetes Cluster\"]\n        api[\"api-pod :8080\"]\n        mysql[\"mysql-pod :3306\"]\n        redis[\"redis-pod :6379\"]\n    end\n\n    pf1 -->|SPDY via K8s API| api\n    pf2 -->|SPDY via K8s API| mysql\n    pf3 -->|SPDY via K8s API| redis\n```\n\n## Key Components\n\n### Service Discovery\n\nkubefwd uses Kubernetes **informers** to watch for service events:\n\n- **Add**: New service discovered → start port forward\n- **Update**: Service modified → update port forward if needed\n- **Delete**: Service removed → stop port forward, cleanup hosts\n\nThis event-driven approach means kubefwd reacts in real-time to cluster changes.\n\n### IP Allocation\n\nEach service receives a unique loopback IP address:\n\n```\n127.[1+cluster].[27+namespace].[service_count]\n```\n\n| Component | Base | Range |\n|-----------|------|-------|\n| First octet | 127 | Fixed |\n| Second octet | 1 | 1-255 (cluster index) |\n| Third octet | 27 | 27-255 (namespace index) |\n| Fourth octet | 1 | 1-255 (service count) |\n\n**Why unique IPs?**\n\nUnlike `kubectl port-forward` which uses `localhost:port`, kubefwd assigns each service its own IP. This allows:\n\n- Multiple services on the same port (e.g., several databases on 3306)\n- Realistic service topology matching in-cluster behavior\n- No port conflict management needed\n\n### Hosts File Management\n\nkubefwd modifies `/etc/hosts` to map service names to allocated IPs:\n\n```\n# Before kubefwd\n127.0.0.1       localhost\n\n# After kubefwd starts\n127.0.0.1       localhost\n127.1.27.1      api-service\n127.1.27.2      database\n127.1.27.3      cache\n```\n\n**Safety measures:**\n- Original hosts file backed up to `~/hosts.original`\n- Entries removed on clean shutdown\n- Mutex locking prevents race conditions\n- Stale entry purging available (`-p` flag)\n\n### Port Forwarding\n\nkubefwd creates SPDY connections through the Kubernetes API server:\n\n1. **Pod Selection**: Find pods backing the service\n2. **Connection**: Establish SPDY tunnel via API server\n3. **Local Binding**: Bind to allocated IP and service port(s)\n4. **Data Transfer**: Proxy traffic bidirectionally\n\n```mermaid\nflowchart LR\n    app[Local App] --> ip[\"127.1.27.1:8080\"] --> kf[kubefwd] --> api[K8s API] --> pod[\"Pod:8080\"]\n```\n\n### Pod Lifecycle Monitoring\n\nkubefwd watches pod events to maintain forwarding:\n\n- **Pod deleted**: Stop forward, trigger reconnection\n- **Pod recreated**: Auto-reconnect (if enabled)\n- **Pod crash**: Detect via connection loss, reconnect\n\nThe auto-reconnect feature uses exponential backoff:\n- Initial: 1 second\n- Maximum: 5 minutes\n- Reset on successful connection\n\n## Service Types\n\n### Normal Services (ClusterIP)\n\nFor services with selectors:\n\n1. Query pods matching the selector\n2. Select first available Running pod\n3. Forward to that single pod\n4. Hostname: `service-name`\n\n### Headless Services (ClusterIP: None)\n\nFor services without cluster IP:\n\n1. Query all pods matching the selector\n2. Forward to ALL pods\n3. Hostnames:\n   - `service-name` → first pod\n   - `pod-name.service-name` → each specific pod\n\nThis is essential for StatefulSets and databases requiring pod-specific addressing.\n\n### Services Without Selectors\n\n**Not supported.** kubefwd requires pod selectors to discover backing pods. Services with manually managed Endpoints are skipped.\n\n## TUI Architecture\n\nThe Terminal User Interface uses the [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework:\n\n```mermaid\nflowchart LR\n    subgraph core[\"Core Services\"]\n        eb[Event Bus]\n        ss[State Store]\n        mr[Metrics Registry]\n    end\n\n    subgraph views[\"View Models\"]\n        sm[Services]\n        lm[Logs]\n        dm[Detail]\n    end\n\n    core --> views\n```\n\n### Event Bus\n\nDecoupled communication between components:\n- Service status changes\n- Metrics updates\n- Log messages\n- User actions\n\n### State Store\n\nCentralized, thread-safe state management:\n- Forward status for all services\n- Metrics data (bytes, rates)\n- Filter/sort state\n\n### Metrics Collection\n\nTraffic monitoring with:\n- Byte counters (atomic operations)\n- Rate calculations (rolling window)\n- HTTP request/response detection\n- Sparkline visualization\n\n## Thread Safety\n\nkubefwd handles concurrent operations carefully:\n\n| Resource | Protection |\n|----------|------------|\n| Service registry | RWMutex |\n| IP allocation | Per-namespace mutex |\n| Hosts file | Global mutex with file locking |\n| Metrics | Atomic operations + RWMutex |\n| Event bus | Channel-based with buffer |\n\n## Shutdown Sequence\n\nClean shutdown ensures no leftover state:\n\n1. User signal (q, Ctrl+C) → stop listening\n2. Close service watchers\n3. Stop all port forwards\n4. Remove hosts file entries\n5. Remove network interface aliases\n\nIf shutdown is interrupted, use `-p` to purge stale entries on next run.\n\n## Network Interface Management\n\nkubefwd creates loopback aliases:\n\n**macOS (lo0):**\n```bash\nifconfig lo0 alias 127.1.27.1\n```\n\n**Linux (lo):**\n```bash\nip addr add 127.1.27.1/8 dev lo\n```\n\nThese aliases allow binding to unique IPs while keeping traffic local.\n\n## Security Considerations\n\nkubefwd requires elevated privileges for:\n\n1. **Network interface modification**: Adding IP aliases\n2. **Hosts file modification**: DNS resolution\n3. **Low port binding**: Ports below 1024\n\n**Recommendations:**\n- Run only in development environments\n- Don't run in production workstations with sensitive data\n- Review services before forwarding from production clusters\n- Use label selectors to limit scope\n\n## Performance Characteristics\n\n| Operation | Complexity |\n|-----------|------------|\n| Service discovery | O(services) per namespace |\n| Port forward setup | O(1) per service |\n| Metrics sampling | O(forwards) per second |\n| Hosts file update | O(forwards) per change |\n\nkubefwd is designed for development use with dozens to hundreds of services. For very large clusters, use selectors to limit scope.\n","docs/llms-full.txt":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n---\n\n# Getting Started\n\nThis guide covers installation and your first steps with kubefwd. By the end, you'll have cluster services accessible locally by name.\n\n## Prerequisites\n\n- **kubectl configured** with access to a Kubernetes cluster\n- **Root/sudo access** (required for `/etc/hosts` and network interface modifications)\n\nkubefwd reads your kubeconfig (`~/.kube/config` or `KUBECONFIG` environment variable) and connects directly to the Kubernetes API.\n\n## Installation\n\n### macOS\n\nUsing Homebrew:\n\n```bash\nbrew install txn2/tap/kubefwd\n```\n\n### Windows\n\nUsing Scoop:\n\n```powershell\nscoop install kubefwd\n```\n\nRun as Administrator for hosts file access.\n\n### Linux (Debian/Ubuntu)\n\nDownload the `.deb` package from GitHub Releases:\n\n```bash\nsudo dpkg -i kubefwd_*_amd64.deb\n```\n\n### Linux (RHEL/Fedora)\n\nDownload the `.rpm` package from GitHub Releases:\n\n```bash\nsudo rpm -i kubefwd_*_amd64.rpm\n```\n\n### Docker\n\n```bash\ndocker run -it --rm --privileged \\\n    -v \"$HOME/.kube:/root/.kube:ro\" \\\n    txn2/kubefwd --tui\n```\n\nVerify installation:\n\n```bash\nkubefwd version\n```\n\n## Operating Modes\n\n### Idle Mode (Recommended)\n\nStart without pre-specified services and add them interactively:\n\n```bash\nsudo -E kubefwd --tui\n```\n\nIn Idle Mode:\n- REST API is enabled by default\n- Auto-reconnect is enabled by default\n- Use TUI to browse namespaces, select services, forward them\n- Or use API to add services dynamically\n\n### Classic Mode\n\nSpecify namespaces upfront. All services forwarded immediately:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n## Your First Forward\n\n1. Start kubefwd in Idle Mode:\n   ```bash\n   sudo -E kubefwd --tui\n   ```\n\n2. Browse namespaces: Press `f` to open the service browser, then select a namespace.\n\n3. Forward services: Select individual services or press `a` to forward all.\n\n4. Use your services:\n   ```bash\n   curl http://my-api:8080/health\n   psql -h postgres -U admin -d mydb\n   redis-cli -h redis ping\n   ```\n\n5. Quit: Press `q` to exit. kubefwd cleans up automatically.\n\n## What Happens Under the Hood\n\nWhen kubefwd forwards a service:\n\n1. **IP Allocation**: Each service gets a unique loopback IP (e.g., `127.1.27.1`)\n2. **Hosts File Update**: Service names added to `/etc/hosts`\n3. **Port Forwarding**: Creates port forwards to pods backing each service\n4. **Ready to Use**: Applications connect using service names\n\n### Cleanup\n\nWhen kubefwd exits:\n- `/etc/hosts` entries are removed\n- Network interface aliases are cleaned up\n- All port forward connections are closed\n\nOriginal hosts file backed up to `~/hosts.original`.\n\n## Why sudo -E?\n\nkubefwd requires root privileges for:\n- Modifying `/etc/hosts`\n- Creating loopback IP aliases\n- Binding to ports below 1024\n\nThe `-E` flag preserves environment variables, especially `KUBECONFIG`:\n\n```bash\n# Correct - preserves KUBECONFIG\nsudo -E kubefwd --tui\n\n# Wrong - may fail to find cluster config\nsudo kubefwd --tui\n```\n\n## Enabling the REST API\n\n**Idle Mode** (API enabled by default):\n```bash\nsudo -E kubefwd\nsudo -E kubefwd --tui\n```\n\n**Classic Mode** (add `--api` flag):\n```bash\nsudo -E kubefwd svc -n default --api\n```\n\nAPI available at:\n- `http://kubefwd.internal/api` - REST endpoints\n- `http://kubefwd.internal/docs` - Interactive API documentation\n\n---\n\n# User Guide\n\nThe Terminal User Interface (TUI) transforms kubefwd into an interactive development companion.\n\n## Interface Overview\n\n### Main View\n\n| Panel | Description |\n|-------|-------------|\n| **Services** | All forwarded services with status, namespace, local address, traffic |\n| **Logs** | Real-time kubefwd activity, connection events, errors |\n| **Status Bar** | Service counts, current filter, keyboard hints |\n\n### Service Status Indicators\n\n| Indicator | Meaning |\n|-----------|---------|\n| Green dot | Active and forwarding |\n| Yellow dot | Connecting or reconnecting |\n| Red dot | Error state |\n\n## Keyboard Shortcuts\n\n### Global\n\n| Key | Action |\n|-----|--------|\n| `q` | Quit kubefwd |\n| `?` | Toggle help overlay |\n| `f` | Open namespace/service browser |\n| `x` | Switch Kubernetes context |\n| `/` | Filter services |\n| `Esc` | Clear filter / Close modal |\n\n### Navigation\n\n| Key | Action |\n|-----|--------|\n| `j` / `↓` | Move down |\n| `k` / `↑` | Move up |\n| `g` / `Home` | Go to first item |\n| `G` / `End` | Go to last item |\n| `Tab` | Switch focus (services ↔ logs) |\n\n### Service Actions\n\n| Key | Action |\n|-----|--------|\n| `Enter` | Open detail view for selected service |\n| `d` | Remove forward for selected service |\n| `r` | Reconnect all errored services |\n| `R` | Force reconnect selected service |\n\n### Detail View\n\n| Key | Action |\n|-----|--------|\n| `1` - `9` | Copy connection string #N to clipboard |\n| `y` | Copy first connection string |\n| `Tab` | Next tab |\n| `Esc` / `q` | Close detail view |\n\n## Auto-Reconnect\n\nTUI enables auto-reconnect by default with exponential backoff:\n\n```\n1s → 2s → 4s → 8s → 16s → 32s → 64s → 128s → 256s → 300s (max)\n```\n\nPress `r` to force immediate reconnection of all errored services.\n\n---\n\n# Configuration\n\nComplete reference for kubefwd command line flags.\n\n## Essential Flags\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--namespace` | `-n` | Namespace(s) to forward services from |\n| `--tui` | | Enable interactive terminal user interface |\n| `--selector` | `-l` | Label selector to filter services |\n| `--field-selector` | `-f` | Field selector to filter services |\n| `--all-namespaces` | `-A` | Forward services from all namespaces |\n\n## TUI and Behavior Flags\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--tui` | | false | Enable interactive TUI mode |\n| `--auto-reconnect` | `-a` | true (TUI) | Automatically reconnect lost port forwards |\n| `--verbose` | `-v` | false | Enable debug logging |\n\n## Network Configuration\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--mapping` | `-m` | Port mapping (e.g., `-m 80:8080`) |\n| `--reserve` | `-r` | Reserve specific IP for service |\n| `--fwd-conf` | `-z` | Path to IP reservation config file |\n| `--domain` | `-d` | Append domain suffix to hostnames |\n\n## Examples\n\n```bash\n# Forward all services in a namespace with TUI\nsudo -E kubefwd svc -n default --tui\n\n# Multiple namespaces\nsudo -E kubefwd svc -n frontend,backend,data --tui\n\n# Filter by label\nsudo -E kubefwd svc -n default -l app=api --tui\n\n# Port mapping (80 → 8080)\nsudo -E kubefwd svc -n default -m 80:8080 --tui\n\n# IP reservation\nsudo -E kubefwd svc -n default -r my-service.default:127.3.3.1 --tui\n```\n\n---\n\n# REST API\n\nkubefwd's REST API enables programmatic control over port forwarding.\n\n## Quick Start\n\n```bash\n# Idle mode - API enabled by default\nsudo -E kubefwd\n\n# Test the API\ncurl http://kubefwd.internal/api/health\n```\n\nBase URL: `http://kubefwd.internal/api`\n\n## Key Endpoints\n\n### Health & Info\n\n- `GET /api/health` - Health check\n- `GET /api/info` - Server information\n\n### Services\n\n- `GET /api/v1/services` - List forwarded services\n- `GET /api/v1/services/:key` - Get specific service\n- `POST /api/v1/services` - Add service to forward\n- `DELETE /api/v1/services/:key` - Stop forwarding\n- `POST /api/v1/services/:key/reconnect` - Reconnect service\n\n### Namespaces\n\n- `GET /api/v1/namespaces` - List namespace watchers\n- `POST /api/v1/namespaces` - Add namespace (forward all services)\n- `DELETE /api/v1/namespaces/:key` - Remove namespace\n\n### Kubernetes Discovery\n\n- `GET /api/v1/kubernetes/contexts` - List kubeconfig contexts\n- `GET /api/v1/kubernetes/namespaces` - List namespaces\n- `GET /api/v1/kubernetes/services` - List services in namespace\n- `GET /api/v1/kubernetes/pods/:namespace` - List pods\n- `GET /api/v1/kubernetes/pods/:namespace/:pod/logs` - Get pod logs\n\n### Metrics & Diagnostics\n\n- `GET /api/v1/metrics` - Summary metrics\n- `GET /api/v1/diagnostics` - Diagnostics summary\n- `GET /api/v1/diagnostics/errors` - Current errors\n\n### Events (SSE)\n\n- `GET /api/v1/events` - Real-time event stream\n\n---\n\n# MCP Integration\n\n## What is MCP?\n\nThe Model Context Protocol (MCP) lets AI assistants connect to external tools. kubefwd's MCP integration gives AI assistants full access to Kubernetes port forwarding.\n\n## Platform Support\n\n| Platform | Support |\n|----------|---------|\n| Claude Code | Full |\n| Claude Desktop | Full |\n| Cursor | Full |\n| Windsurf | Full |\n| VS Code Copilot | Full |\n| Zed | Full |\n| JetBrains IDEs | Full |\n\n## Setup\n\n### 1. Start kubefwd\n\n```bash\nsudo -E kubefwd --tui\n```\n\n### 2. Configure AI Client\n\n**Claude Code:**\n```bash\nclaude mcp add --transport stdio kubefwd -- kubefwd mcp\n```\n\n**Cursor/Windsurf/VS Code:**\nAdd to MCP config:\n```json\n{\n  \"mcpServers\": {\n    \"kubefwd\": {\n      \"command\": \"kubefwd\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n## What Your AI Can Do\n\n### Service Forwarding\n- Forward entire namespaces\n- Forward individual services\n- Remove forwards\n- Multi-context support\n\n### Discovery & Connection\n- List Kubernetes contexts\n- List namespaces and services\n- Get connection info (IPs, hostnames, env vars)\n- Find services by name/port\n\n### Pod Debugging\n- List pods with status\n- Get pod details and logs\n- View Kubernetes events\n- Check service endpoints\n\n### Monitoring & Troubleshooting\n- Quick status checks\n- Traffic metrics\n- Error diagnosis\n- Reconnect services\n\n## Example Conversations\n\n**You:** \"I need to connect to PostgreSQL in kft1\"\n**AI:** \"Connected. Use: `psql -h postgres -U admin -d mydb`\"\n\n**You:** \"Set up my environment for the checkout service\"\n**AI:** \"Ready. Services available: cart-service:8080, payment-service:443, user-db:5432\"\n\n**You:** \"My API calls to auth-service are failing\"\n**AI:** \"The auth-service pod restarted. I've reconnected it. Try again.\"\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nkubefwd is a popular command-line utility for bulk Kubernetes port forwarding, featured in \"essential k8s developer tools\" lists. It forwards multiple services from one or more namespaces, adding corresponding entries to `/etc/hosts` for local development.\n\n**Key Differentiator from `kubectl port-forward`**: Each service gets its own unique loopback IP address (127.x.x.x), allowing multiple services to use the same port simultaneously (e.g., multiple databases on port 3306, or multiple web services on port 80). This mirrors how services work in the cluster, enabling truly cluster-like local development.\n\nThe tool automatically monitors service and pod lifecycle events, starting/stopping port forwards as services are created, deleted, or pods are rescheduled.\n\n## Integration and Usage Patterns\n\nkubefwd is commonly integrated into development workflows:\n\n- **With Tilt**: Blog posts document using kubefwd with Tilt for automated local development setups\n- **Development Environment Setup**: Teams use kubefwd to mirror production-like service topologies locally\n- **Microservices Development**: Allows developers to run one service locally while accessing dependencies in the cluster via service names\n- **Database Access**: Popular for forwarding multiple databases (MySQL, PostgreSQL, MongoDB) on their native ports without port conflicts\n\nThe typical workflow: `sudo -E kubefwd svc -n <namespace> --tui` runs in a dedicated terminal while developers work in their IDE, accessing cluster services as if running in-cluster.\n\n## TUI (Terminal User Interface)\n\nkubefwd includes an interactive TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), enabled with `--tui`:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n### TUI Features\n- **Real-time service monitoring**: See all forwarded services with connection status\n- **Traffic metrics**: Bytes in/out with sparkline graphs\n- **Pod log streaming**: View container logs directly in the TUI\n- **HTTP activity detection**: Monitor HTTP requests/responses flowing through forwards\n- **Auto-reconnect**: Enabled by default in TUI mode, with exponential backoff (1s → 5min max)\n- **Keyboard-driven**: Full keyboard navigation (j/k, Enter, Tab, /, ?, q)\n\n### TUI Architecture\n\nThe TUI follows the Model-View-Update (MVU) pattern:\n\n- **Event Bus** (`pkg/fwdtui/events`): Decoupled pub/sub communication between components\n- **State Store** (`pkg/fwdtui/state`): Centralized, thread-safe state management for all forwards\n- **Metrics Registry** (`pkg/fwdtui/metrics`): Traffic counters with atomic operations\n- **Components** (`pkg/fwdtui/components`): UI models for services list, logs, detail view\n\n### TUI Keyboard Shortcuts\n- `j/k` or arrows: Navigate\n- `Enter`: Open detail view\n- `Tab`: Switch panels/tabs\n- `/`: Filter services\n- `r`: Reconnect errored services\n- `b`: Toggle bandwidth columns\n- `?`: Help overlay\n- `q`: Quit\n\n## Git Policy\n\n**All commits require explicit human approval.** Do not run `git commit` unless the user explicitly asks you to commit. Always show the diff or summarize changes and wait for approval first.\n\n## Verification\n\n**\"Testing\" means `make verify`, not `go test ./...`.** Run it before handing work back; it runs every check CI runs, with the same pinned tools, and a change isn't done until it passes.\n\nThe gates (details in CONTRIBUTING.md, \"Quality Gates\"):\n\n- **Formatting**: gofmt, goimports (`github.com/txn2/kubefwd` local prefix), gofumpt over the whole tree. Fix with `make fmt`.\n- **Lint**: every linter in `.golangci.yml` applies to lines changed since the merge base with `origin/master` (`make lint`, CI `--new-from-rev`). Pre-existing issues elsewhere don't fail; anything touched must pass. `make lint-full` shows the backlog. A `//nolint` or `#nosec` needs a reason.\n- **Complexity** (production code): gocyclo 10, gocognit 15, nestif 5, dupl 150, nakedret 30. Split functions rather than suppressing.\n- **Layering**: depguard rules in `.golangci.yml`; `pkg/` never imports `cmd/`, leaf packages import nothing first-party, the forwarding core never imports `fwdapi`/`fwdmcp`.\n- **Coverage**: total ≥ 80% (`make coverage-check`); changed lines ≥ 80% (`make patch-coverage`). Both block, here and in codecov. Root-only or cluster-only code is made testable by injecting the OS call (see `runCommand` and `goos` in `pkg/fwdapi/network.go`), not left uncovered.\n- **Security**: `make security` runs gosec, govulncheck on both modules (gated by `scripts/govulncheck-gate.py` against `.govulncheck-allow.txt`), and osv-scanner (against `osv-scanner.toml`). Upgrade rather than accept; an accepted advisory needs a reason and expires.\n- **SAST**: `make semgrep` (p/golang, whole tree) and `make semgrep-diff` (`.semgrep-diff/` rules, changed lines). CodeQL runs `security-and-quality` in CI.\n- **Mutation**: `make mutate` (gremlins, 60% efficacy), weekly in CI. Too slow for every change.\n- **Toolchain**: Go is pinned by the `toolchain` line in go.mod; CI's setup-go reads the same line. Tool versions are pinned in the Makefile and installed into `.tools/`.\n\n## Build and Development Commands\n\n### Building\n```bash\n# Build the project (uses goreleaser)\ngo build -o kubefwd ./cmd/kubefwd/kubefwd.go\n\n# Build with version information\ngo build -ldflags \"-X main.Version=dev\" -o kubefwd ./cmd/kubefwd/kubefwd.go\n```\n\n### Testing\n```bash\n# Run all tests\ngo test ./...\n\n# Run tests for a specific package\ngo test ./pkg/fwdport\n\n# Run tests with verbose output\ngo test -v ./pkg/fwdport\n```\n\n### Running Locally\n```bash\n# Requires root/sudo for network interface management and /etc/hosts modification\nsudo ./kubefwd svc -n <namespace>\n\n# Use -E flag to preserve environment (especially KUBECONFIG)\nsudo -E ./kubefwd svc -n <namespace>\n\n# With interactive TUI (recommended for development)\nsudo -E ./kubefwd svc -n <namespace> --tui\n```\n\n### Dependencies\n```bash\n# Download dependencies\ngo mod download\n\n# Update dependencies\ngo mod tidy\n```\n\n### Debugging and Development\n\n```bash\n# Enable verbose logging\nsudo -E ./kubefwd svc -n <namespace> -v\n\n# Test with a single service using field selector\nsudo -E ./kubefwd svc -n <namespace> -f metadata.name=<service-name>\n\n# Test with label selector\nsudo -E ./kubefwd svc -n <namespace> -l app=myapp\n\n# Use IP reservation config for reproducible testing\nsudo -E ./kubefwd svc -n <namespace> -z example.fwdconf.yml\n```\n\nThe verbose flag (`-v`) enables debug-level logging (logrus.DebugLevel), which shows:\n- Service registry operations\n- Pod sync events\n- IP allocation details\n- Port forwarding lifecycle events\n\n### Demo Environment\n\nA comprehensive demo manifest is available for testing:\n\n```bash\n# Deploy 60 services across 2 namespaces\nkubectl apply -f test/manifests/demo-microservices.yaml\n\n# Forward all demo services with TUI\nsudo -E ./kubefwd svc -n kft1,kft2 --tui\n\n# Cleanup\nkubectl delete -f test/manifests/demo-microservices.yaml\n```\n\n## Architecture\n\n### Core Components Flow\n\n1. **Entry Point** (`cmd/kubefwd/kubefwd.go`): CLI entry, delegates to services command\n2. **Services Command** (`cmd/kubefwd/services/services.go`): Main orchestration logic\n   - Validates cluster connectivity and RBAC permissions\n   - Creates Kubernetes informers to watch Service events (Add/Delete/Update)\n   - Spawns namespace watchers for each namespace×context combination\n3. **Service Registry** (`pkg/fwdsvcregistry`): Central registry of all forwarded services\n   - Thread-safe map of active ServiceFWD instances\n   - Handles lifecycle (add, remove, shutdown all)\n4. **Service Forwarding** (`pkg/fwdservice`): Per-service forwarding logic\n   - Queries pods backing each service\n   - Manages pod selection (single pod for normal services, all pods for headless)\n   - Debounces pod sync operations to avoid hammering k8s API\n   - Maintains map of active port forwards per pod\n5. **Port Forwarding** (`pkg/fwdport`): Individual pod port forwarding\n   - Creates SPDY connection to k8s API server\n   - Manages port forward lifecycle with watch for pod deletion\n   - Updates `/etc/hosts` file with service hostnames\n6. **Network/IP Management** (`pkg/fwdnet`, `pkg/fwdIp`): Loopback interface management\n   - Allocates unique 127.x.x.x IPs for each service\n   - Manages IP aliases on loopback interface (macOS: lo0, Linux: lo)\n   - Supports IP reservation via config file or CLI flags\n\n### Key Architectural Patterns\n\n**Event-Driven Architecture**: Uses Kubernetes informers to react to service/pod lifecycle events in real-time.\n\n**Headless vs Normal Services**:\n- Normal services forward the first available pod using the service name\n- Headless services (ClusterIP: None) forward all pods, with first pod as service name and rest as pod-name.service-name\n\n**Debouncing**: Uses 5-second debouncer for pod sync operations to handle rapid pod changes (e.g., rolling deployments) without excessive k8s API calls.\n\n**Thread Safety**: Extensive use of mutexes for:\n- Per-namespace IP allocation (`NamespaceIPLock`)\n- Service registry access\n- Hosts file modifications\n\n**Shutdown Orchestration**: Clean shutdown cascade:\n1. User signal → stopListenCh\n2. Namespace watchers stop\n3. Service registry shutdown\n4. Individual pod port forwards stop\n5. Hosts file cleanup and network alias removal\n\n### Package Responsibilities\n\n- `fwdservice`: Service-level forwarding orchestration and pod management\n- `fwdport`: Individual pod port forwarding via k8s API\n- `fwdsvcregistry`: Global service registry and lifecycle management\n- `fwdnet`: Network interface management (IP aliasing)\n- `fwdIp`: IP allocation logic and reservation handling\n- `fwdhost`: Hosts file backup management\n- `fwdcfg`: Kubernetes client configuration\n- `fwdpub`: Publisher interface for output\n- `fwdtui`: Terminal User Interface (Bubble Tea)\n  - `fwdtui/components`: UI view models (services list, logs, detail, help, status bar)\n  - `fwdtui/events`: Event bus with panic recovery for decoupled pub/sub\n  - `fwdtui/state`: Thread-safe state store with RWMutex protection\n  - `fwdtui/metrics`: Traffic metrics with atomic counters and rate calculation\n  - `fwdtui/portforward`: Port forward wrapper that emits metrics events\n- `utils`: Root permission checks (OS-specific)\n\n## Important Implementation Details\n\n### Root Permissions and Security\n\nkubefwd requires superuser privileges for:\n- Adding IP aliases to loopback interface\n- Binding to low-numbered ports\n- Modifying `/etc/hosts`\n\nAlways run with `sudo -E` to preserve environment variables (KUBECONFIG).\n\n**Security Considerations**: kubefwd is considered a \"powerful but potentially dangerous tool\" because it:\n- Modifies system-level network configuration\n- Changes `/etc/hosts` which affects DNS resolution system-wide\n- Requires root access which can impact system stability if misused\n- Opens network connections to cluster services\n\nThe tool backs up the original hosts file to `~/hosts.original` before making modifications, but improper shutdown can leave the system in an inconsistent state.\n\n### Hostname Generation\nHostnames follow pattern based on cluster and namespace indices:\n- Namespace 0, Cluster 0: `service-name`\n- Namespace >0: `service-name.namespace`\n- Cluster >0: `service-name.context` or `service-name.namespace.context`\n\nFor headless services, pods get: `pod-name.service-name[.namespace][.context]`\n\n### IP Allocation\nBase IP is 127.1.x.x with incremental allocation. Can be customized via:\n- `--fwd-conf` YAML config file (see `example.fwdconf.yml`)\n- `--reserve` CLI flag for individual reservations\n\n### Port Mapping\nSupports port remapping with `-m` flag (e.g., `-m 80:8080` maps service port 80 to local 8080).\n\n### UDP Limitation\nUDP port forwarding is not supported (Kubernetes API limitation: kubernetes/kubernetes#47862).\n\n## Code Organization\n\n```\ncmd/kubefwd/           # CLI entry point\n  kubefwd.go          # Main entry, root command\n  services/\n    services.go       # Services subcommand, namespace watchers\npkg/\n  fwdservice/         # Service forwarding logic\n  fwdport/            # Pod port forwarding\n  fwdsvcregistry/     # Service registry\n  fwdnet/             # Network interface management\n  fwdIp/              # IP allocation\n  fwdhost/            # Hosts file operations\n  fwdcfg/             # K8s config\n  fwdpub/             # Publisher\n  fwdtui/             # Terminal User Interface\n    components/       # UI models (services, logs, detail, help)\n    events/           # Event bus for decoupled communication\n    state/            # Centralized state store\n    metrics/          # Traffic metrics with atomic counters\n    portforward/      # Port forward wrapper with metrics\n  utils/              # Utilities (root check)\ntest/\n  integration/        # Integration tests (require KIND cluster)\n  manifests/          # Test Kubernetes manifests\n  scripts/            # Test setup/teardown scripts\n```\n\n## Contribution Policy\n\n**Public Contributions**: The project welcomes pull requests from the community for:\n- Bug fixes\n- Tests\n- Documentation\n- Stability and compatibility enhancements\n\n**Feature Development**: New features are developed by select contributors only. Public feature PRs are discouraged due to past experience with contributions that introduced drastic codebase changes, were difficult to review and test, and added significant technical debt. This policy is documented in the README.\n\n**Internal Development**: Maintainers and trusted contributors are welcome to develop new features. If you're working on this codebase with direct access, feature development is encouraged.\n\n## Release Process\n\nUses GoReleaser (`.goreleaser.yml`):\n- Builds for Linux, macOS, Windows (multiple architectures)\n- Creates Docker images (Alpine and Ubuntu variants)\n- Publishes to GitHub releases\n- Updates Homebrew tap (txn2/homebrew-tap)\n- Generates RPM, DEB, APK packages\n\nThe version is set via ldflags during build: `-ldflags \"-X main.Version={{.Version}}\"`\n\n## Testing\n\n### Unit Tests\n\n`make verify` is the full check (see Verification above). For quicker loops:\n\n```bash\n# Run all unit tests\ngo test ./...\n\n# Run with coverage\ngo test -cover ./...\n\n# Run specific package tests\ngo test -v ./pkg/fwdtui/events/...     # Event bus tests (100% coverage)\ngo test -v ./pkg/fwdtui/components/... # UI component tests\ngo test -v ./pkg/fwdtui/state/...      # State store tests\ngo test -v ./pkg/fwdport/...           # Port forwarding tests\n```\n\n### Integration Tests\n\nLocated in `test/integration/`, these require a KIND cluster:\n\n```bash\n# Setup KIND cluster\n./test/scripts/setup-kind.sh\n./test/scripts/deploy-test-services.sh test/manifests\n\n# Run integration tests (requires sudo)\nsudo -E go test -tags=integration -v ./test/integration/...\n\n# Teardown\n./test/scripts/teardown-kind.sh\n```\n\nIntegration tests cover: basic forwarding, headless services, auto-reconnect, multi-namespace, port mapping, and cleanup verification.\n\n### Areas for Additional Testing\n- Hosts file race condition scenarios (Issue #74)\n- Cleanup/restore logic for error conditions (Issue #5)\n- Pod state filtering for evicted/completed pods (Issues #34, #114)\n\n## Areas for Improvement\n\nBased on known issues, these areas would benefit from development:\n\n### Auto-Reconnect Enhancement\nAuto-reconnect is now implemented (`-a` flag, enabled by default in TUI mode) with exponential backoff. However, edge cases may still exist:\n- Very rapid pod cycling during rolling deployments\n- Network partitions vs pod deletion detection\n- Reconnection priority when multiple pods are available\n\n### Hosts File Synchronization (Issues #74, #79)\nThe `HostFileWithLock` mutex in `pkg/fwdport` may not be sufficient for all race conditions. Consider:\n- Batching hosts file updates\n- Implementing retry logic for failed updates\n- Adding verification that all services are actually written\n\n### Graceful Shutdown (Issue #5)\nEnhance the shutdown cascade to guarantee hosts file restoration even on signal interruption. Consider using `defer` more extensively or implementing a signal handler with guaranteed cleanup.\n\n### Pod State Filtering (Issues #34, #114)\nThe pod filtering in `fwdservice.GetPodsForService()` should be more defensive:\n- Handle additional pod phases gracefully\n- Add better error handling for watch events with non-pod objects\n- Consider ignoring evicted pods earlier in the pipeline\n\n### Services Without Selectors (Issue #35)\nCould potentially support endpoint-based services by querying Endpoints resources directly instead of relying on pod selectors.\n\n## Known Limitations and Active Issues\n\nBased on community feedback and GitHub issues, developers should be aware of:\n\n### Architectural Limitations\n\n**Services Without Selectors** (Issue #35): kubefwd does not support ClusterIP services without selectors (services backed by manually created Endpoints). The code assumes services have pod selectors and will skip services with empty selector strings.\n\n**Auto-Reconnect Available** (Issue #21 resolved): Auto-reconnect is now implemented with the `-a` flag (enabled by default in TUI mode). When pods restart, kubefwd automatically re-establishes port forwards with exponential backoff (1s → 5min max).\n\n**UDP Protocol Not Supported**: Kubernetes port-forwarding API limitation (kubernetes/kubernetes#47862).\n\n### Race Conditions and Edge Cases\n\n**Hosts File Race Condition** (Issue #74): When forwarding multiple services simultaneously, especially on Windows with Docker Desktop, race conditions can occur during hosts file updates, leading to DNS resolution errors.\n\n**Hosts File Not Fully Restored** (Issue #5): On certain error conditions or unclean shutdowns (Ctrl-C timing), the original `/etc/hosts` may not be fully restored. Always check `~/hosts.original` backup.\n\n**Incomplete Hosts File Updates** (Issue #79): Some services may be assigned IPs and be accessible but not appear in the hosts file. This appears related to timing in the hosts file update logic.\n\n### Pod State Handling\n\n**Evicted/Completed Pods** (Issues #34, #114): Starting from v1.11.0, interface conversion errors occur with evicted pods or completed jobs. The code in `pkg/fwdservice` filters for `PodPending` and `PodRunning` states, but watch events for other states can cause errors.\n\n**Pod Status Assumptions**: The code assumes pods are either Pending, Running, Succeeded, Failed, or Unknown. Edge cases with custom pod conditions may not be handled gracefully.\n\n## Common Issues and Troubleshooting\n\n**Permission Errors**: Always use `sudo -E` to preserve KUBECONFIG.\n\n**IP/Port Conflicts**: Use IP reservations (`-r` or `-z`) to avoid conflicts.\n\n**Stale /etc/hosts Entries**: Original hosts file backed up to `~/hosts.original`. Check this file if DNS resolution is broken after kubefwd exits.\n\n**Pod Watch Failures**: Check RBAC permissions (list/get/watch pods, get services).\n\n**Connection Refused (localhost:8080)**: This usually means kubectl is not properly configured or KUBECONFIG was not preserved (missing `-E` flag with sudo).\n"},"items":[{"name":"llms-full.txt","path":"docs/llms-full.txt","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/docs/llms-full.txt","title":"docs - LLM Full Documentation Context","category":"root-instruction","format":"text","content":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n---\n\n# Getting Started\n\nThis guide covers installation and your first steps with kubefwd. By the end, you'll have cluster services accessible locally by name.\n\n## Prerequisites\n\n- **kubectl configured** with access to a Kubernetes cluster\n- **Root/sudo access** (required for `/etc/hosts` and network interface modifications)\n\nkubefwd reads your kubeconfig (`~/.kube/config` or `KUBECONFIG` environment variable) and connects directly to the Kubernetes API.\n\n## Installation\n\n### macOS\n\nUsing Homebrew:\n\n```bash\nbrew install txn2/tap/kubefwd\n```\n\n### Windows\n\nUsing Scoop:\n\n```powershell\nscoop install kubefwd\n```\n\nRun as Administrator for hosts file access.\n\n### Linux (Debian/Ubuntu)\n\nDownload the `.deb` package from GitHub Releases:\n\n```bash\nsudo dpkg -i kubefwd_*_amd64.deb\n```\n\n### Linux (RHEL/Fedora)\n\nDownload the `.rpm` package from GitHub Releases:\n\n```bash\nsudo rpm -i kubefwd_*_amd64.rpm\n```\n\n### Docker\n\n```bash\ndocker run -it --rm --privileged \\\n    -v \"$HOME/.kube:/root/.kube:ro\" \\\n    txn2/kubefwd --tui\n```\n\nVerify installation:\n\n```bash\nkubefwd version\n```\n\n## Operating Modes\n\n### Idle Mode (Recommended)\n\nStart without pre-specified services and add them interactively:\n\n```bash\nsudo -E kubefwd --tui\n```\n\nIn Idle Mode:\n- REST API is enabled by default\n- Auto-reconnect is enabled by default\n- Use TUI to browse namespaces, select services, forward them\n- Or use API to add services dynamically\n\n### Classic Mode\n\nSpecify namespaces upfront. All services forwarded immediately:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n## Your First Forward\n\n1. Start kubefwd in Idle Mode:\n   ```bash\n   sudo -E kubefwd --tui\n   ```\n\n2. Browse namespaces: Press `f` to open the service browser, then select a namespace.\n\n3. Forward services: Select individual services or press `a` to forward all.\n\n4. Use your services:\n   ```bash\n   curl http://my-api:8080/health\n   psql -h postgres -U admin -d mydb\n   redis-cli -h redis ping\n   ```\n\n5. Quit: Press `q` to exit. kubefwd cleans up automatically.\n\n## What Happens Under the Hood\n\nWhen kubefwd forwards a service:\n\n1. **IP Allocation**: Each service gets a unique loopback IP (e.g., `127.1.27.1`)\n2. **Hosts File Update**: Service names added to `/etc/hosts`\n3. **Port Forwarding**: Creates port forwards to pods backing each service\n4. **Ready to Use**: Applications connect using service names\n\n### Cleanup\n\nWhen kubefwd exits:\n- `/etc/hosts` entries are removed\n- Network interface aliases are cleaned up\n- All port forward connections are closed\n\nOriginal hosts file backed up to `~/hosts.original`.\n\n## Why sudo -E?\n\nkubefwd requires root privileges for:\n- Modifying `/etc/hosts`\n- Creating loopback IP aliases\n- Binding to ports below 1024\n\nThe `-E` flag preserves environment variables, especially `KUBECONFIG`:\n\n```bash\n# Correct - preserves KUBECONFIG\nsudo -E kubefwd --tui\n\n# Wrong - may fail to find cluster config\nsudo kubefwd --tui\n```\n\n## Enabling the REST API\n\n**Idle Mode** (API enabled by default):\n```bash\nsudo -E kubefwd\nsudo -E kubefwd --tui\n```\n\n**Classic Mode** (add `--api` flag):\n```bash\nsudo -E kubefwd svc -n default --api\n```\n\nAPI available at:\n- `http://kubefwd.internal/api` - REST endpoints\n- `http://kubefwd.internal/docs` - Interactive API documentation\n\n---\n\n# User Guide\n\nThe Terminal User Interface (TUI) transforms kubefwd into an interactive development companion.\n\n## Interface Overview\n\n### Main View\n\n| Panel | Description |\n|-------|-------------|\n| **Services** | All forwarded services with status, namespace, local address, traffic |\n| **Logs** | Real-time kubefwd activity, connection events, errors |\n| **Status Bar** | Service counts, current filter, keyboard hints |\n\n### Service Status Indicators\n\n| Indicator | Meaning |\n|-----------|---------|\n| Green dot | Active and forwarding |\n| Yellow dot | Connecting or reconnecting |\n| Red dot | Error state |\n\n## Keyboard Shortcuts\n\n### Global\n\n| Key | Action |\n|-----|--------|\n| `q` | Quit kubefwd |\n| `?` | Toggle help overlay |\n| `f` | Open namespace/service browser |\n| `x` | Switch Kubernetes context |\n| `/` | Filter services |\n| `Esc` | Clear filter / Close modal |\n\n### Navigation\n\n| Key | Action |\n|-----|--------|\n| `j` / `↓` | Move down |\n| `k` / `↑` | Move up |\n| `g` / `Home` | Go to first item |\n| `G` / `End` | Go to last item |\n| `Tab` | Switch focus (services ↔ logs) |\n\n### Service Actions\n\n| Key | Action |\n|-----|--------|\n| `Enter` | Open detail view for selected service |\n| `d` | Remove forward for selected service |\n| `r` | Reconnect all errored services |\n| `R` | Force reconnect selected service |\n\n### Detail View\n\n| Key | Action |\n|-----|--------|\n| `1` - `9` | Copy connection string #N to clipboard |\n| `y` | Copy first connection string |\n| `Tab` | Next tab |\n| `Esc` / `q` | Close detail view |\n\n## Auto-Reconnect\n\nTUI enables auto-reconnect by default with exponential backoff:\n\n```\n1s → 2s → 4s → 8s → 16s → 32s → 64s → 128s → 256s → 300s (max)\n```\n\nPress `r` to force immediate reconnection of all errored services.\n\n---\n\n# Configuration\n\nComplete reference for kubefwd command line flags.\n\n## Essential Flags\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--namespace` | `-n` | Namespace(s) to forward services from |\n| `--tui` | | Enable interactive terminal user interface |\n| `--selector` | `-l` | Label selector to filter services |\n| `--field-selector` | `-f` | Field selector to filter services |\n| `--all-namespaces` | `-A` | Forward services from all namespaces |\n\n## TUI and Behavior Flags\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--tui` | | false | Enable interactive TUI mode |\n| `--auto-reconnect` | `-a` | true (TUI) | Automatically reconnect lost port forwards |\n| `--verbose` | `-v` | false | Enable debug logging |\n\n## Network Configuration\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--mapping` | `-m` | Port mapping (e.g., `-m 80:8080`) |\n| `--reserve` | `-r` | Reserve specific IP for service |\n| `--fwd-conf` | `-z` | Path to IP reservation config file |\n| `--domain` | `-d` | Append domain suffix to hostnames |\n\n## Examples\n\n```bash\n# Forward all services in a namespace with TUI\nsudo -E kubefwd svc -n default --tui\n\n# Multiple namespaces\nsudo -E kubefwd svc -n frontend,backend,data --tui\n\n# Filter by label\nsudo -E kubefwd svc -n default -l app=api --tui\n\n# Port mapping (80 → 8080)\nsudo -E kubefwd svc -n default -m 80:8080 --tui\n\n# IP reservation\nsudo -E kubefwd svc -n default -r my-service.default:127.3.3.1 --tui\n```\n\n---\n\n# REST API\n\nkubefwd's REST API enables programmatic control over port forwarding.\n\n## Quick Start\n\n```bash\n# Idle mode - API enabled by default\nsudo -E kubefwd\n\n# Test the API\ncurl http://kubefwd.internal/api/health\n```\n\nBase URL: `http://kubefwd.internal/api`\n\n## Key Endpoints\n\n### Health & Info\n\n- `GET /api/health` - Health check\n- `GET /api/info` - Server information\n\n### Services\n\n- `GET /api/v1/services` - List forwarded services\n- `GET /api/v1/services/:key` - Get specific service\n- `POST /api/v1/services` - Add service to forward\n- `DELETE /api/v1/services/:key` - Stop forwarding\n- `POST /api/v1/services/:key/reconnect` - Reconnect service\n\n### Namespaces\n\n- `GET /api/v1/namespaces` - List namespace watchers\n- `POST /api/v1/namespaces` - Add namespace (forward all services)\n- `DELETE /api/v1/namespaces/:key` - Remove namespace\n\n### Kubernetes Discovery\n\n- `GET /api/v1/kubernetes/contexts` - List kubeconfig contexts\n- `GET /api/v1/kubernetes/namespaces` - List namespaces\n- `GET /api/v1/kubernetes/services` - List services in namespace\n- `GET /api/v1/kubernetes/pods/:namespace` - List pods\n- `GET /api/v1/kubernetes/pods/:namespace/:pod/logs` - Get pod logs\n\n### Metrics & Diagnostics\n\n- `GET /api/v1/metrics` - Summary metrics\n- `GET /api/v1/diagnostics` - Diagnostics summary\n- `GET /api/v1/diagnostics/errors` - Current errors\n\n### Events (SSE)\n\n- `GET /api/v1/events` - Real-time event stream\n\n---\n\n# MCP Integration\n\n## What is MCP?\n\nThe Model Context Protocol (MCP) lets AI assistants connect to external tools. kubefwd's MCP integration gives AI assistants full access to Kubernetes port forwarding.\n\n## Platform Support\n\n| Platform | Support |\n|----------|---------|\n| Claude Code | Full |\n| Claude Desktop | Full |\n| Cursor | Full |\n| Windsurf | Full |\n| VS Code Copilot | Full |\n| Zed | Full |\n| JetBrains IDEs | Full |\n\n## Setup\n\n### 1. Start kubefwd\n\n```bash\nsudo -E kubefwd --tui\n```\n\n### 2. Configure AI Client\n\n**Claude Code:**\n```bash\nclaude mcp add --transport stdio kubefwd -- kubefwd mcp\n```\n\n**Cursor/Windsurf/VS Code:**\nAdd to MCP config:\n```json\n{\n  \"mcpServers\": {\n    \"kubefwd\": {\n      \"command\": \"kubefwd\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n## What Your AI Can Do\n\n### Service Forwarding\n- Forward entire namespaces\n- Forward individual services\n- Remove forwards\n- Multi-context support\n\n### Discovery & Connection\n- List Kubernetes contexts\n- List namespaces and services\n- Get connection info (IPs, hostnames, env vars)\n- Find services by name/port\n\n### Pod Debugging\n- List pods with status\n- Get pod details and logs\n- View Kubernetes events\n- Check service endpoints\n\n### Monitoring & Troubleshooting\n- Quick status checks\n- Traffic metrics\n- Error diagnosis\n- Reconnect services\n\n## Example Conversations\n\n**You:** \"I need to connect to PostgreSQL in kft1\"\n**AI:** \"Connected. Use: `psql -h postgres -U admin -d mydb`\"\n\n**You:** \"Set up my environment for the checkout service\"\n**AI:** \"Ready. Services available: cart-service:8080, payment-service:443, user-db:5432\"\n\n**You:** \"My API calls to auth-service are failing\"\n**AI:** \"The auth-service pod restarted. I've reconnected it. Try again.\"\n","isInternal":false,"tokens":2759,"sizeBytes":10132},{"name":"llms.txt","path":"docs/llms.txt","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/docs/llms.txt","title":"docs - LLM Index & Context Digest","category":"root-instruction","format":"text","content":"# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n## Documentation\n\n- [Getting Started](https://kubefwd.com/getting-started/): Installation, prerequisites, and first forward\n- [User Guide](https://kubefwd.com/user-guide/): Interactive TUI interface and keyboard shortcuts\n- [Configuration](https://kubefwd.com/configuration/): CLI flags, IP reservations, and port mapping\n- [REST API](https://kubefwd.com/api-reference/): Programmatic control via 40+ HTTP endpoints\n- [MCP Integration](https://kubefwd.com/mcp-integration/): AI assistant integration (Claude, Cursor, VS Code)\n\n## Key Features\n\n- **Unique IP per service**: Multiple databases on port 3306 work without conflicts\n- **Auto-reconnect**: Reconnects automatically when pods restart\n- **Interactive TUI**: Browse namespaces, monitor traffic, stream logs\n- **Service name resolution**: Updates /etc/hosts so apps connect by service name\n- **REST API**: Add/remove services dynamically\n- **MCP support**: Natural language control via AI assistants\n\n## Quick Start\n\n```bash\n# Install (macOS)\nbrew install txn2/tap/kubefwd\n\n# Forward services with TUI\nsudo -E kubefwd svc -n my-namespace --tui\n```\n\n## Optional\n\n- [Troubleshooting](https://kubefwd.com/troubleshooting/): Common issues and solutions\n- [Architecture](https://kubefwd.com/architecture/): Technical implementation details\n- [Comparison](https://kubefwd.com/comparison/): vs kubectl port-forward, Telepresence, mirrord\n- [GitHub Repository](https://github.com/txn2/kubefwd): Source code, issues, releases\n","isInternal":false,"tokens":455,"sizeBytes":1888},{"name":"DESIGN.md","path":"DESIGN.md","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/DESIGN.md","title":"kubefwd-docs","category":"project-spec","format":"markdown","content":"---\nversion: alpha\nspec: https://github.com/google-labs-code/design.md\nname: kubefwd-docs\ndescription: Local design adoption record for the kubefwd.com documentation site. References txn2/www DESIGN.md as the canonical visual identity for tokens, typography, components, copyright voice, and accessibility rules. Records only the decisions and MkDocs Material learnings that the canonical does not cover.\nupstream:\n  design: https://github.com/txn2/www/blob/master/DESIGN.md\n  tokens: https://github.com/txn2/www/blob/master/tokens.json\nadoption: token-alignment\nstack:\n  generator: MkDocs\n  theme: Material for MkDocs\n  templates: docs/overrides/\n  styles: docs/stylesheets/extra.css\n---\n\n## What is canonical\n\nThe canonical visual identity for txn2 lives in [`txn2/www/DESIGN.md`](https://github.com/txn2/www/blob/master/DESIGN.md) with tokens in [`txn2/www/tokens.json`](https://github.com/txn2/www/blob/master/tokens.json). This file defers to those for everything below. If a value here disagrees with upstream, upstream wins.\n\n| Concern              | Source of truth |\n|----------------------|-----------------|\n| Color palette        | upstream `tokens.json` `color.*` |\n| Typography stack     | upstream `tokens.json` `font.*` |\n| Type scale           | upstream `DESIGN.md` Typography table |\n| Spacing / measure    | upstream `tokens.json` `size.*` |\n| Component contracts  | upstream `DESIGN.md` Components |\n| Voice / copy rules   | upstream `DESIGN.md` Voice and Copy |\n| Accessibility rules  | upstream `DESIGN.md` Do's and Don'ts |\n| Mermaid theme        | upstream `DESIGN.md` `mcp__card--feature` block |\n\nTokens are mirrored as CSS custom properties in `docs/stylesheets/extra.css` `:root`. They are duplicated for runtime use, not as a divergence point. When upstream changes a token, update the value in `extra.css` and ship.\n\n## Adoption level: token alignment\n\nPer the upstream downstream contract, three levels are valid:\n\n1. Reference. Link to upstream, no visual changes.\n2. Token alignment. Keep MkDocs Material, re-skin via `extra.css` against upstream tokens.\n3. Full re-skin. Replace MkDocs Material with custom layouts.\n\nkubefwd runs at **level 2**. The site keeps Material's instant nav, search, sidebar, version selector, code copy, and content extensions. The visual layer is replaced. The homepage is a custom Material template that takes over `block header`, `block container`, and `block footer` for full-bleed treatment.\n\n## File map\n\n| Path | Role |\n|------|------|\n| `mkdocs.yml`                   | Single dark `slate` palette. `font: false` so CSS loads the upstream Google Fonts URL with trimmed axes. |\n| `docs/index.md`                | Stub front matter with `template: home.html`. All homepage HTML lives in the template. |\n| `docs/overrides/main.html`     | Adds the upstream Google Fonts `<link>` plus OG and Twitter meta. Inherited by every page. |\n| `docs/overrides/home.html`     | Custom homepage template. Overrides `block header` (rail), `block tabs` (empty), `block container` (page--home shell with hero, sections, flagship cards, stack, coda), `block footer` (home-footer). |\n| `docs/stylesheets/extra.css`   | All design rules. Two halves: homepage components scoped under `.page--home`, and Material chrome restyle for inner pages via `[data-md-color-scheme=\"slate\"]` variable overrides. |\n\n## Project-specific components\n\nComponents ported from upstream verbatim, with kubefwd content:\n\n- `.rail` (replaces Material `.md-header` on the homepage). Brand links to `./`. Live UTC clock in meta. txn2.com link in meta as `part of <em class=\"serif\">txn2</em> ↗`.\n- `.hero` with three Fraunces rows (kubefwd / kubernetes / port forwards.).\n- `.section`, `.section__index`, `.section__title`.\n- `.flagship__card`. Two cards: `--kubefwd` (TUI mode demo) and a second variant for the API + MCP surfaces. Top accent line animates on hover per upstream spec.\n- `.terminal`, `.terminal__bar`, `.terminal__body` with `.t-prompt`, `.t-ok`, `.t-mute` classes. The only block with shadow.\n- `.stack`, `.stack__row`. Each row links to a real anchor in the docs (architecture/#ip-allocation, advanced-usage/#custom-hosts-file-path, user-guide/#auto-reconnect, user-guide/#interface-overview, api-reference/, mcp-integration/).\n- `.coda` and `.home-footer` (renamed from upstream `.footer` to avoid collision with markdown that uses `class=\"footer\"`; see Learning #5).\n\nComponents from upstream **not used** here, with reason:\n\n- `.mcp__card--feature` and the MCP grid. kubefwd is a single project, not an MCP catalog.\n- The `mcp-data-platform` mermaid hero. Not relevant.\n- The 5-column footer's `sponsors / craig` columns. The kubefwd home-footer has `about / docs / interfaces / code / txn2 / org` columns instead, since this site is project-scoped.\n\nCustom additions specific to kubefwd:\n\n- `home-footer__col--meta` includes a `txn2 / org` panel that backlinks to txn2.com explicitly. Per the org-wide rule that every sister project must clearly link home.\n- All CNCF Landscape mentions on the homepage and in `docs/attributions.md` link to the kubefwd entry on `landscape.cncf.io`. The Landscape listing is a load-bearing credential and earns a real link wherever it appears.\n\n## MkDocs Material learnings\n\nThe upstream is built with Hugo. kubefwd is built with MkDocs Material. The two have different override surfaces, so the same visual outcome requires different mechanics. These are the lessons worth carrying forward when re-skinning the next sister project.\n\n### 1. Override the homepage via a separate template, not via CSS hacks\n\nMkDocs Material's content pipeline wraps every page body in `.md-content__inner` with hard-coded max-widths. Trying to break out with `:has()` selectors or full-bleed hacks inside the markdown body is fragile and fights Material's own layout.\n\nThe pattern that works: create `docs/overrides/home.html` that extends Material's `main.html` and overrides `block container`, `block header`, `block footer`. Set `template: home.html` in `docs/index.md` front matter. Material then renders the homepage with the custom blocks instead of the standard layout. The homepage gets full viewport control without any width-fighting.\n\n```yaml\n# docs/index.md\n---\ntitle: kubefwd\ntemplate: home.html\nhide:\n  - navigation\n  - toc\n  - footer\n---\n```\n\n### 2. Re-skin inner pages via Material variable overrides\n\nMaterial exposes its own design tokens as CSS custom properties on `[data-md-color-scheme=\"slate\"]`. Mapping these to upstream tokens re-skins every inner page automatically without touching their markdown:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-default-bg-color:        var(--ink);\n  --md-default-fg-color:        var(--paper);\n  --md-typeset-a-color:         var(--signal);\n  --md-text-font:               var(--sans);\n  --md-code-font:               var(--mono);\n  /* ...etc */\n}\n```\n\nVerify the body actually carries the attribute (`grep data-md-color-scheme site/getting-started/index.html`). Single-scheme palettes (`palette: scheme: slate`) do emit it. If they ever stop, fall back to `:root`.\n\n### 3. `font: false` to load fonts directly from CSS\n\nMaterial's `font:` directive loads fonts through Google Fonts but without axis control. To get the upstream's exact trimmed payload (Fraunces with `opsz/wght` italic axis, Instrument Sans roman 400-700, JetBrains Mono roman 400-700, **no SOFT axis**), set `font: false` in `mkdocs.yml` and load the upstream Google Fonts URL via a `<link>` in `main.html`'s `extrahead` block. Verify a single `fonts.googleapis.com` request in DevTools.\n\n### 4. Scope every homepage component class under `.page--home`\n\nThe upstream uses `<main class=\"page page--home\">` on its index page and inner pages don't inherit those classes. In MkDocs the same component class names will collide if any markdown happens to use `class=\"terminal\"`, `class=\"footer\"`, `class=\"section\"`, etc. Material's admonitions, tabbed content, and `md_in_html` all generate divs with predictable class names, and contributors will write more.\n\nDiscipline: every homepage component rule must include `.page--home` as an ancestor, OR rename the class with a project-specific prefix (e.g., `home-footer`). The cost of getting this wrong is silent visual breakage on inner pages weeks later when someone uses one of the colliding names.\n\n### 5. Rename `.footer` → `.home-footer`\n\nThe single most common collision. Markdown that includes a literal `<div class=\"footer\">` is plausible and will inherit the homepage's 60px-padded, 5-column-grid footer styling. Rename rather than scope.\n\n### 6. h3 and h4 are technical reference, not display type\n\nInner pages like `api-reference.md` use `### GET /api/health` and `### POST /api/v1/services` as section headings. Rendering these in Fraunces italic display style (the obvious choice for a \"serif headings\" design) makes the API reference unreadable.\n\nThe rule: h1 and h2 stay Fraunces italic for page and section titles. h3 and h4 switch to Instrument Sans bold so technical reference reads as text, not as type. Add a `:has(code)` block that flips any heading containing inline code to JetBrains Mono with signal-orange code text. Add a `@supports not selector(:has(*))` fallback for older browsers.\n\n```css\n.md-typeset h3 {\n  font-family: var(--sans);\n  font-weight: 700;\n  font-size: clamp(18px, 1.6vw, 22px);\n}\n.md-typeset h1:has(code),\n.md-typeset h2:has(code),\n.md-typeset h3:has(code),\n.md-typeset h4:has(code) {\n  font-family: var(--mono);\n  font-style: normal;\n  font-weight: 700;\n}\n```\n\n### 7. Tabbed content nests boxes, fix it\n\nMaterial's `.md-typeset .tabbed-set` defaults to a bordered, backgrounded box. Code blocks inside also default to bordered backgrounded boxes. The result is nested rectangles with cluttered visual hierarchy.\n\nThe fix: strip the `.tabbed-set` background and border. Leave only a bottom underline on `.tabbed-labels`. Let the inner code blocks be the visual statement. Tighten `pre > code` padding to ~14px so single-line install commands don't render as 70px-tall rectangles.\n\n### 8. Mermaid via Material's CSS variables, not via separate init\n\nMkDocs Material includes a Mermaid integration that reads `--md-mermaid-*` CSS variables. Don't bring in `mermaid.esm.mjs` separately like the upstream Hugo site does. Instead, set the variables in the slate scheme block:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-mermaid-node-bg-color:   var(--ink-3);\n  --md-mermaid-node-fg-color:   var(--paper);\n  --md-mermaid-edge-color:      var(--mute);\n  /* ...full list in extra.css */\n}\n```\n\nPlus a `.md-typeset .mermaid` container restyle (dashed border, ink-3 background) for the diagram block itself.\n\n### 9. Guard inline scripts against `navigation.instant`\n\n`navigation.instant` is enabled (`mkdocs.yml`). On every navigation back to the homepage, Material rehydrates the body. Any `setInterval`, `setTimeout`, or event listener registered in an inline `<script>` will register **again**, leaking handles indefinitely.\n\nPattern for the live UTC clock used in the rail and footer:\n\n```html\n<script>\n  (function () {\n    if (window.__kubefwdClock) {\n      window.__kubefwdClock.tick();\n      return;\n    }\n    function tick() { /* ... */ }\n    tick();\n    var handle = setInterval(tick, 30 * 1000);\n    window.__kubefwdClock = { tick: tick, handle: handle };\n  })();\n</script>\n```\n\nThe `tick()` call on re-entry refreshes the displayed time without registering a new interval.\n\n### 10. Drop the light/dark toggle\n\nThe canonical txn2 identity is dark only. Collapse `palette` to a single `scheme: slate`. Remove the `toggle:` blocks. Audit `extra.css` and `index.md` for orphan light-mode references (`hero-logo-light`, `prefers-color-scheme: light`, `kf-green` etc).\n\n### 11. Atmospheric overlays at low z-index\n\n`body::before` (grain) and `body::after` (vignette) are fixed viewport overlays. Place them at `z-index: 1` so they sit above the page background but below the rail (z-50) and skiplink (z-200). Vignette has no blend mode, so a higher z-index would darken interactive chrome.\n\n### 12. What Hugo does that MkDocs cannot match\n\nFor reference when the next sister project chooses its adoption level:\n\n- Hugo can compile tokens.json into CSS custom properties at build time via `resources.Get` + `transform.Unmarshal`. MkDocs has no equivalent. We hand-mirror the tokens in `extra.css` `:root` and update them when upstream changes.\n- Hugo can subscribe to upstream tokens through a small extra.css that imports a generated `:root { --... }` block. MkDocs cannot. Token sync is a manual PR.\n- Hugo's partial system handles header/footer composition naturally. MkDocs uses Material template `{% block %}` overrides, which is similar but constrained to Material's block names (`announce`, `header`, `tabs`, `container`, `content`, `footer`, `scripts`).\n\n## Voice and copy\n\nDefers to upstream. Briefly:\n\n- No em-dashes (U+2014) or en-dashes (U+2013) anywhere, including code comments and template comments. Use commas, periods, colons, parentheses, slashes, hyphens.\n- No AI-tell vocabulary: `seamless`, `leverage`, `comprehensive`, `robust`, `delve`, `unleash`, `elevate`, `embark`, `tapestry`, `not just X but Y`, `as an AI`, `let me X`.\n- Sentence case for body. Lowercase for rail and label text. Title case rare.\n- Section indices: `§ 01 / title` with slash, never an em-dash.\n- Year ranges use a hyphen: `2017-2026`.\n- Verify before commit: `grep -RE \"—|–\" docs/ mkdocs.yml`.\n\n## Updating\n\nWhen the upstream `txn2/www/DESIGN.md` or `tokens.json` changes:\n\n1. Read the upstream diff. Identify which tokens, components, or rules changed.\n2. Update the matching CSS variables in `docs/stylesheets/extra.css` `:root`.\n3. If a component contract changed (padding, border, hover behavior), update the homepage template in `docs/overrides/home.html` and the matching CSS rules.\n4. Update this file's File map / Project-specific components / MkDocs Material learnings sections if a new learning emerges.\n5. Run `mkdocs build --strict` and verify in the browser before committing. Verify the home page hero, flagship cards, terminal, stack, coda, and home-footer. Verify an inner page (`/getting-started/`, `/api-reference/`) still inherits the look.\n\nKeep this file thin. If a section grows past 30 lines, ask whether it belongs upstream instead.\n\n## Downstream contract for sister projects\n\nThis file is canonical only for kubefwd.com. Other sister projects (txeh, mcp-s3, mcp-trino, mcp-datahub, mcp-data-platform) considering the same adoption should:\n\n1. Use this file as a template for their own thin local DESIGN.md.\n2. Reference upstream `txn2/www/DESIGN.md` as the source of truth for tokens, typography, components, voice.\n3. Replace the kubefwd-specific sections (project-specific components, file paths, custom additions) with their own.\n4. Keep the MkDocs Material learnings section. Those apply to every MkDocs Material project.\n5. Update upstream's downstream-contract list when adding a new project.\n","frontmatter":{"version":"alpha","spec":"https://github.com/google-labs-code/design.md","name":"kubefwd-docs","description":"Local design adoption record for the kubefwd.com documentation site. References txn2/www DESIGN.md as the canonical visual identity for tokens, typography, components, copyright voice, and accessibility rules. Records only the decisions and MkDocs Material learnings that the canonical does not cover.","upstream":{"design":"https://github.com/txn2/www/blob/master/DESIGN.md","tokens":"https://github.com/txn2/www/blob/master/tokens.json"},"adoption":"token-alignment","stack":{"generator":"MkDocs","theme":"Material for MkDocs","templates":"docs/overrides/","styles":"docs/stylesheets/extra.css"}},"isInternal":false,"tokens":3689,"sizeBytes":15008},{"name":"architecture.md","path":"docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/docs/architecture.md","title":"docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"# Architecture\n\nHow kubefwd works under the hood.\n\n## Overview\n\nkubefwd establishes port forwards to Kubernetes services by:\n\n1. Discovering services in specified namespaces\n2. Allocating unique local IP addresses (127.x.x.x)\n3. Updating `/etc/hosts` with service hostnames\n4. Creating SPDY connections through the Kubernetes API\n5. Monitoring pod lifecycle for automatic reconnection\n\n```mermaid\nflowchart TB\n    subgraph workstation[\"Your Workstation\"]\n        subgraph kubefwd[\"kubefwd\"]\n            sw[Service Watcher]\n            ip[IP Allocator]\n            hm[Hosts Manager]\n\n            subgraph pfm[\"Port Forward Manager\"]\n                pf1[\"127.1.27.1:8080\"]\n                pf2[\"127.1.27.2:3306\"]\n                pf3[\"127.1.27.3:6379\"]\n            end\n        end\n    end\n\n    subgraph cluster[\"Kubernetes Cluster\"]\n        api[\"api-pod :8080\"]\n        mysql[\"mysql-pod :3306\"]\n        redis[\"redis-pod :6379\"]\n    end\n\n    pf1 -->|SPDY via K8s API| api\n    pf2 -->|SPDY via K8s API| mysql\n    pf3 -->|SPDY via K8s API| redis\n```\n\n## Key Components\n\n### Service Discovery\n\nkubefwd uses Kubernetes **informers** to watch for service events:\n\n- **Add**: New service discovered → start port forward\n- **Update**: Service modified → update port forward if needed\n- **Delete**: Service removed → stop port forward, cleanup hosts\n\nThis event-driven approach means kubefwd reacts in real-time to cluster changes.\n\n### IP Allocation\n\nEach service receives a unique loopback IP address:\n\n```\n127.[1+cluster].[27+namespace].[service_count]\n```\n\n| Component | Base | Range |\n|-----------|------|-------|\n| First octet | 127 | Fixed |\n| Second octet | 1 | 1-255 (cluster index) |\n| Third octet | 27 | 27-255 (namespace index) |\n| Fourth octet | 1 | 1-255 (service count) |\n\n**Why unique IPs?**\n\nUnlike `kubectl port-forward` which uses `localhost:port`, kubefwd assigns each service its own IP. This allows:\n\n- Multiple services on the same port (e.g., several databases on 3306)\n- Realistic service topology matching in-cluster behavior\n- No port conflict management needed\n\n### Hosts File Management\n\nkubefwd modifies `/etc/hosts` to map service names to allocated IPs:\n\n```\n# Before kubefwd\n127.0.0.1       localhost\n\n# After kubefwd starts\n127.0.0.1       localhost\n127.1.27.1      api-service\n127.1.27.2      database\n127.1.27.3      cache\n```\n\n**Safety measures:**\n- Original hosts file backed up to `~/hosts.original`\n- Entries removed on clean shutdown\n- Mutex locking prevents race conditions\n- Stale entry purging available (`-p` flag)\n\n### Port Forwarding\n\nkubefwd creates SPDY connections through the Kubernetes API server:\n\n1. **Pod Selection**: Find pods backing the service\n2. **Connection**: Establish SPDY tunnel via API server\n3. **Local Binding**: Bind to allocated IP and service port(s)\n4. **Data Transfer**: Proxy traffic bidirectionally\n\n```mermaid\nflowchart LR\n    app[Local App] --> ip[\"127.1.27.1:8080\"] --> kf[kubefwd] --> api[K8s API] --> pod[\"Pod:8080\"]\n```\n\n### Pod Lifecycle Monitoring\n\nkubefwd watches pod events to maintain forwarding:\n\n- **Pod deleted**: Stop forward, trigger reconnection\n- **Pod recreated**: Auto-reconnect (if enabled)\n- **Pod crash**: Detect via connection loss, reconnect\n\nThe auto-reconnect feature uses exponential backoff:\n- Initial: 1 second\n- Maximum: 5 minutes\n- Reset on successful connection\n\n## Service Types\n\n### Normal Services (ClusterIP)\n\nFor services with selectors:\n\n1. Query pods matching the selector\n2. Select first available Running pod\n3. Forward to that single pod\n4. Hostname: `service-name`\n\n### Headless Services (ClusterIP: None)\n\nFor services without cluster IP:\n\n1. Query all pods matching the selector\n2. Forward to ALL pods\n3. Hostnames:\n   - `service-name` → first pod\n   - `pod-name.service-name` → each specific pod\n\nThis is essential for StatefulSets and databases requiring pod-specific addressing.\n\n### Services Without Selectors\n\n**Not supported.** kubefwd requires pod selectors to discover backing pods. Services with manually managed Endpoints are skipped.\n\n## TUI Architecture\n\nThe Terminal User Interface uses the [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework:\n\n```mermaid\nflowchart LR\n    subgraph core[\"Core Services\"]\n        eb[Event Bus]\n        ss[State Store]\n        mr[Metrics Registry]\n    end\n\n    subgraph views[\"View Models\"]\n        sm[Services]\n        lm[Logs]\n        dm[Detail]\n    end\n\n    core --> views\n```\n\n### Event Bus\n\nDecoupled communication between components:\n- Service status changes\n- Metrics updates\n- Log messages\n- User actions\n\n### State Store\n\nCentralized, thread-safe state management:\n- Forward status for all services\n- Metrics data (bytes, rates)\n- Filter/sort state\n\n### Metrics Collection\n\nTraffic monitoring with:\n- Byte counters (atomic operations)\n- Rate calculations (rolling window)\n- HTTP request/response detection\n- Sparkline visualization\n\n## Thread Safety\n\nkubefwd handles concurrent operations carefully:\n\n| Resource | Protection |\n|----------|------------|\n| Service registry | RWMutex |\n| IP allocation | Per-namespace mutex |\n| Hosts file | Global mutex with file locking |\n| Metrics | Atomic operations + RWMutex |\n| Event bus | Channel-based with buffer |\n\n## Shutdown Sequence\n\nClean shutdown ensures no leftover state:\n\n1. User signal (q, Ctrl+C) → stop listening\n2. Close service watchers\n3. Stop all port forwards\n4. Remove hosts file entries\n5. Remove network interface aliases\n\nIf shutdown is interrupted, use `-p` to purge stale entries on next run.\n\n## Network Interface Management\n\nkubefwd creates loopback aliases:\n\n**macOS (lo0):**\n```bash\nifconfig lo0 alias 127.1.27.1\n```\n\n**Linux (lo):**\n```bash\nip addr add 127.1.27.1/8 dev lo\n```\n\nThese aliases allow binding to unique IPs while keeping traffic local.\n\n## Security Considerations\n\nkubefwd requires elevated privileges for:\n\n1. **Network interface modification**: Adding IP aliases\n2. **Hosts file modification**: DNS resolution\n3. **Low port binding**: Ports below 1024\n\n**Recommendations:**\n- Run only in development environments\n- Don't run in production workstations with sensitive data\n- Review services before forwarding from production clusters\n- Use label selectors to limit scope\n\n## Performance Characteristics\n\n| Operation | Complexity |\n|-----------|------------|\n| Service discovery | O(services) per namespace |\n| Port forward setup | O(1) per service |\n| Metrics sampling | O(forwards) per second |\n| Hosts file update | O(forwards) per change |\n\nkubefwd is designed for development use with dozens to hundreds of services. For very large clusters, use selectors to limit scope.\n","isInternal":false,"tokens":1630,"sizeBytes":6647},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nkubefwd is a popular command-line utility for bulk Kubernetes port forwarding, featured in \"essential k8s developer tools\" lists. It forwards multiple services from one or more namespaces, adding corresponding entries to `/etc/hosts` for local development.\n\n**Key Differentiator from `kubectl port-forward`**: Each service gets its own unique loopback IP address (127.x.x.x), allowing multiple services to use the same port simultaneously (e.g., multiple databases on port 3306, or multiple web services on port 80). This mirrors how services work in the cluster, enabling truly cluster-like local development.\n\nThe tool automatically monitors service and pod lifecycle events, starting/stopping port forwards as services are created, deleted, or pods are rescheduled.\n\n## Integration and Usage Patterns\n\nkubefwd is commonly integrated into development workflows:\n\n- **With Tilt**: Blog posts document using kubefwd with Tilt for automated local development setups\n- **Development Environment Setup**: Teams use kubefwd to mirror production-like service topologies locally\n- **Microservices Development**: Allows developers to run one service locally while accessing dependencies in the cluster via service names\n- **Database Access**: Popular for forwarding multiple databases (MySQL, PostgreSQL, MongoDB) on their native ports without port conflicts\n\nThe typical workflow: `sudo -E kubefwd svc -n <namespace> --tui` runs in a dedicated terminal while developers work in their IDE, accessing cluster services as if running in-cluster.\n\n## TUI (Terminal User Interface)\n\nkubefwd includes an interactive TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), enabled with `--tui`:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n### TUI Features\n- **Real-time service monitoring**: See all forwarded services with connection status\n- **Traffic metrics**: Bytes in/out with sparkline graphs\n- **Pod log streaming**: View container logs directly in the TUI\n- **HTTP activity detection**: Monitor HTTP requests/responses flowing through forwards\n- **Auto-reconnect**: Enabled by default in TUI mode, with exponential backoff (1s → 5min max)\n- **Keyboard-driven**: Full keyboard navigation (j/k, Enter, Tab, /, ?, q)\n\n### TUI Architecture\n\nThe TUI follows the Model-View-Update (MVU) pattern:\n\n- **Event Bus** (`pkg/fwdtui/events`): Decoupled pub/sub communication between components\n- **State Store** (`pkg/fwdtui/state`): Centralized, thread-safe state management for all forwards\n- **Metrics Registry** (`pkg/fwdtui/metrics`): Traffic counters with atomic operations\n- **Components** (`pkg/fwdtui/components`): UI models for services list, logs, detail view\n\n### TUI Keyboard Shortcuts\n- `j/k` or arrows: Navigate\n- `Enter`: Open detail view\n- `Tab`: Switch panels/tabs\n- `/`: Filter services\n- `r`: Reconnect errored services\n- `b`: Toggle bandwidth columns\n- `?`: Help overlay\n- `q`: Quit\n\n## Git Policy\n\n**All commits require explicit human approval.** Do not run `git commit` unless the user explicitly asks you to commit. Always show the diff or summarize changes and wait for approval first.\n\n## Verification\n\n**\"Testing\" means `make verify`, not `go test ./...`.** Run it before handing work back; it runs every check CI runs, with the same pinned tools, and a change isn't done until it passes.\n\nThe gates (details in CONTRIBUTING.md, \"Quality Gates\"):\n\n- **Formatting**: gofmt, goimports (`github.com/txn2/kubefwd` local prefix), gofumpt over the whole tree. Fix with `make fmt`.\n- **Lint**: every linter in `.golangci.yml` applies to lines changed since the merge base with `origin/master` (`make lint`, CI `--new-from-rev`). Pre-existing issues elsewhere don't fail; anything touched must pass. `make lint-full` shows the backlog. A `//nolint` or `#nosec` needs a reason.\n- **Complexity** (production code): gocyclo 10, gocognit 15, nestif 5, dupl 150, nakedret 30. Split functions rather than suppressing.\n- **Layering**: depguard rules in `.golangci.yml`; `pkg/` never imports `cmd/`, leaf packages import nothing first-party, the forwarding core never imports `fwdapi`/`fwdmcp`.\n- **Coverage**: total ≥ 80% (`make coverage-check`); changed lines ≥ 80% (`make patch-coverage`). Both block, here and in codecov. Root-only or cluster-only code is made testable by injecting the OS call (see `runCommand` and `goos` in `pkg/fwdapi/network.go`), not left uncovered.\n- **Security**: `make security` runs gosec, govulncheck on both modules (gated by `scripts/govulncheck-gate.py` against `.govulncheck-allow.txt`), and osv-scanner (against `osv-scanner.toml`). Upgrade rather than accept; an accepted advisory needs a reason and expires.\n- **SAST**: `make semgrep` (p/golang, whole tree) and `make semgrep-diff` (`.semgrep-diff/` rules, changed lines). CodeQL runs `security-and-quality` in CI.\n- **Mutation**: `make mutate` (gremlins, 60% efficacy), weekly in CI. Too slow for every change.\n- **Toolchain**: Go is pinned by the `toolchain` line in go.mod; CI's setup-go reads the same line. Tool versions are pinned in the Makefile and installed into `.tools/`.\n\n## Build and Development Commands\n\n### Building\n```bash\n# Build the project (uses goreleaser)\ngo build -o kubefwd ./cmd/kubefwd/kubefwd.go\n\n# Build with version information\ngo build -ldflags \"-X main.Version=dev\" -o kubefwd ./cmd/kubefwd/kubefwd.go\n```\n\n### Testing\n```bash\n# Run all tests\ngo test ./...\n\n# Run tests for a specific package\ngo test ./pkg/fwdport\n\n# Run tests with verbose output\ngo test -v ./pkg/fwdport\n```\n\n### Running Locally\n```bash\n# Requires root/sudo for network interface management and /etc/hosts modification\nsudo ./kubefwd svc -n <namespace>\n\n# Use -E flag to preserve environment (especially KUBECONFIG)\nsudo -E ./kubefwd svc -n <namespace>\n\n# With interactive TUI (recommended for development)\nsudo -E ./kubefwd svc -n <namespace> --tui\n```\n\n### Dependencies\n```bash\n# Download dependencies\ngo mod download\n\n# Update dependencies\ngo mod tidy\n```\n\n### Debugging and Development\n\n```bash\n# Enable verbose logging\nsudo -E ./kubefwd svc -n <namespace> -v\n\n# Test with a single service using field selector\nsudo -E ./kubefwd svc -n <namespace> -f metadata.name=<service-name>\n\n# Test with label selector\nsudo -E ./kubefwd svc -n <namespace> -l app=myapp\n\n# Use IP reservation config for reproducible testing\nsudo -E ./kubefwd svc -n <namespace> -z example.fwdconf.yml\n```\n\nThe verbose flag (`-v`) enables debug-level logging (logrus.DebugLevel), which shows:\n- Service registry operations\n- Pod sync events\n- IP allocation details\n- Port forwarding lifecycle events\n\n### Demo Environment\n\nA comprehensive demo manifest is available for testing:\n\n```bash\n# Deploy 60 services across 2 namespaces\nkubectl apply -f test/manifests/demo-microservices.yaml\n\n# Forward all demo services with TUI\nsudo -E ./kubefwd svc -n kft1,kft2 --tui\n\n# Cleanup\nkubectl delete -f test/manifests/demo-microservices.yaml\n```\n\n## Architecture\n\n### Core Components Flow\n\n1. **Entry Point** (`cmd/kubefwd/kubefwd.go`): CLI entry, delegates to services command\n2. **Services Command** (`cmd/kubefwd/services/services.go`): Main orchestration logic\n   - Validates cluster connectivity and RBAC permissions\n   - Creates Kubernetes informers to watch Service events (Add/Delete/Update)\n   - Spawns namespace watchers for each namespace×context combination\n3. **Service Registry** (`pkg/fwdsvcregistry`): Central registry of all forwarded services\n   - Thread-safe map of active ServiceFWD instances\n   - Handles lifecycle (add, remove, shutdown all)\n4. **Service Forwarding** (`pkg/fwdservice`): Per-service forwarding logic\n   - Queries pods backing each service\n   - Manages pod selection (single pod for normal services, all pods for headless)\n   - Debounces pod sync operations to avoid hammering k8s API\n   - Maintains map of active port forwards per pod\n5. **Port Forwarding** (`pkg/fwdport`): Individual pod port forwarding\n   - Creates SPDY connection to k8s API server\n   - Manages port forward lifecycle with watch for pod deletion\n   - Updates `/etc/hosts` file with service hostnames\n6. **Network/IP Management** (`pkg/fwdnet`, `pkg/fwdIp`): Loopback interface management\n   - Allocates unique 127.x.x.x IPs for each service\n   - Manages IP aliases on loopback interface (macOS: lo0, Linux: lo)\n   - Supports IP reservation via config file or CLI flags\n\n### Key Architectural Patterns\n\n**Event-Driven Architecture**: Uses Kubernetes informers to react to service/pod lifecycle events in real-time.\n\n**Headless vs Normal Services**:\n- Normal services forward the first available pod using the service name\n- Headless services (ClusterIP: None) forward all pods, with first pod as service name and rest as pod-name.service-name\n\n**Debouncing**: Uses 5-second debouncer for pod sync operations to handle rapid pod changes (e.g., rolling deployments) without excessive k8s API calls.\n\n**Thread Safety**: Extensive use of mutexes for:\n- Per-namespace IP allocation (`NamespaceIPLock`)\n- Service registry access\n- Hosts file modifications\n\n**Shutdown Orchestration**: Clean shutdown cascade:\n1. User signal → stopListenCh\n2. Namespace watchers stop\n3. Service registry shutdown\n4. Individual pod port forwards stop\n5. Hosts file cleanup and network alias removal\n\n### Package Responsibilities\n\n- `fwdservice`: Service-level forwarding orchestration and pod management\n- `fwdport`: Individual pod port forwarding via k8s API\n- `fwdsvcregistry`: Global service registry and lifecycle management\n- `fwdnet`: Network interface management (IP aliasing)\n- `fwdIp`: IP allocation logic and reservation handling\n- `fwdhost`: Hosts file backup management\n- `fwdcfg`: Kubernetes client configuration\n- `fwdpub`: Publisher interface for output\n- `fwdtui`: Terminal User Interface (Bubble Tea)\n  - `fwdtui/components`: UI view models (services list, logs, detail, help, status bar)\n  - `fwdtui/events`: Event bus with panic recovery for decoupled pub/sub\n  - `fwdtui/state`: Thread-safe state store with RWMutex protection\n  - `fwdtui/metrics`: Traffic metrics with atomic counters and rate calculation\n  - `fwdtui/portforward`: Port forward wrapper that emits metrics events\n- `utils`: Root permission checks (OS-specific)\n\n## Important Implementation Details\n\n### Root Permissions and Security\n\nkubefwd requires superuser privileges for:\n- Adding IP aliases to loopback interface\n- Binding to low-numbered ports\n- Modifying `/etc/hosts`\n\nAlways run with `sudo -E` to preserve environment variables (KUBECONFIG).\n\n**Security Considerations**: kubefwd is considered a \"powerful but potentially dangerous tool\" because it:\n- Modifies system-level network configuration\n- Changes `/etc/hosts` which affects DNS resolution system-wide\n- Requires root access which can impact system stability if misused\n- Opens network connections to cluster services\n\nThe tool backs up the original hosts file to `~/hosts.original` before making modifications, but improper shutdown can leave the system in an inconsistent state.\n\n### Hostname Generation\nHostnames follow pattern based on cluster and namespace indices:\n- Namespace 0, Cluster 0: `service-name`\n- Namespace >0: `service-name.namespace`\n- Cluster >0: `service-name.context` or `service-name.namespace.context`\n\nFor headless services, pods get: `pod-name.service-name[.namespace][.context]`\n\n### IP Allocation\nBase IP is 127.1.x.x with incremental allocation. Can be customized via:\n- `--fwd-conf` YAML config file (see `example.fwdconf.yml`)\n- `--reserve` CLI flag for individual reservations\n\n### Port Mapping\nSupports port remapping with `-m` flag (e.g., `-m 80:8080` maps service port 80 to local 8080).\n\n### UDP Limitation\nUDP port forwarding is not supported (Kubernetes API limitation: kubernetes/kubernetes#47862).\n\n## Code Organization\n\n```\ncmd/kubefwd/           # CLI entry point\n  kubefwd.go          # Main entry, root command\n  services/\n    services.go       # Services subcommand, namespace watchers\npkg/\n  fwdservice/         # Service forwarding logic\n  fwdport/            # Pod port forwarding\n  fwdsvcregistry/     # Service registry\n  fwdnet/             # Network interface management\n  fwdIp/              # IP allocation\n  fwdhost/            # Hosts file operations\n  fwdcfg/             # K8s config\n  fwdpub/             # Publisher\n  fwdtui/             # Terminal User Interface\n    components/       # UI models (services, logs, detail, help)\n    events/           # Event bus for decoupled communication\n    state/            # Centralized state store\n    metrics/          # Traffic metrics with atomic counters\n    portforward/      # Port forward wrapper with metrics\n  utils/              # Utilities (root check)\ntest/\n  integration/        # Integration tests (require KIND cluster)\n  manifests/          # Test Kubernetes manifests\n  scripts/            # Test setup/teardown scripts\n```\n\n## Contribution Policy\n\n**Public Contributions**: The project welcomes pull requests from the community for:\n- Bug fixes\n- Tests\n- Documentation\n- Stability and compatibility enhancements\n\n**Feature Development**: New features are developed by select contributors only. Public feature PRs are discouraged due to past experience with contributions that introduced drastic codebase changes, were difficult to review and test, and added significant technical debt. This policy is documented in the README.\n\n**Internal Development**: Maintainers and trusted contributors are welcome to develop new features. If you're working on this codebase with direct access, feature development is encouraged.\n\n## Release Process\n\nUses GoReleaser (`.goreleaser.yml`):\n- Builds for Linux, macOS, Windows (multiple architectures)\n- Creates Docker images (Alpine and Ubuntu variants)\n- Publishes to GitHub releases\n- Updates Homebrew tap (txn2/homebrew-tap)\n- Generates RPM, DEB, APK packages\n\nThe version is set via ldflags during build: `-ldflags \"-X main.Version={{.Version}}\"`\n\n## Testing\n\n### Unit Tests\n\n`make verify` is the full check (see Verification above). For quicker loops:\n\n```bash\n# Run all unit tests\ngo test ./...\n\n# Run with coverage\ngo test -cover ./...\n\n# Run specific package tests\ngo test -v ./pkg/fwdtui/events/...     # Event bus tests (100% coverage)\ngo test -v ./pkg/fwdtui/components/... # UI component tests\ngo test -v ./pkg/fwdtui/state/...      # State store tests\ngo test -v ./pkg/fwdport/...           # Port forwarding tests\n```\n\n### Integration Tests\n\nLocated in `test/integration/`, these require a KIND cluster:\n\n```bash\n# Setup KIND cluster\n./test/scripts/setup-kind.sh\n./test/scripts/deploy-test-services.sh test/manifests\n\n# Run integration tests (requires sudo)\nsudo -E go test -tags=integration -v ./test/integration/...\n\n# Teardown\n./test/scripts/teardown-kind.sh\n```\n\nIntegration tests cover: basic forwarding, headless services, auto-reconnect, multi-namespace, port mapping, and cleanup verification.\n\n### Areas for Additional Testing\n- Hosts file race condition scenarios (Issue #74)\n- Cleanup/restore logic for error conditions (Issue #5)\n- Pod state filtering for evicted/completed pods (Issues #34, #114)\n\n## Areas for Improvement\n\nBased on known issues, these areas would benefit from development:\n\n### Auto-Reconnect Enhancement\nAuto-reconnect is now implemented (`-a` flag, enabled by default in TUI mode) with exponential backoff. However, edge cases may still exist:\n- Very rapid pod cycling during rolling deployments\n- Network partitions vs pod deletion detection\n- Reconnection priority when multiple pods are available\n\n### Hosts File Synchronization (Issues #74, #79)\nThe `HostFileWithLock` mutex in `pkg/fwdport` may not be sufficient for all race conditions. Consider:\n- Batching hosts file updates\n- Implementing retry logic for failed updates\n- Adding verification that all services are actually written\n\n### Graceful Shutdown (Issue #5)\nEnhance the shutdown cascade to guarantee hosts file restoration even on signal interruption. Consider using `defer` more extensively or implementing a signal handler with guaranteed cleanup.\n\n### Pod State Filtering (Issues #34, #114)\nThe pod filtering in `fwdservice.GetPodsForService()` should be more defensive:\n- Handle additional pod phases gracefully\n- Add better error handling for watch events with non-pod objects\n- Consider ignoring evicted pods earlier in the pipeline\n\n### Services Without Selectors (Issue #35)\nCould potentially support endpoint-based services by querying Endpoints resources directly instead of relying on pod selectors.\n\n## Known Limitations and Active Issues\n\nBased on community feedback and GitHub issues, developers should be aware of:\n\n### Architectural Limitations\n\n**Services Without Selectors** (Issue #35): kubefwd does not support ClusterIP services without selectors (services backed by manually created Endpoints). The code assumes services have pod selectors and will skip services with empty selector strings.\n\n**Auto-Reconnect Available** (Issue #21 resolved): Auto-reconnect is now implemented with the `-a` flag (enabled by default in TUI mode). When pods restart, kubefwd automatically re-establishes port forwards with exponential backoff (1s → 5min max).\n\n**UDP Protocol Not Supported**: Kubernetes port-forwarding API limitation (kubernetes/kubernetes#47862).\n\n### Race Conditions and Edge Cases\n\n**Hosts File Race Condition** (Issue #74): When forwarding multiple services simultaneously, especially on Windows with Docker Desktop, race conditions can occur during hosts file updates, leading to DNS resolution errors.\n\n**Hosts File Not Fully Restored** (Issue #5): On certain error conditions or unclean shutdowns (Ctrl-C timing), the original `/etc/hosts` may not be fully restored. Always check `~/hosts.original` backup.\n\n**Incomplete Hosts File Updates** (Issue #79): Some services may be assigned IPs and be accessible but not appear in the hosts file. This appears related to timing in the hosts file update logic.\n\n### Pod State Handling\n\n**Evicted/Completed Pods** (Issues #34, #114): Starting from v1.11.0, interface conversion errors occur with evicted pods or completed jobs. The code in `pkg/fwdservice` filters for `PodPending` and `PodRunning` states, but watch events for other states can cause errors.\n\n**Pod Status Assumptions**: The code assumes pods are either Pending, Running, Succeeded, Failed, or Unknown. Edge cases with custom pod conditions may not be handled gracefully.\n\n## Common Issues and Troubleshooting\n\n**Permission Errors**: Always use `sudo -E` to preserve KUBECONFIG.\n\n**IP/Port Conflicts**: Use IP reservations (`-r` or `-z`) to avoid conflicts.\n\n**Stale /etc/hosts Entries**: Original hosts file backed up to `~/hosts.original`. Check this file if DNS resolution is broken after kubefwd exits.\n\n**Pod Watch Failures**: Check RBAC permissions (list/get/watch pods, get services).\n\n**Connection Refused (localhost:8080)**: This usually means kubectl is not properly configured or KUBECONFIG was not preserved (missing `-E` flag with sudo).\n","isInternal":false,"tokens":4494,"sizeBytes":19114},{"name":"smithery.yaml","path":"smithery.yaml","rawUrl":"https://raw.githubusercontent.com/txn2/kubefwd/HEAD/smithery.yaml","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"yaml","content":"# Smithery.ai MCP Server Configuration\n# https://smithery.ai/docs\n\nstartCommand:\n  type: stdio\n  configSchema:\n    type: object\n    properties:\n      apiUrl:\n        type: string\n        description: \"URL of the kubefwd REST API\"\n        default: \"http://kubefwd.internal/api\"\n    required: []\n  commandFunction: |\n    (config) => ({\n      command: 'kubefwd',\n      args: ['mcp', ...(config.apiUrl ? ['--api-url', config.apiUrl] : [])],\n      env: {}\n    })\n","isInternal":false,"tokens":124,"sizeBytes":458}],"systemPromptSnippet":"<yakaai_skills repo=\"txn2/kubefwd\">\n<!-- File: docs/llms-full.txt (Tokens: ~2759 | Category: root-instruction) -->\n# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n---\n\n# Getting Started\n\nThis guide covers installation and your first steps with kubefwd. By the end, you'll have cluster services accessible locally by name.\n\n## Prerequisites\n\n- **kubectl configured** with access to a Kubernetes cluster\n- **Root/sudo access** (required for `/etc/hosts` and network interface modifications)\n\nkubefwd reads your kubeconfig (`~/.kube/config` or `KUBECONFIG` environment variable) and connects directly to the Kubernetes API.\n\n## Installation\n\n### macOS\n\nUsing Homebrew:\n\n```bash\nbrew install txn2/tap/kubefwd\n```\n\n### Windows\n\nUsing Scoop:\n\n```powershell\nscoop install kubefwd\n```\n\nRun as Administrator for hosts file access.\n\n### Linux (Debian/Ubuntu)\n\nDownload the `.deb` package from GitHub Releases:\n\n```bash\nsudo dpkg -i kubefwd_*_amd64.deb\n```\n\n### Linux (RHEL/Fedora)\n\nDownload the `.rpm` package from GitHub Releases:\n\n```bash\nsudo rpm -i kubefwd_*_amd64.rpm\n```\n\n### Docker\n\n```bash\ndocker run -it --rm --privileged \\\n    -v \"$HOME/.kube:/root/.kube:ro\" \\\n    txn2/kubefwd --tui\n```\n\nVerify installation:\n\n```bash\nkubefwd version\n```\n\n## Operating Modes\n\n### Idle Mode (Recommended)\n\nStart without pre-specified services and add them interactively:\n\n```bash\nsudo -E kubefwd --tui\n```\n\nIn Idle Mode:\n- REST API is enabled by default\n- Auto-reconnect is enabled by default\n- Use TUI to browse namespaces, select services, forward them\n- Or use API to add services dynamically\n\n### Classic Mode\n\nSpecify namespaces upfront. All services forwarded immediately:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n## Your First Forward\n\n1. Start kubefwd in Idle Mode:\n   ```bash\n   sudo -E kubefwd --tui\n   ```\n\n2. Browse namespaces: Press `f` to open the service browser, then select a namespace.\n\n3. Forward services: Select individual services or press `a` to forward all.\n\n4. Use your services:\n   ```bash\n   curl http://my-api:8080/health\n   psql -h postgres -U admin -d mydb\n   redis-cli -h redis ping\n   ```\n\n5. Quit: Press `q` to exit. kubefwd cleans up automatically.\n\n## What Happens Under the Hood\n\nWhen kubefwd forwards a service:\n\n1. **IP Allocation**: Each service gets a unique loopback IP (e.g., `127.1.27.1`)\n2. **Hosts File Update**: Service names added to `/etc/hosts`\n3. **Port Forwarding**: Creates port forwards to pods backing each service\n4. **Ready to Use**: Applications connect using service names\n\n### Cleanup\n\nWhen kubefwd exits:\n- `/etc/hosts` entries are removed\n- Network interface aliases are cleaned up\n- All port forward connections are closed\n\nOriginal hosts file backed up to `~/hosts.original`.\n\n## Why sudo -E?\n\nkubefwd requires root privileges for:\n- Modifying `/etc/hosts`\n- Creating loopback IP aliases\n- Binding to ports below 1024\n\nThe `-E` flag preserves environment variables, especially `KUBECONFIG`:\n\n```bash\n# Correct - preserves KUBECONFIG\nsudo -E kubefwd --tui\n\n# Wrong - may fail to find cluster config\nsudo kubefwd --tui\n```\n\n## Enabling the REST API\n\n**Idle Mode** (API enabled by default):\n```bash\nsudo -E kubefwd\nsudo -E kubefwd --tui\n```\n\n**Classic Mode** (add `--api` flag):\n```bash\nsudo -E kubefwd svc -n default --api\n```\n\nAPI available at:\n- `http://kubefwd.internal/api` - REST endpoints\n- `http://kubefwd.internal/docs` - Interactive API documentation\n\n---\n\n# User Guide\n\nThe Terminal User Interface (TUI) transforms kubefwd into an interactive development companion.\n\n## Interface Overview\n\n### Main View\n\n| Panel | Description |\n|-------|-------------|\n| **Services** | All forwarded services with status, namespace, local address, traffic |\n| **Logs** | Real-time kubefwd activity, connection events, errors |\n| **Status Bar** | Service counts, current filter, keyboard hints |\n\n### Service Status Indicators\n\n| Indicator | Meaning |\n|-----------|---------|\n| Green dot | Active and forwarding |\n| Yellow dot | Connecting or reconnecting |\n| Red dot | Error state |\n\n## Keyboard Shortcuts\n\n### Global\n\n| Key | Action |\n|-----|--------|\n| `q` | Quit kubefwd |\n| `?` | Toggle help overlay |\n| `f` | Open namespace/service browser |\n| `x` | Switch Kubernetes context |\n| `/` | Filter services |\n| `Esc` | Clear filter / Close modal |\n\n### Navigation\n\n| Key | Action |\n|-----|--------|\n| `j` / `↓` | Move down |\n| `k` / `↑` | Move up |\n| `g` / `Home` | Go to first item |\n| `G` / `End` | Go to last item |\n| `Tab` | Switch focus (services ↔ logs) |\n\n### Service Actions\n\n| Key | Action |\n|-----|--------|\n| `Enter` | Open detail view for selected service |\n| `d` | Remove forward for selected service |\n| `r` | Reconnect all errored services |\n| `R` | Force reconnect selected service |\n\n### Detail View\n\n| Key | Action |\n|-----|--------|\n| `1` - `9` | Copy connection string #N to clipboard |\n| `y` | Copy first connection string |\n| `Tab` | Next tab |\n| `Esc` / `q` | Close detail view |\n\n## Auto-Reconnect\n\nTUI enables auto-reconnect by default with exponential backoff:\n\n```\n1s → 2s → 4s → 8s → 16s → 32s → 64s → 128s → 256s → 300s (max)\n```\n\nPress `r` to force immediate reconnection of all errored services.\n\n---\n\n# Configuration\n\nComplete reference for kubefwd command line flags.\n\n## Essential Flags\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--namespace` | `-n` | Namespace(s) to forward services from |\n| `--tui` | | Enable interactive terminal user interface |\n| `--selector` | `-l` | Label selector to filter services |\n| `--field-selector` | `-f` | Field selector to filter services |\n| `--all-namespaces` | `-A` | Forward services from all namespaces |\n\n## TUI and Behavior Flags\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--tui` | | false | Enable interactive TUI mode |\n| `--auto-reconnect` | `-a` | true (TUI) | Automatically reconnect lost port forwards |\n| `--verbose` | `-v` | false | Enable debug logging |\n\n## Network Configuration\n\n| Flag | Short | Description |\n|------|-------|-------------|\n| `--mapping` | `-m` | Port mapping (e.g., `-m 80:8080`) |\n| `--reserve` | `-r` | Reserve specific IP for service |\n| `--fwd-conf` | `-z` | Path to IP reservation config file |\n| `--domain` | `-d` | Append domain suffix to hostnames |\n\n## Examples\n\n```bash\n# Forward all services in a namespace with TUI\nsudo -E kubefwd svc -n default --tui\n\n# Multiple namespaces\nsudo -E kubefwd svc -n frontend,backend,data --tui\n\n# Filter by label\nsudo -E kubefwd svc -n default -l app=api --tui\n\n# Port mapping (80 → 8080)\nsudo -E kubefwd svc -n default -m 80:8080 --tui\n\n# IP reservation\nsudo -E kubefwd svc -n default -r my-service.default:127.3.3.1 --tui\n```\n\n---\n\n# REST API\n\nkubefwd's REST API enables programmatic control over port forwarding.\n\n## Quick Start\n\n```bash\n# Idle mode - API enabled by default\nsudo -E kubefwd\n\n# Test the API\ncurl http://kubefwd.internal/api/health\n```\n\nBase URL: `http://kubefwd.internal/api`\n\n## Key Endpoints\n\n### Health & Info\n\n- `GET /api/health` - Health check\n- `GET /api/info` - Server information\n\n### Services\n\n- `GET /api/v1/services` - List forwarded services\n- `GET /api/v1/services/:key` - Get specific service\n- `POST /api/v1/services` - Add service to forward\n- `DELETE /api/v1/services/:key` - Stop forwarding\n- `POST /api/v1/services/:key/reconnect` - Reconnect service\n\n### Namespaces\n\n- `GET /api/v1/namespaces` - List namespace watchers\n- `POST /api/v1/namespaces` - Add namespace (forward all services)\n- `DELETE /api/v1/namespaces/:key` - Remove namespace\n\n### Kubernetes Discovery\n\n- `GET /api/v1/kubernetes/contexts` - List kubeconfig contexts\n- `GET /api/v1/kubernetes/namespaces` - List namespaces\n- `GET /api/v1/kubernetes/services` - List services in namespace\n- `GET /api/v1/kubernetes/pods/:namespace` - List pods\n- `GET /api/v1/kubernetes/pods/:namespace/:pod/logs` - Get pod logs\n\n### Metrics & Diagnostics\n\n- `GET /api/v1/metrics` - Summary metrics\n- `GET /api/v1/diagnostics` - Diagnostics summary\n- `GET /api/v1/diagnostics/errors` - Current errors\n\n### Events (SSE)\n\n- `GET /api/v1/events` - Real-time event stream\n\n---\n\n# MCP Integration\n\n## What is MCP?\n\nThe Model Context Protocol (MCP) lets AI assistants connect to external tools. kubefwd's MCP integration gives AI assistants full access to Kubernetes port forwarding.\n\n## Platform Support\n\n| Platform | Support |\n|----------|---------|\n| Claude Code | Full |\n| Claude Desktop | Full |\n| Cursor | Full |\n| Windsurf | Full |\n| VS Code Copilot | Full |\n| Zed | Full |\n| JetBrains IDEs | Full |\n\n## Setup\n\n### 1. Start kubefwd\n\n```bash\nsudo -E kubefwd --tui\n```\n\n### 2. Configure AI Client\n\n**Claude Code:**\n```bash\nclaude mcp add --transport stdio kubefwd -- kubefwd mcp\n```\n\n**Cursor/Windsurf/VS Code:**\nAdd to MCP config:\n```json\n{\n  \"mcpServers\": {\n    \"kubefwd\": {\n      \"command\": \"kubefwd\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n## What Your AI Can Do\n\n### Service Forwarding\n- Forward entire namespaces\n- Forward individual services\n- Remove forwards\n- Multi-context support\n\n### Discovery & Connection\n- List Kubernetes contexts\n- List namespaces and services\n- Get connection info (IPs, hostnames, env vars)\n- Find services by name/port\n\n### Pod Debugging\n- List pods with status\n- Get pod details and logs\n- View Kubernetes events\n- Check service endpoints\n\n### Monitoring & Troubleshooting\n- Quick status checks\n- Traffic metrics\n- Error diagnosis\n- Reconnect services\n\n## Example Conversations\n\n**You:** \"I need to connect to PostgreSQL in kft1\"\n**AI:** \"Connected. Use: `psql -h postgres -U admin -d mydb`\"\n\n**You:** \"Set up my environment for the checkout service\"\n**AI:** \"Ready. Services available: cart-service:8080, payment-service:443, user-db:5432\"\n\n**You:** \"My API calls to auth-service are failing\"\n**AI:** \"The auth-service pod restarted. I've reconnected it. Try again.\"\n\n<!-- File: docs/llms.txt (Tokens: ~455 | Category: root-instruction) -->\n# kubefwd\n\n> Kubernetes bulk port forwarding for local development. Forward services from any namespace to localhost with automatic /etc/hosts entries and unique IPs per service.\n\nkubefwd enables developers to work locally while accessing services running in Kubernetes. Each service gets its own unique loopback IP (127.x.x.x), eliminating port conflicts. Access cluster services by name—exactly as in-cluster.\n\n## Documentation\n\n- [Getting Started](https://kubefwd.com/getting-started/): Installation, prerequisites, and first forward\n- [User Guide](https://kubefwd.com/user-guide/): Interactive TUI interface and keyboard shortcuts\n- [Configuration](https://kubefwd.com/configuration/): CLI flags, IP reservations, and port mapping\n- [REST API](https://kubefwd.com/api-reference/): Programmatic control via 40+ HTTP endpoints\n- [MCP Integration](https://kubefwd.com/mcp-integration/): AI assistant integration (Claude, Cursor, VS Code)\n\n## Key Features\n\n- **Unique IP per service**: Multiple databases on port 3306 work without conflicts\n- **Auto-reconnect**: Reconnects automatically when pods restart\n- **Interactive TUI**: Browse namespaces, monitor traffic, stream logs\n- **Service name resolution**: Updates /etc/hosts so apps connect by service name\n- **REST API**: Add/remove services dynamically\n- **MCP support**: Natural language control via AI assistants\n\n## Quick Start\n\n```bash\n# Install (macOS)\nbrew install txn2/tap/kubefwd\n\n# Forward services with TUI\nsudo -E kubefwd svc -n my-namespace --tui\n```\n\n## Optional\n\n- [Troubleshooting](https://kubefwd.com/troubleshooting/): Common issues and solutions\n- [Architecture](https://kubefwd.com/architecture/): Technical implementation details\n- [Comparison](https://kubefwd.com/comparison/): vs kubectl port-forward, Telepresence, mirrord\n- [GitHub Repository](https://github.com/txn2/kubefwd): Source code, issues, releases\n\n<!-- File: DESIGN.md (Tokens: ~3689 | Category: project-spec) -->\n---\nversion: alpha\nspec: https://github.com/google-labs-code/design.md\nname: kubefwd-docs\ndescription: Local design adoption record for the kubefwd.com documentation site. References txn2/www DESIGN.md as the canonical visual identity for tokens, typography, components, copyright voice, and accessibility rules. Records only the decisions and MkDocs Material learnings that the canonical does not cover.\nupstream:\n  design: https://github.com/txn2/www/blob/master/DESIGN.md\n  tokens: https://github.com/txn2/www/blob/master/tokens.json\nadoption: token-alignment\nstack:\n  generator: MkDocs\n  theme: Material for MkDocs\n  templates: docs/overrides/\n  styles: docs/stylesheets/extra.css\n---\n\n## What is canonical\n\nThe canonical visual identity for txn2 lives in [`txn2/www/DESIGN.md`](https://github.com/txn2/www/blob/master/DESIGN.md) with tokens in [`txn2/www/tokens.json`](https://github.com/txn2/www/blob/master/tokens.json). This file defers to those for everything below. If a value here disagrees with upstream, upstream wins.\n\n| Concern              | Source of truth |\n|----------------------|-----------------|\n| Color palette        | upstream `tokens.json` `color.*` |\n| Typography stack     | upstream `tokens.json` `font.*` |\n| Type scale           | upstream `DESIGN.md` Typography table |\n| Spacing / measure    | upstream `tokens.json` `size.*` |\n| Component contracts  | upstream `DESIGN.md` Components |\n| Voice / copy rules   | upstream `DESIGN.md` Voice and Copy |\n| Accessibility rules  | upstream `DESIGN.md` Do's and Don'ts |\n| Mermaid theme        | upstream `DESIGN.md` `mcp__card--feature` block |\n\nTokens are mirrored as CSS custom properties in `docs/stylesheets/extra.css` `:root`. They are duplicated for runtime use, not as a divergence point. When upstream changes a token, update the value in `extra.css` and ship.\n\n## Adoption level: token alignment\n\nPer the upstream downstream contract, three levels are valid:\n\n1. Reference. Link to upstream, no visual changes.\n2. Token alignment. Keep MkDocs Material, re-skin via `extra.css` against upstream tokens.\n3. Full re-skin. Replace MkDocs Material with custom layouts.\n\nkubefwd runs at **level 2**. The site keeps Material's instant nav, search, sidebar, version selector, code copy, and content extensions. The visual layer is replaced. The homepage is a custom Material template that takes over `block header`, `block container`, and `block footer` for full-bleed treatment.\n\n## File map\n\n| Path | Role |\n|------|------|\n| `mkdocs.yml`                   | Single dark `slate` palette. `font: false` so CSS loads the upstream Google Fonts URL with trimmed axes. |\n| `docs/index.md`                | Stub front matter with `template: home.html`. All homepage HTML lives in the template. |\n| `docs/overrides/main.html`     | Adds the upstream Google Fonts `<link>` plus OG and Twitter meta. Inherited by every page. |\n| `docs/overrides/home.html`     | Custom homepage template. Overrides `block header` (rail), `block tabs` (empty), `block container` (page--home shell with hero, sections, flagship cards, stack, coda), `block footer` (home-footer). |\n| `docs/stylesheets/extra.css`   | All design rules. Two halves: homepage components scoped under `.page--home`, and Material chrome restyle for inner pages via `[data-md-color-scheme=\"slate\"]` variable overrides. |\n\n## Project-specific components\n\nComponents ported from upstream verbatim, with kubefwd content:\n\n- `.rail` (replaces Material `.md-header` on the homepage). Brand links to `./`. Live UTC clock in meta. txn2.com link in meta as `part of <em class=\"serif\">txn2</em> ↗`.\n- `.hero` with three Fraunces rows (kubefwd / kubernetes / port forwards.).\n- `.section`, `.section__index`, `.section__title`.\n- `.flagship__card`. Two cards: `--kubefwd` (TUI mode demo) and a second variant for the API + MCP surfaces. Top accent line animates on hover per upstream spec.\n- `.terminal`, `.terminal__bar`, `.terminal__body` with `.t-prompt`, `.t-ok`, `.t-mute` classes. The only block with shadow.\n- `.stack`, `.stack__row`. Each row links to a real anchor in the docs (architecture/#ip-allocation, advanced-usage/#custom-hosts-file-path, user-guide/#auto-reconnect, user-guide/#interface-overview, api-reference/, mcp-integration/).\n- `.coda` and `.home-footer` (renamed from upstream `.footer` to avoid collision with markdown that uses `class=\"footer\"`; see Learning #5).\n\nComponents from upstream **not used** here, with reason:\n\n- `.mcp__card--feature` and the MCP grid. kubefwd is a single project, not an MCP catalog.\n- The `mcp-data-platform` mermaid hero. Not relevant.\n- The 5-column footer's `sponsors / craig` columns. The kubefwd home-footer has `about / docs / interfaces / code / txn2 / org` columns instead, since this site is project-scoped.\n\nCustom additions specific to kubefwd:\n\n- `home-footer__col--meta` includes a `txn2 / org` panel that backlinks to txn2.com explicitly. Per the org-wide rule that every sister project must clearly link home.\n- All CNCF Landscape mentions on the homepage and in `docs/attributions.md` link to the kubefwd entry on `landscape.cncf.io`. The Landscape listing is a load-bearing credential and earns a real link wherever it appears.\n\n## MkDocs Material learnings\n\nThe upstream is built with Hugo. kubefwd is built with MkDocs Material. The two have different override surfaces, so the same visual outcome requires different mechanics. These are the lessons worth carrying forward when re-skinning the next sister project.\n\n### 1. Override the homepage via a separate template, not via CSS hacks\n\nMkDocs Material's content pipeline wraps every page body in `.md-content__inner` with hard-coded max-widths. Trying to break out with `:has()` selectors or full-bleed hacks inside the markdown body is fragile and fights Material's own layout.\n\nThe pattern that works: create `docs/overrides/home.html` that extends Material's `main.html` and overrides `block container`, `block header`, `block footer`. Set `template: home.html` in `docs/index.md` front matter. Material then renders the homepage with the custom blocks instead of the standard layout. The homepage gets full viewport control without any width-fighting.\n\n```yaml\n# docs/index.md\n---\ntitle: kubefwd\ntemplate: home.html\nhide:\n  - navigation\n  - toc\n  - footer\n---\n```\n\n### 2. Re-skin inner pages via Material variable overrides\n\nMaterial exposes its own design tokens as CSS custom properties on `[data-md-color-scheme=\"slate\"]`. Mapping these to upstream tokens re-skins every inner page automatically without touching their markdown:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-default-bg-color:        var(--ink);\n  --md-default-fg-color:        var(--paper);\n  --md-typeset-a-color:         var(--signal);\n  --md-text-font:               var(--sans);\n  --md-code-font:               var(--mono);\n  /* ...etc */\n}\n```\n\nVerify the body actually carries the attribute (`grep data-md-color-scheme site/getting-started/index.html`). Single-scheme palettes (`palette: scheme: slate`) do emit it. If they ever stop, fall back to `:root`.\n\n### 3. `font: false` to load fonts directly from CSS\n\nMaterial's `font:` directive loads fonts through Google Fonts but without axis control. To get the upstream's exact trimmed payload (Fraunces with `opsz/wght` italic axis, Instrument Sans roman 400-700, JetBrains Mono roman 400-700, **no SOFT axis**), set `font: false` in `mkdocs.yml` and load the upstream Google Fonts URL via a `<link>` in `main.html`'s `extrahead` block. Verify a single `fonts.googleapis.com` request in DevTools.\n\n### 4. Scope every homepage component class under `.page--home`\n\nThe upstream uses `<main class=\"page page--home\">` on its index page and inner pages don't inherit those classes. In MkDocs the same component class names will collide if any markdown happens to use `class=\"terminal\"`, `class=\"footer\"`, `class=\"section\"`, etc. Material's admonitions, tabbed content, and `md_in_html` all generate divs with predictable class names, and contributors will write more.\n\nDiscipline: every homepage component rule must include `.page--home` as an ancestor, OR rename the class with a project-specific prefix (e.g., `home-footer`). The cost of getting this wrong is silent visual breakage on inner pages weeks later when someone uses one of the colliding names.\n\n### 5. Rename `.footer` → `.home-footer`\n\nThe single most common collision. Markdown that includes a literal `<div class=\"footer\">` is plausible and will inherit the homepage's 60px-padded, 5-column-grid footer styling. Rename rather than scope.\n\n### 6. h3 and h4 are technical reference, not display type\n\nInner pages like `api-reference.md` use `### GET /api/health` and `### POST /api/v1/services` as section headings. Rendering these in Fraunces italic display style (the obvious choice for a \"serif headings\" design) makes the API reference unreadable.\n\nThe rule: h1 and h2 stay Fraunces italic for page and section titles. h3 and h4 switch to Instrument Sans bold so technical reference reads as text, not as type. Add a `:has(code)` block that flips any heading containing inline code to JetBrains Mono with signal-orange code text. Add a `@supports not selector(:has(*))` fallback for older browsers.\n\n```css\n.md-typeset h3 {\n  font-family: var(--sans);\n  font-weight: 700;\n  font-size: clamp(18px, 1.6vw, 22px);\n}\n.md-typeset h1:has(code),\n.md-typeset h2:has(code),\n.md-typeset h3:has(code),\n.md-typeset h4:has(code) {\n  font-family: var(--mono);\n  font-style: normal;\n  font-weight: 700;\n}\n```\n\n### 7. Tabbed content nests boxes, fix it\n\nMaterial's `.md-typeset .tabbed-set` defaults to a bordered, backgrounded box. Code blocks inside also default to bordered backgrounded boxes. The result is nested rectangles with cluttered visual hierarchy.\n\nThe fix: strip the `.tabbed-set` background and border. Leave only a bottom underline on `.tabbed-labels`. Let the inner code blocks be the visual statement. Tighten `pre > code` padding to ~14px so single-line install commands don't render as 70px-tall rectangles.\n\n### 8. Mermaid via Material's CSS variables, not via separate init\n\nMkDocs Material includes a Mermaid integration that reads `--md-mermaid-*` CSS variables. Don't bring in `mermaid.esm.mjs` separately like the upstream Hugo site does. Instead, set the variables in the slate scheme block:\n\n```css\n[data-md-color-scheme=\"slate\"] {\n  --md-mermaid-node-bg-color:   var(--ink-3);\n  --md-mermaid-node-fg-color:   var(--paper);\n  --md-mermaid-edge-color:      var(--mute);\n  /* ...full list in extra.css */\n}\n```\n\nPlus a `.md-typeset .mermaid` container restyle (dashed border, ink-3 background) for the diagram block itself.\n\n### 9. Guard inline scripts against `navigation.instant`\n\n`navigation.instant` is enabled (`mkdocs.yml`). On every navigation back to the homepage, Material rehydrates the body. Any `setInterval`, `setTimeout`, or event listener registered in an inline `<script>` will register **again**, leaking handles indefinitely.\n\nPattern for the live UTC clock used in the rail and footer:\n\n```html\n<script>\n  (function () {\n    if (window.__kubefwdClock) {\n      window.__kubefwdClock.tick();\n      return;\n    }\n    function tick() { /* ... */ }\n    tick();\n    var handle = setInterval(tick, 30 * 1000);\n    window.__kubefwdClock = { tick: tick, handle: handle };\n  })();\n</script>\n```\n\nThe `tick()` call on re-entry refreshes the displayed time without registering a new interval.\n\n### 10. Drop the light/dark toggle\n\nThe canonical txn2 identity is dark only. Collapse `palette` to a single `scheme: slate`. Remove the `toggle:` blocks. Audit `extra.css` and `index.md` for orphan light-mode references (`hero-logo-light`, `prefers-color-scheme: light`, `kf-green` etc).\n\n### 11. Atmospheric overlays at low z-index\n\n`body::before` (grain) and `body::after` (vignette) are fixed viewport overlays. Place them at `z-index: 1` so they sit above the page background but below the rail (z-50) and skiplink (z-200). Vignette has no blend mode, so a higher z-index would darken interactive chrome.\n\n### 12. What Hugo does that MkDocs cannot match\n\nFor reference when the next sister project chooses its adoption level:\n\n- Hugo can compile tokens.json into CSS custom properties at build time via `resources.Get` + `transform.Unmarshal`. MkDocs has no equivalent. We hand-mirror the tokens in `extra.css` `:root` and update them when upstream changes.\n- Hugo can subscribe to upstream tokens through a small extra.css that imports a generated `:root { --... }` block. MkDocs cannot. Token sync is a manual PR.\n- Hugo's partial system handles header/footer composition naturally. MkDocs uses Material template `{% block %}` overrides, which is similar but constrained to Material's block names (`announce`, `header`, `tabs`, `container`, `content`, `footer`, `scripts`).\n\n## Voice and copy\n\nDefers to upstream. Briefly:\n\n- No em-dashes (U+2014) or en-dashes (U+2013) anywhere, including code comments and template comments. Use commas, periods, colons, parentheses, slashes, hyphens.\n- No AI-tell vocabulary: `seamless`, `leverage`, `comprehensive`, `robust`, `delve`, `unleash`, `elevate`, `embark`, `tapestry`, `not just X but Y`, `as an AI`, `let me X`.\n- Sentence case for body. Lowercase for rail and label text. Title case rare.\n- Section indices: `§ 01 / title` with slash, never an em-dash.\n- Year ranges use a hyphen: `2017-2026`.\n- Verify before commit: `grep -RE \"—|–\" docs/ mkdocs.yml`.\n\n## Updating\n\nWhen the upstream `txn2/www/DESIGN.md` or `tokens.json` changes:\n\n1. Read the upstream diff. Identify which tokens, components, or rules changed.\n2. Update the matching CSS variables in `docs/stylesheets/extra.css` `:root`.\n3. If a component contract changed (padding, border, hover behavior), update the homepage template in `docs/overrides/home.html` and the matching CSS rules.\n4. Update this file's File map / Project-specific components / MkDocs Material learnings sections if a new learning emerges.\n5. Run `mkdocs build --strict` and verify in the browser before committing. Verify the home page hero, flagship cards, terminal, stack, coda, and home-footer. Verify an inner page (`/getting-started/`, `/api-reference/`) still inherits the look.\n\nKeep this file thin. If a section grows past 30 lines, ask whether it belongs upstream instead.\n\n## Downstream contract for sister projects\n\nThis file is canonical only for kubefwd.com. Other sister projects (txeh, mcp-s3, mcp-trino, mcp-datahub, mcp-data-platform) considering the same adoption should:\n\n1. Use this file as a template for their own thin local DESIGN.md.\n2. Reference upstream `txn2/www/DESIGN.md` as the source of truth for tokens, typography, components, voice.\n3. Replace the kubefwd-specific sections (project-specific components, file paths, custom additions) with their own.\n4. Keep the MkDocs Material learnings section. Those apply to every MkDocs Material project.\n5. Update upstream's downstream-contract list when adding a new project.\n\n<!-- File: docs/architecture.md (Tokens: ~1630 | Category: project-spec) -->\n# Architecture\n\nHow kubefwd works under the hood.\n\n## Overview\n\nkubefwd establishes port forwards to Kubernetes services by:\n\n1. Discovering services in specified namespaces\n2. Allocating unique local IP addresses (127.x.x.x)\n3. Updating `/etc/hosts` with service hostnames\n4. Creating SPDY connections through the Kubernetes API\n5. Monitoring pod lifecycle for automatic reconnection\n\n```mermaid\nflowchart TB\n    subgraph workstation[\"Your Workstation\"]\n        subgraph kubefwd[\"kubefwd\"]\n            sw[Service Watcher]\n            ip[IP Allocator]\n            hm[Hosts Manager]\n\n            subgraph pfm[\"Port Forward Manager\"]\n                pf1[\"127.1.27.1:8080\"]\n                pf2[\"127.1.27.2:3306\"]\n                pf3[\"127.1.27.3:6379\"]\n            end\n        end\n    end\n\n    subgraph cluster[\"Kubernetes Cluster\"]\n        api[\"api-pod :8080\"]\n        mysql[\"mysql-pod :3306\"]\n        redis[\"redis-pod :6379\"]\n    end\n\n    pf1 -->|SPDY via K8s API| api\n    pf2 -->|SPDY via K8s API| mysql\n    pf3 -->|SPDY via K8s API| redis\n```\n\n## Key Components\n\n### Service Discovery\n\nkubefwd uses Kubernetes **informers** to watch for service events:\n\n- **Add**: New service discovered → start port forward\n- **Update**: Service modified → update port forward if needed\n- **Delete**: Service removed → stop port forward, cleanup hosts\n\nThis event-driven approach means kubefwd reacts in real-time to cluster changes.\n\n### IP Allocation\n\nEach service receives a unique loopback IP address:\n\n```\n127.[1+cluster].[27+namespace].[service_count]\n```\n\n| Component | Base | Range |\n|-----------|------|-------|\n| First octet | 127 | Fixed |\n| Second octet | 1 | 1-255 (cluster index) |\n| Third octet | 27 | 27-255 (namespace index) |\n| Fourth octet | 1 | 1-255 (service count) |\n\n**Why unique IPs?**\n\nUnlike `kubectl port-forward` which uses `localhost:port`, kubefwd assigns each service its own IP. This allows:\n\n- Multiple services on the same port (e.g., several databases on 3306)\n- Realistic service topology matching in-cluster behavior\n- No port conflict management needed\n\n### Hosts File Management\n\nkubefwd modifies `/etc/hosts` to map service names to allocated IPs:\n\n```\n# Before kubefwd\n127.0.0.1       localhost\n\n# After kubefwd starts\n127.0.0.1       localhost\n127.1.27.1      api-service\n127.1.27.2      database\n127.1.27.3      cache\n```\n\n**Safety measures:**\n- Original hosts file backed up to `~/hosts.original`\n- Entries removed on clean shutdown\n- Mutex locking prevents race conditions\n- Stale entry purging available (`-p` flag)\n\n### Port Forwarding\n\nkubefwd creates SPDY connections through the Kubernetes API server:\n\n1. **Pod Selection**: Find pods backing the service\n2. **Connection**: Establish SPDY tunnel via API server\n3. **Local Binding**: Bind to allocated IP and service port(s)\n4. **Data Transfer**: Proxy traffic bidirectionally\n\n```mermaid\nflowchart LR\n    app[Local App] --> ip[\"127.1.27.1:8080\"] --> kf[kubefwd] --> api[K8s API] --> pod[\"Pod:8080\"]\n```\n\n### Pod Lifecycle Monitoring\n\nkubefwd watches pod events to maintain forwarding:\n\n- **Pod deleted**: Stop forward, trigger reconnection\n- **Pod recreated**: Auto-reconnect (if enabled)\n- **Pod crash**: Detect via connection loss, reconnect\n\nThe auto-reconnect feature uses exponential backoff:\n- Initial: 1 second\n- Maximum: 5 minutes\n- Reset on successful connection\n\n## Service Types\n\n### Normal Services (ClusterIP)\n\nFor services with selectors:\n\n1. Query pods matching the selector\n2. Select first available Running pod\n3. Forward to that single pod\n4. Hostname: `service-name`\n\n### Headless Services (ClusterIP: None)\n\nFor services without cluster IP:\n\n1. Query all pods matching the selector\n2. Forward to ALL pods\n3. Hostnames:\n   - `service-name` → first pod\n   - `pod-name.service-name` → each specific pod\n\nThis is essential for StatefulSets and databases requiring pod-specific addressing.\n\n### Services Without Selectors\n\n**Not supported.** kubefwd requires pod selectors to discover backing pods. Services with manually managed Endpoints are skipped.\n\n## TUI Architecture\n\nThe Terminal User Interface uses the [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework:\n\n```mermaid\nflowchart LR\n    subgraph core[\"Core Services\"]\n        eb[Event Bus]\n        ss[State Store]\n        mr[Metrics Registry]\n    end\n\n    subgraph views[\"View Models\"]\n        sm[Services]\n        lm[Logs]\n        dm[Detail]\n    end\n\n    core --> views\n```\n\n### Event Bus\n\nDecoupled communication between components:\n- Service status changes\n- Metrics updates\n- Log messages\n- User actions\n\n### State Store\n\nCentralized, thread-safe state management:\n- Forward status for all services\n- Metrics data (bytes, rates)\n- Filter/sort state\n\n### Metrics Collection\n\nTraffic monitoring with:\n- Byte counters (atomic operations)\n- Rate calculations (rolling window)\n- HTTP request/response detection\n- Sparkline visualization\n\n## Thread Safety\n\nkubefwd handles concurrent operations carefully:\n\n| Resource | Protection |\n|----------|------------|\n| Service registry | RWMutex |\n| IP allocation | Per-namespace mutex |\n| Hosts file | Global mutex with file locking |\n| Metrics | Atomic operations + RWMutex |\n| Event bus | Channel-based with buffer |\n\n## Shutdown Sequence\n\nClean shutdown ensures no leftover state:\n\n1. User signal (q, Ctrl+C) → stop listening\n2. Close service watchers\n3. Stop all port forwards\n4. Remove hosts file entries\n5. Remove network interface aliases\n\nIf shutdown is interrupted, use `-p` to purge stale entries on next run.\n\n## Network Interface Management\n\nkubefwd creates loopback aliases:\n\n**macOS (lo0):**\n```bash\nifconfig lo0 alias 127.1.27.1\n```\n\n**Linux (lo):**\n```bash\nip addr add 127.1.27.1/8 dev lo\n```\n\nThese aliases allow binding to unique IPs while keeping traffic local.\n\n## Security Considerations\n\nkubefwd requires elevated privileges for:\n\n1. **Network interface modification**: Adding IP aliases\n2. **Hosts file modification**: DNS resolution\n3. **Low port binding**: Ports below 1024\n\n**Recommendations:**\n- Run only in development environments\n- Don't run in production workstations with sensitive data\n- Review services before forwarding from production clusters\n- Use label selectors to limit scope\n\n## Performance Characteristics\n\n| Operation | Complexity |\n|-----------|------------|\n| Service discovery | O(services) per namespace |\n| Port forward setup | O(1) per service |\n| Metrics sampling | O(forwards) per second |\n| Hosts file update | O(forwards) per change |\n\nkubefwd is designed for development use with dozens to hundreds of services. For very large clusters, use selectors to limit scope.\n\n<!-- File: CLAUDE.md (Tokens: ~4494 | Category: claude-rule) -->\n# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\nkubefwd is a popular command-line utility for bulk Kubernetes port forwarding, featured in \"essential k8s developer tools\" lists. It forwards multiple services from one or more namespaces, adding corresponding entries to `/etc/hosts` for local development.\n\n**Key Differentiator from `kubectl port-forward`**: Each service gets its own unique loopback IP address (127.x.x.x), allowing multiple services to use the same port simultaneously (e.g., multiple databases on port 3306, or multiple web services on port 80). This mirrors how services work in the cluster, enabling truly cluster-like local development.\n\nThe tool automatically monitors service and pod lifecycle events, starting/stopping port forwards as services are created, deleted, or pods are rescheduled.\n\n## Integration and Usage Patterns\n\nkubefwd is commonly integrated into development workflows:\n\n- **With Tilt**: Blog posts document using kubefwd with Tilt for automated local development setups\n- **Development Environment Setup**: Teams use kubefwd to mirror production-like service topologies locally\n- **Microservices Development**: Allows developers to run one service locally while accessing dependencies in the cluster via service names\n- **Database Access**: Popular for forwarding multiple databases (MySQL, PostgreSQL, MongoDB) on their native ports without port conflicts\n\nThe typical workflow: `sudo -E kubefwd svc -n <namespace> --tui` runs in a dedicated terminal while developers work in their IDE, accessing cluster services as if running in-cluster.\n\n## TUI (Terminal User Interface)\n\nkubefwd includes an interactive TUI built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), enabled with `--tui`:\n\n```bash\nsudo -E kubefwd svc -n default --tui\n```\n\n### TUI Features\n- **Real-time service monitoring**: See all forwarded services with connection status\n- **Traffic metrics**: Bytes in/out with sparkline graphs\n- **Pod log streaming**: View container logs directly in the TUI\n- **HTTP activity detection**: Monitor HTTP requests/responses flowing through forwards\n- **Auto-reconnect**: Enabled by default in TUI mode, with exponential backoff (1s → 5min max)\n- **Keyboard-driven**: Full keyboard navigation (j/k, Enter, Tab, /, ?, q)\n\n### TUI Architecture\n\nThe TUI follows the Model-View-Update (MVU) pattern:\n\n- **Event Bus** (`pkg/fwdtui/events`): Decoupled pub/sub communication between components\n- **State Store** (`pkg/fwdtui/state`): Centralized, thread-safe state management for all forwards\n- **Metrics Registry** (`pkg/fwdtui/metrics`): Traffic counters with atomic operations\n- **Components** (`pkg/fwdtui/components`): UI models for services list, logs, detail view\n\n### TUI Keyboard Shortcuts\n- `j/k` or arrows: Navigate\n- `Enter`: Open detail view\n- `Tab`: Switch panels/tabs\n- `/`: Filter services\n- `r`: Reconnect errored services\n- `b`: Toggle bandwidth columns\n- `?`: Help overlay\n- `q`: Quit\n\n## Git Policy\n\n**All commits require explicit human approval.** Do not run `git commit` unless the user explicitly asks you to commit. Always show the diff or summarize changes and wait for approval first.\n\n## Verification\n\n**\"Testing\" means `make verify`, not `go test ./...`.** Run it before handing work back; it runs every check CI runs, with the same pinned tools, and a change isn't done until it passes.\n\nThe gates (details in CONTRIBUTING.md, \"Quality Gates\"):\n\n- **Formatting**: gofmt, goimports (`github.com/txn2/kubefwd` local prefix), gofumpt over the whole tree. Fix with `make fmt`.\n- **Lint**: every linter in `.golangci.yml` applies to lines changed since the merge base with `origin/master` (`make lint`, CI `--new-from-rev`). Pre-existing issues elsewhere don't fail; anything touched must pass. `make lint-full` shows the backlog. A `//nolint` or `#nosec` needs a reason.\n- **Complexity** (production code): gocyclo 10, gocognit 15, nestif 5, dupl 150, nakedret 30. Split functions rather than suppressing.\n- **Layering**: depguard rules in `.golangci.yml`; `pkg/` never imports `cmd/`, leaf packages import nothing first-party, the forwarding core never imports `fwdapi`/`fwdmcp`.\n- **Coverage**: total ≥ 80% (`make coverage-check`); changed lines ≥ 80% (`make patch-coverage`). Both block, here and in codecov. Root-only or cluster-only code is made testable by injecting the OS call (see `runCommand` and `goos` in `pkg/fwdapi/network.go`), not left uncovered.\n- **Security**: `make security` runs gosec, govulncheck on both modules (gated by `scripts/govulncheck-gate.py` against `.govulncheck-allow.txt`), and osv-scanner (against `osv-scanner.toml`). Upgrade rather than accept; an accepted advisory needs a reason and expires.\n- **SAST**: `make semgrep` (p/golang, whole tree) and `make semgrep-diff` (`.semgrep-diff/` rules, changed lines). CodeQL runs `security-and-quality` in CI.\n- **Mutation**: `make mutate` (gremlins, 60% efficacy), weekly in CI. Too slow for every change.\n- **Toolchain**: Go is pinned by the `toolchain` line in go.mod; CI's setup-go reads the same line. Tool versions are pinned in the Makefile and installed into `.tools/`.\n\n## Build and Development Commands\n\n### Building\n```bash\n# Build the project (uses goreleaser)\ngo build -o kubefwd ./cmd/kubefwd/kubefwd.go\n\n# Build with version information\ngo build -ldflags \"-X main.Version=dev\" -o kubefwd ./cmd/kubefwd/kubefwd.go\n```\n\n### Testing\n```bash\n# Run all tests\ngo test ./...\n\n# Run tests for a specific package\ngo test ./pkg/fwdport\n\n# Run tests with verbose output\ngo test -v ./pkg/fwdport\n```\n\n### Running Locally\n```bash\n# Requires root/sudo for network interface management and /etc/hosts modification\nsudo ./kubefwd svc -n <namespace>\n\n# Use -E flag to preserve environment (especially KUBECONFIG)\nsudo -E ./kubefwd svc -n <namespace>\n\n# With interactive TUI (recommended for development)\nsudo -E ./kubefwd svc -n <namespace> --tui\n```\n\n### Dependencies\n```bash\n# Download dependencies\ngo mod download\n\n# Update dependencies\ngo mod tidy\n```\n\n### Debugging and Development\n\n```bash\n# Enable verbose logging\nsudo -E ./kubefwd svc -n <namespace> -v\n\n# Test with a single service using field selector\nsudo -E ./kubefwd svc -n <namespace> -f metadata.name=<service-name>\n\n# Test with label selector\nsudo -E ./kubefwd svc -n <namespace> -l app=myapp\n\n# Use IP reservation config for reproducible testing\nsudo -E ./kubefwd svc -n <namespace> -z example.fwdconf.yml\n```\n\nThe verbose flag (`-v`) enables debug-level logging (logrus.DebugLevel), which shows:\n- Service registry operations\n- Pod sync events\n- IP allocation details\n- Port forwarding lifecycle events\n\n### Demo Environment\n\nA comprehensive demo manifest is available for testing:\n\n```bash\n# Deploy 60 services across 2 namespaces\nkubectl apply -f test/manifests/demo-microservices.yaml\n\n# Forward all demo services with TUI\nsudo -E ./kubefwd svc -n kft1,kft2 --tui\n\n# Cleanup\nkubectl delete -f test/manifests/demo-microservices.yaml\n```\n\n## Architecture\n\n### Core Components Flow\n\n1. **Entry Point** (`cmd/kubefwd/kubefwd.go`): CLI entry, delegates to services command\n2. **Services Command** (`cmd/kubefwd/services/services.go`): Main orchestration logic\n   - Validates cluster connectivity and RBAC permissions\n   - Creates Kubernetes informers to watch Service events (Add/Delete/Update)\n   - Spawns namespace watchers for each namespace×context combination\n3. **Service Registry** (`pkg/fwdsvcregistry`): Central registry of all forwarded services\n   - Thread-safe map of active ServiceFWD instances\n   - Handles lifecycle (add, remove, shutdown all)\n4. **Service Forwarding** (`pkg/fwdservice`): Per-service forwarding logic\n   - Queries pods backing each service\n   - Manages pod selection (single pod for normal services, all pods for headless)\n   - Debounces pod sync operations to avoid hammering k8s API\n   - Maintains map of active port forwards per pod\n5. **Port Forwarding** (`pkg/fwdport`): Individual pod port forwarding\n   - Creates SPDY connection to k8s API server\n   - Manages port forward lifecycle with watch for pod deletion\n   - Updates `/etc/hosts` file with service hostnames\n6. **Network/IP Management** (`pkg/fwdnet`, `pkg/fwdIp`): Loopback interface management\n   - Allocates unique 127.x.x.x IPs for each service\n   - Manages IP aliases on loopback interface (macOS: lo0, Linux: lo)\n   - Supports IP reservation via config file or CLI flags\n\n### Key Architectural Patterns\n\n**Event-Driven Architecture**: Uses Kubernetes informers to react to service/pod lifecycle events in real-time.\n\n**Headless vs Normal Services**:\n- Normal services forward the first available pod using the service name\n- Headless services (ClusterIP: None) forward all pods, with first pod as service name and rest as pod-name.service-name\n\n**Debouncing**: Uses 5-second debouncer for pod sync operations to handle rapid pod changes (e.g., rolling deployments) without excessive k8s API calls.\n\n**Thread Safety**: Extensive use of mutexes for:\n- Per-namespace IP allocation (`NamespaceIPLock`)\n- Service registry access\n- Hosts file modifications\n\n**Shutdown Orchestration**: Clean shutdown cascade:\n1. User signal → stopListenCh\n2. Namespace watchers stop\n3. Service registry shutdown\n4. Individual pod port forwards stop\n5. Hosts file cleanup and network alias removal\n\n### Package Responsibilities\n\n- `fwdservice`: Service-level forwarding orchestration and pod management\n- `fwdport`: Individual pod port forwarding via k8s API\n- `fwdsvcregistry`: Global service registry and lifecycle management\n- `fwdnet`: Network interface management (IP aliasing)\n- `fwdIp`: IP allocation logic and reservation handling\n- `fwdhost`: Hosts file backup management\n- `fwdcfg`: Kubernetes client configuration\n- `fwdpub`: Publisher interface for output\n- `fwdtui`: Terminal User Interface (Bubble Tea)\n  - `fwdtui/components`: UI view models (services list, logs, detail, help, status bar)\n  - `fwdtui/events`: Event bus with panic recovery for decoupled pub/sub\n  - `fwdtui/state`: Thread-safe state store with RWMutex protection\n  - `fwdtui/metrics`: Traffic metrics with atomic counters and rate calculation\n  - `fwdtui/portforward`: Port forward wrapper that emits metrics events\n- `utils`: Root permission checks (OS-specific)\n\n## Important Implementation Details\n\n### Root Permissions and Security\n\nkubefwd requires superuser privileges for:\n- Adding IP aliases to loopback interface\n- Binding to low-numbered ports\n- Modifying `/etc/hosts`\n\nAlways run with `sudo -E` to preserve environment variables (KUBECONFIG).\n\n**Security Considerations**: kubefwd is considered a \"powerful but potentially dangerous tool\" because it:\n- Modifies system-level network configuration\n- Changes `/etc/hosts` which affects DNS resolution system-wide\n- Requires root access which can impact system stability if misused\n- Opens network connections to cluster services\n\nThe tool backs up the original hosts file to `~/hosts.original` before making modifications, but improper shutdown can leave the system in an inconsistent state.\n\n### Hostname Generation\nHostnames follow pattern based on cluster and namespace indices:\n- Namespace 0, Cluster 0: `service-name`\n- Namespace >0: `service-name.namespace`\n- Cluster >0: `service-name.context` or `service-name.namespace.context`\n\nFor headless services, pods get: `pod-name.service-name[.namespace][.context]`\n\n### IP Allocation\nBase IP is 127.1.x.x with incremental allocation. Can be customized via:\n- `--fwd-conf` YAML config file (see `example.fwdconf.yml`)\n- `--reserve` CLI flag for individual reservations\n\n### Port Mapping\nSupports port remapping with `-m` flag (e.g., `-m 80:8080` maps service port 80 to local 8080).\n\n### UDP Limitation\nUDP port forwarding is not supported (Kubernetes API limitation: kubernetes/kubernetes#47862).\n\n## Code Organization\n\n```\ncmd/kubefwd/           # CLI entry point\n  kubefwd.go          # Main entry, root command\n  services/\n    services.go       # Services subcommand, namespace watchers\npkg/\n  fwdservice/         # Service forwarding logic\n  fwdport/            # Pod port forwarding\n  fwdsvcregistry/     # Service registry\n  fwdnet/             # Network interface management\n  fwdIp/              # IP allocation\n  fwdhost/            # Hosts file operations\n  fwdcfg/             # K8s config\n  fwdpub/             # Publisher\n  fwdtui/             # Terminal User Interface\n    components/       # UI models (services, logs, detail, help)\n    events/           # Event bus for decoupled communication\n    state/            # Centralized state store\n    metrics/          # Traffic metrics with atomic counters\n    portforward/      # Port forward wrapper with metrics\n  utils/              # Utilities (root check)\ntest/\n  integration/        # Integration tests (require KIND cluster)\n  manifests/          # Test Kubernetes manifests\n  scripts/            # Test setup/teardown scripts\n```\n\n## Contribution Policy\n\n**Public Contributions**: The project welcomes pull requests from the community for:\n- Bug fixes\n- Tests\n- Documentation\n- Stability and compatibility enhancements\n\n**Feature Development**: New features are developed by select contributors only. Public feature PRs are discouraged due to past experience with contributions that introduced drastic codebase changes, were difficult to review and test, and added significant technical debt. This policy is documented in the README.\n\n**Internal Development**: Maintainers and trusted contributors are welcome to develop new features. If you're working on this codebase with direct access, feature development is encouraged.\n\n## Release Process\n\nUses GoReleaser (`.goreleaser.yml`):\n- Builds for Linux, macOS, Windows (multiple architectures)\n- Creates Docker images (Alpine and Ubuntu variants)\n- Publishes to GitHub releases\n- Updates Homebrew tap (txn2/homebrew-tap)\n- Generates RPM, DEB, APK packages\n\nThe version is set via ldflags during build: `-ldflags \"-X main.Version={{.Version}}\"`\n\n## Testing\n\n### Unit Tests\n\n`make verify` is the full check (see Verification above). For quicker loops:\n\n```bash\n# Run all unit tests\ngo test ./...\n\n# Run with coverage\ngo test -cover ./...\n\n# Run specific package tests\ngo test -v ./pkg/fwdtui/events/...     # Event bus tests (100% coverage)\ngo test -v ./pkg/fwdtui/components/... # UI component tests\ngo test -v ./pkg/fwdtui/state/...      # State store tests\ngo test -v ./pkg/fwdport/...           # Port forwarding tests\n```\n\n### Integration Tests\n\nLocated in `test/integration/`, these require a KIND cluster:\n\n```bash\n# Setup KIND cluster\n./test/scripts/setup-kind.sh\n./test/scripts/deploy-test-services.sh test/manifests\n\n# Run integration tests (requires sudo)\nsudo -E go test -tags=integration -v ./test/integration/...\n\n# Teardown\n./test/scripts/teardown-kind.sh\n```\n\nIntegration tests cover: basic forwarding, headless services, auto-reconnect, multi-namespace, port mapping, and cleanup verification.\n\n### Areas for Additional Testing\n- Hosts file race condition scenarios (Issue #74)\n- Cleanup/restore logic for error conditions (Issue #5)\n- Pod state filtering for evicted/completed pods (Issues #34, #114)\n\n## Areas for Improvement\n\nBased on known issues, these areas would benefit from development:\n\n### Auto-Reconnect Enhancement\nAuto-reconnect is now implemented (`-a` flag, enabled by default in TUI mode) with exponential backoff. However, edge cases may still exist:\n- Very rapid pod cycling during rolling deployments\n- Network partitions vs pod deletion detection\n- Reconnection priority when multiple pods are available\n\n### Hosts File Synchronization (Issues #74, #79)\nThe `HostFileWithLock` mutex in `pkg/fwdport` may not be sufficient for all race conditions. Consider:\n- Batching hosts file updates\n- Implementing retry logic for failed updates\n- Adding verification that all services are actually written\n\n### Graceful Shutdown (Issue #5)\nEnhance the shutdown cascade to guarantee hosts file restoration even on signal interruption. Consider using `defer` more extensively or implementing a signal handler with guaranteed cleanup.\n\n### Pod State Filtering (Issues #34, #114)\nThe pod filtering in `fwdservice.GetPodsForService()` should be more defensive:\n- Handle additional pod phases gracefully\n- Add better error handling for watch events with non-pod objects\n- Consider ignoring evicted pods earlier in the pipeline\n\n### Services Without Selectors (Issue #35)\nCould potentially support endpoint-based services by querying Endpoints resources directly instead of relying on pod selectors.\n\n## Known Limitations and Active Issues\n\nBased on community feedback and GitHub issues, developers should be aware of:\n\n### Architectural Limitations\n\n**Services Without Selectors** (Issue #35): kubefwd does not support ClusterIP services without selectors (services backed by manually created Endpoints). The code assumes services have pod selectors and will skip services with empty selector strings.\n\n**Auto-Reconnect Available** (Issue #21 resolved): Auto-reconnect is now implemented with the `-a` flag (enabled by default in TUI mode). When pods restart, kubefwd automatically re-establishes port forwards with exponential backoff (1s → 5min max).\n\n**UDP Protocol Not Supported**: Kubernetes port-forwarding API limitation (kubernetes/kubernetes#47862).\n\n### Race Conditions and Edge Cases\n\n**Hosts File Race Condition** (Issue #74): When forwarding multiple services simultaneously, especially on Windows with Docker Desktop, race conditions can occur during hosts file updates, leading to DNS resolution errors.\n\n**Hosts File Not Fully Restored** (Issue #5): On certain error conditions or unclean shutdowns (Ctrl-C timing), the original `/etc/hosts` may not be fully restored. Always check `~/hosts.original` backup.\n\n**Incomplete Hosts File Updates** (Issue #79): Some services may be assigned IPs and be accessible but not appear in the hosts file. This appears related to timing in the hosts file update logic.\n\n### Pod State Handling\n\n**Evicted/Completed Pods** (Issues #34, #114): Starting from v1.11.0, interface conversion errors occur with evicted pods or completed jobs. The code in `pkg/fwdservice` filters for `PodPending` and `PodRunning` states, but watch events for other states can cause errors.\n\n**Pod Status Assumptions**: The code assumes pods are either Pending, Running, Succeeded, Failed, or Unknown. Edge cases with custom pod conditions may not be handled gracefully.\n\n## Common Issues and Troubleshooting\n\n**Permission Errors**: Always use `sudo -E` to preserve KUBECONFIG.\n\n**IP/Port Conflicts**: Use IP reservations (`-r` or `-z`) to avoid conflicts.\n\n**Stale /etc/hosts Entries**: Original hosts file backed up to `~/hosts.original`. Check this file if DNS resolution is broken after kubefwd exits.\n\n**Pod Watch Failures**: Check RBAC permissions (list/get/watch pods, get services).\n\n**Connection Refused (localhost:8080)**: This usually means kubectl is not properly configured or KUBECONFIG was not preserved (missing `-E` flag with sudo).\n\n<!-- File: smithery.yaml (Tokens: ~124 | Category: mcp-config) -->\n# Smithery.ai MCP Server Configuration\n# https://smithery.ai/docs\n\nstartCommand:\n  type: stdio\n  configSchema:\n    type: object\n    properties:\n      apiUrl:\n        type: string\n        description: \"URL of the kubefwd REST API\"\n        default: \"http://kubefwd.internal/api\"\n    required: []\n  commandFunction: |\n    (config) => ({\n      command: 'kubefwd',\n      args: ['mcp', ...(config.apiUrl ? ['--api-url', config.apiUrl] : [])],\n      env: {}\n    })\n</yakaai_skills>"}