Metadata-Version: 2.4
Name: ice-context
Version: 0.1.7
Summary: Issue Context Engine — transform issue tracker tickets into structured AI-ready context.
Project-URL: Homepage, https://github.com/althaf-space/ice
Project-URL: Repository, https://github.com/althaf-space/ice
Project-URL: Bug Tracker, https://github.com/althaf-space/ice/issues
Author-email: althaf <althaf.space@gmail.com>
License: ICE — Issue Context Engine
        Personal Use License with Contributor License Agreement
        
        Copyright (c) 2026 Althaf. All rights reserved.
        
        ────────────────────────────────────────────────────────────────────────────────
        GRANT OF USE
        ────────────────────────────────────────────────────────────────────────────────
        
        Permission is granted, free of charge, to any individual to use this software
        for personal, non-commercial purposes, subject to the following conditions.
        
        ────────────────────────────────────────────────────────────────────────────────
        RESTRICTIONS
        ────────────────────────────────────────────────────────────────────────────────
        
        You MAY NOT, without prior written permission from the copyright holder:
        
          1. Sell, rent, lease, or sublicense this software or any derivative of it.
        
          2. Incorporate this software or any derivative into a commercial product,
             SaaS offering, hosted service, or any product sold or licensed to others.
        
          3. Redistribute this software or modified versions of it to third parties,
             whether for free or for a fee.
        
          4. Remove or alter any copyright, license, or attribution notices contained
             in the software.
        
        ────────────────────────────────────────────────────────────────────────────────
        PERMITTED MODIFICATIONS
        ────────────────────────────────────────────────────────────────────────────────
        
        You may modify the software for your own personal use. Modified versions may
        not be redistributed or published without written permission from the copyright
        holder.
        
        ────────────────────────────────────────────────────────────────────────────────
        CONTRIBUTOR LICENSE AGREEMENT
        ────────────────────────────────────────────────────────────────────────────────
        
        By submitting a contribution (pull request, patch, or any other change) to
        this project, you agree to the following terms:
        
          1. You retain copyright in your contribution.
        
          2. You grant the copyright holder (Althaf) a perpetual, worldwide,
             irrevocable, royalty-free license to use, reproduce, modify, distribute,
             sublicense, and commercialize your contribution as part of this project,
             without restriction, including for commercial purposes.
        
          3. You confirm that you have the right to grant this license — that your
             contribution is your original work, or that you have the necessary rights
             from your employer or any third party.
        
          4. You understand that this project and all contributions to it may be used
             commercially by the copyright holder, and that you will receive no
             compensation, royalty, or commercial rights as a result of contributing.
        
        This agreement does not transfer your copyright — you remain the author of your
        contribution. It gives the copyright holder the exclusive right to commercialize
        the combined work.
        
        ────────────────────────────────────────────────────────────────────────────────
        COPYRIGHT INFRINGEMENT
        ────────────────────────────────────────────────────────────────────────────────
        
        Any use of this software in violation of the restrictions above constitutes
        copyright infringement and may be subject to legal action under applicable
        copyright law.
        
        ────────────────────────────────────────────────────────────────────────────────
        DISCLAIMER
        ────────────────────────────────────────────────────────────────────────────────
        
        THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS
        FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
        COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING
        FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR ITS USE.
        
        ────────────────────────────────────────────────────────────────────────────────
        CONTACT
        ────────────────────────────────────────────────────────────────────────────────
        
        For commercial licensing inquiries or written permissions:
          althaf.space@gmail.com
          https://github.com/althaf-space/ice
Keywords: ai,cli,context,issues,jira,llm,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.30
Requires-Dist: cryptography>=41.0
Requires-Dist: google-genai>=1.0
Requires-Dist: httpx>=0.27
Requires-Dist: keyring>=24.0
Requires-Dist: mcp>=1.0
Requires-Dist: openai>=1.0
Requires-Dist: openpyxl>=3.1
Requires-Dist: pdfminer-six>=20221105
Requires-Dist: pillow>=10.0
Requires-Dist: pydantic>=2.0
Requires-Dist: pytesseract>=0.3.10
Requires-Dist: python-docx>=1.1
Requires-Dist: rich>=13.0
Requires-Dist: shellingham>=1.5
Requires-Dist: tomli-w>=1.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# ICE — Issue Context Engine

ICE transforms issue tracker tickets into structured, AI-ready context. It works as a standalone CLI and as an MCP server that any AI coding agent (Claude Code, Cursor, Codex, Windsurf, Antigravity) can call as a tool.

Instead of copying and pasting raw ticket text into a chat window, you point ICE at an issue key or URL and it fetches the ticket, processes all attachments (images via OCR and vision AI; documents via text extraction with formula annotation), runs a structured LLM analysis with visual grounding verification, and returns a clean JSON object your agent can act on immediately.

Currently supports **Jira Cloud**. Built to be extended to any issue tracker.

# Core Pillars

- **D-Lock Hardened Security**: All credentials are encrypted with **AES-256-GCM** and hardware-bound to the OS keyring. Secrets never touch the disk in plaintext.
- **Vision-Native Transcription**: An AI-first OCR workflow that prioritizes LLM Vision for 100% accurate transcription of complex tables, charts, and handwriting.
- **Universal AI Orchestration**: Native, optimized support for **Google Gemini (1.5 Pro/Flash)**, **xAI Grok**, **Anthropic Claude**, **OpenAI GPT-4o**, **Nvidia NIM**, and **Ollama (Local)**.
- **Agentic MCP Integration**: Seamlessly wires into Claude Code, Cursor, and other AI editors to provide your agent with high-fidelity "Ground Truth" context.
- **Universal Attachment Engine (UAE)**: Automated extraction from PDF, DOCX, XLSX (with formula logic), and images.

---

## How it works

```
ice analyze PROJ-123
       │
       ▼
  resolve connection
       │
       ▼
  connector.fetch()  ──────────────►  Jira REST API
       │                              ↓ issue JSON
       │◄──────────────────────────── parse → RawIssueData
       │
       ▼
  download & process attachments  (all in parallel)
  ├─ images  → Vision-Native OCR (Tesseract + LLM Vision fallback) + Base64 capture
  │             vision LLM: transcribes text, interprets graphs, and preserves literal UI data
  └─ documents (CSV / Excel / PDF / DOCX / TXT) → text / Markdown conversion
       ├─ Excel: dual-pass (values + formulas) — annotates formula cells as VALUE (Formula: EXPR)
       └─ large docs (>20 000 chars) → LLM summarization with verbatim preservation of
            column headers, formula annotations, and schema/logic blocks
       │
       ▼
  [no LLM configured — MCP headless mode]
  └─ return RawIssueResponse  (raw data + extracted texts + Base64 images)
       │
       ▼  [LLM configured]
  LLM analysis  (SYSTEM_PROMPT + structured user message)
  └─ SYSTEM_PROMPT mandates structured tagged blocks for spreadsheet data:
       ### [TECHNICAL SCHEMA: <filename>]  — column headers and sheet names
       ### [TECHNICAL LOGIC: <filename>]   — formula cells (Non-Negotiable Business Rules)
       │
       ▼
  visual grounding pass  (if confidence < 0.8 and image model set)
  └─ re-verify analysis against raw images, correct any contradictions
       │
       ▼
  attach Base64 images to output (always, when images exist)
  heuristic check still runs for log warning only:
       • confidence_score < 0.8
       • images exist but OCR text < 500 chars
       • issue type is Bug with no reproduction steps
       │
       ▼
  finalize()  — deterministic post-processing
  └─ completeness_score and missing_information recomputed from LLM output
       • missing_schema flagged for Story/Task/Epic with spreadsheet attachments
         when no [TECHNICAL SCHEMA:] or [TECHNICAL LOGIC:] block was produced
       • completeness_score capped at 0.79 when missing_schema is flagged
       │
       ▼
  IssueContext JSON  →  stdout / MCP response
```

---

## Prerequisites

- Python 3.11 or higher
- A Jira Cloud account — API Token works everywhere; OAuth PKCE available for SSO-enforced orgs
- An LLM provider — OpenAI, Anthropic, Google Gemini, xAI Grok, NVIDIA NIM, or Ollama (local, free). **Optional for MCP mode** — ICE returns raw data without any LLM configured.
- **Optional:** Tesseract OCR binary — only needed for image attachments. ICE works fully without it.

---

## Installation

The recommended install method for CLI tools is `pipx` — it isolates ICE from your project Python environments:

```bash
pipx install ice-context
```

Or install with plain pip:

```bash
pip install ice-context
```

Either way, the command is always `ice`.

**From source (development):**

```bash
git clone https://github.com/althaf-space/ice.git
cd ice
pip install -e ".[dev]"
```

Verify:

```bash
ice --version
ice --help
```

### Automatic update notifications

ICE checks PyPI once per day for newer versions. When an update is available you'll see a brief notice on stderr:

```
  ⬆  Update available: ice-context 0.1.6 → 0.1.7
     Run: pipx upgrade ice-context   or   pip install --upgrade ice-context
```

No action is needed — the check is silent if you're already on the latest version.

### Tesseract (optional — for image attachments)

If your tickets contain screenshots or diagrams, install the Tesseract binary for your OS. ICE detects it automatically — no configuration needed.

| OS | Install command |
|---|---|
| macOS | `brew install tesseract` |
| Ubuntu / Debian | `sudo apt install tesseract-ocr` |
| Windows | `winget install UB-Mannheim.TesseractOCR` |
| Other Linux | [Tesseract installation docs](https://tesseract-ocr.github.io/tessdoc/Installation.html) |

When Tesseract is absent and a ticket has image attachments, ICE prints a one-line warning and continues — it does not crash or exit.

### Tab completion

Run once after install, then restart your shell:

```bash
# PowerShell (Windows)
ice --install-completion powershell

# Bash (macOS / Linux)
ice --install-completion bash

# Zsh
ice --install-completion zsh
```

After restarting, `Tab` completes commands and double-`Tab` shows all options — exactly like git.

---

## Quick start

```bash
# 1. Connect to Jira
ice connection --add

# 2. Set up an LLM provider
ice model --add

# 3. Verify setup
ice status

# 4. Analyze a ticket
ice analyze PROJ-123
# or by full URL:
ice analyze https://yourcompany.atlassian.net/browse/PROJ-123
```

---

## Step 1 — Connect to Jira

```bash
ice connection --add
```

Choose your authentication method:

```
  1. API Token   (email + token, works everywhere)  ← recommended
  2. OAuth PKCE  (browser login — for SSO-enforced orgs)
```

### API Token (recommended)

You need:
1. Your Jira base URL — e.g. `https://yourcompany.atlassian.net`
2. Your Atlassian email address
3. An API token — generate one at `https://id.atlassian.com/manage-profile/security/api-tokens`

The token field is hidden — paste and press Enter. On Windows, use right-click to paste (Ctrl+V does not work in hidden fields).

### OAuth PKCE (for SSO-enforced orgs)

One-time setup at Atlassian's developer portal:

1. Go to `https://developer.atlassian.com/console/myapps/`
2. Click **Create** → **OAuth 2.0 integration**
3. Under **Permissions** → add Jira API → enable `read:jira-work` and `read:jira-user`
4. Under **Authorization** → set Callback URL to exactly: `http://localhost:8765/callback`
5. Copy your **Client ID** and **Client Secret**

Run `ice connection --add`, choose option 2, and enter those values. ICE opens your browser for Atlassian login and handles the token exchange automatically.

> **Headless / no-browser environments:** If ICE cannot open a browser (SSH session, CI machine, headless server), it prints the full authorization URL to the terminal instead of failing:
> ```
> No browser detected. Copy the URL below and open it manually:
>
>   https://auth.atlassian.com/authorize?...
>
> Waiting for authentication callback... (120s timeout)
> ```
> Copy the URL, open it in any browser on any device, complete the Atlassian login, and the terminal will continue automatically once the callback is received.

---

## Step 2 — Configure an LLM provider

```bash
ice model --add
```

```
  1. Ollama / LM Studio  (local, free — no API key needed)
  2. Nvidia NIM          (cloud, free tier at build.nvidia.com)
  3. OpenAI              (cloud, paid)
  4. Claude / Anthropic  (cloud, paid)
  5. Google Gemini       (cloud, free tier + paid)
  6. xAI Grok            (cloud, paid)
```

For each provider you choose a **text model** (for analysis) and an **image model** (for attachment vision enrichment and visual grounding). Type `none` at the image model prompt to disable vision and use OCR-only.

| Provider | Text default | Image default | Notes |
|---|---|---|---|
| Ollama | `llama3` | `llava` | Local, no API key |
| NVIDIA NIM | `deepseek-ai/deepseek-v3` | `meta/llama-3.2-11b-vision-instruct` | Free tier |
| OpenAI | `gpt-4o` | `gpt-4o` | |
| Anthropic | `claude-opus-4-5` | `claude-opus-4-5` | |
| Google Gemini | `gemini-1.5-pro` | `gemini-1.5-flash` | Free tier available |
| xAI Grok | `grok-beta` | `grok-vision-beta` | Vision model is a forward-looking default; ICE will offer OCR-only mode if it is not yet live on your account |

**Ollama:** Install from [ollama.ai](https://ollama.ai), pull models (`ollama pull llama3 && ollama pull llava`), then choose Ollama in ICE. No API key required.

### Google Gemini

Get a free API key at [aistudio.google.com](https://aistudio.google.com/apikey). The free tier includes 15 RPM and 1 million tokens/day on `gemini-1.5-flash`.

Vision enrichment, visual grounding, and large-document summarization all use the native `google-genai` SDK — no OpenAI bridge. Configure `gemini-1.5-flash` or `gemini-1.5-pro` as the image model for full vision support.

### Security — D-Lock encryption

ICE stores credentials in your OS keyring (Windows Credential Manager, macOS Keychain, GNOME Keyring). Some providers — particularly Jira Cloud OAuth — issue tokens longer than 512 bytes, which Windows Credential Manager cannot store.

When this happens, ICE automatically encrypts the token with AES-256-GCM before writing it to `~/.ice/config.json`. The encryption key (your Master Key) stays in the OS keyring. Your config file contains zero readable credentials, even for long tokens.

No action is required. If your OS keyring is unavailable (headless servers), ICE falls back to the existing `ICE_*` environment variable path and warns you at save time.

### Multiple LLM profiles

Run `ice model --add` again to add more profiles — each is saved under a name you choose (e.g. `personal`, `work`, `fast`). The first profile you create becomes the active default.

Use `ice status` to see all configured profiles. Use `--profile NAME` on `ice analyze` to pick a specific profile for a single request without changing your default. See **Step 4** for details.

---

## Hybrid Configuration

ICE supports mixing providers per profile — use a fast model for text analysis and a
specialist vision model for screenshots.

**Example: Anthropic text + NIM images**

```bash
ice model --add
# Profile name: work
# Text Intelligence: select Claude / Anthropic → claude-opus-4-5
# Visual Intelligence: select Different provider → NIM → meta/llama-3.2-11b-vision-instruct
```

**Example: Gemini text + xAI image**

```bash
ice model --add
# Profile name: frontier
# Text Intelligence: select Google Gemini → gemini-1.5-pro
# Visual Intelligence: select Different provider → xAI Grok → grok-vision-beta
```

**Check your setup:**

```bash
ice status
# Shows TEXT and IMAGE rows per profile with provider, model, and masked key
```

**Remove only the image channel:**

```bash
ice model --remove work --channel 2
```

---

## Step 3 — Check your setup

```bash
ice status
```

Example output:

```
 Connections
 ──────────────────────────────────────────
 Type   Domain                    Auth     Default
 jira   yourcompany.atlassian.net token    ✓

LLM profiles:
  personal  openai / gpt-4o  key: sk-1...abcd  (active)
  work      anthropic / claude-3-opus  key: sk-an...wxyz
```

---

## Step 4 — Analyze an issue

By URL:
```bash
ice analyze https://yourcompany.atlassian.net/browse/PROJ-123
```

By bare key (when you have exactly one connection configured):
```bash
ice analyze PROJ-123
```

ICE prints a JSON object to stdout:

```json
{
  "problem_summary": "Submit button is unresponsive on iOS Safari 17",
  "detailed_description": "...",
  "reproduction_steps": ["Open on iPhone", "Tap submit", "Nothing happens"],
  "expected_behavior": "Form submits and shows confirmation",
  "actual_behavior": "Button press has no visible effect",
  "acceptance_criteria": ["Button submits on iOS Safari 17", "..."],
  "impact": "All mobile users — blocking checkout flow",
  "priority": "High",
  "issue_type": "Bug",
  "confidence_score": 0.92,
  "completeness_score": 0.83,
  "missing_information": ["due_date"],
  "images": {}
}
```

**`completeness_score`** is computed deterministically by ICE after the LLM analysis — the LLM's own estimate is discarded. For Story, Task, and Epic issues that have spreadsheet attachments (`.xlsx`, `.xls`, `.csv`), the score is capped at `0.79` if the LLM did not produce a `### [TECHNICAL SCHEMA:]` or `### [TECHNICAL LOGIC:]` block. This signals that the structured data from the spreadsheet was not captured in the output.

**`missing_information`** is also computed deterministically. Possible values include:
- `"detailed_description"`, `"impact"` — required for all issue types
- `"reproduction_steps"`, `"expected_behavior"`, `"actual_behavior"` — Bug issues only
- `"acceptance_criteria"` — Story, Task, Epic issues only
- `"missing_schema"` — Story, Task, Epic issues with spreadsheet attachments where no schema block appears in the output
- `"due_date"` — when the ticket has no due date set

The `images` field contains Base64-encoded image attachments whenever image attachments are present on the ticket. It is `{}` only when the ticket has no images.

### Using a specific LLM profile

Use `--profile NAME` to run the analysis with a specific configured profile without changing your active default:

```bash
ice analyze PROJ-123 --profile work
ice analyze PROJ-456 --profile fast
```

The profile must already exist in your config (run `ice model --add` to add one, `ice status` to list them). ICE exits with an error if the name is not found:

```
Error: Profile 'typo' not found. Available profiles: fast, personal, work
```

`--profile` is **volatile** — it never modifies the active profile stored in your config.

### Debug mode

See every step — what was fetched, what attachments were processed, and the exact prompt sent to the LLM (rendered as a highlighted panel):

```bash
ice analyze PROJ-123 --debug
```

To show the full Python traceback when an error occurs, add `--traceback`:

```bash
ice analyze PROJ-123 --debug --traceback
```

---

## Error Handling

All ICE errors surface as a Rich panel with three fields:

```
╭─ ICE Error ────────────────────────────────────────────────────────╮
│ What: <the error message>                                          │
│ Why:  <what caused it>                                             │
│ How:  <what to do next>                                            │
╰────────────────────────────────────────────────────────────────────╯
```

Pass `--traceback` to append the full Python traceback below the panel. Raw Python tracebacks never appear without this flag.

Common error panels and their meaning:

| Error | Why | How |
|---|---|---|
| AuthError | Credentials rejected by the issue tracker | Run `ice connection --add` to re-enter credentials |
| IssueNotFound | Issue key doesn't exist or is inaccessible | Verify the key and your permissions |
| RateLimited | API rate limit hit | Wait briefly and retry |
| SourceUnavailable | Tracker returned 5xx or is unreachable | Check the tracker's status page |
| NoLLMError | No AI provider configured | Run `ice model --add` to configure one |
| ContextBuildError | LLM returned unparseable output | Use `--traceback` to see raw LLM response; try a different model |

---

## Using ICE with AI coding agents (MCP)

ICE registers itself as an MCP tool so Claude Code, Cursor, Codex, Windsurf, or Antigravity can call `analyze_issue` automatically when working on a ticket.

### MCP headless mode — no LLM required

When ICE is used via MCP and no LLM provider is configured, it returns a `RawIssueResponse` instead of a full analysis. This contains the raw issue data, all extracted attachment text (including formula annotations from Excel files), and Base64 images — ready for the host agent to analyze directly:

```json
{
  "mode": "raw",
  "issue_key": "PROJ-123",
  "summary": "...",
  "description": "...",
  "attachment_texts": { "report.pdf": "Extracted text...", "data.xlsx": "| Col A | Col B (Formula: =A2*1.18) |..." },
  "images": { "screenshot.png": "<base64>" },
  "note": "No LLM analysis performed — no API key configured. Raw issue data, digested documents, and raw images are provided for your direct analysis."
}
```

### Register ICE with your AI tool

```bash
ice mcp setup
```

ICE auto-detects which AI tools are installed and writes the config entry. Or target a specific tool:

```bash
ice mcp setup --host claude
ice mcp setup --host cursor
ice mcp setup --host codex
ice mcp setup --host windsurf
ice mcp setup --host antigravity
```

If a host is not detected on the current machine, ICE writes a fallback `.mcp.json` in the current directory and prints a notice.

**Config file locations:**

| Tool | Config written |
|---|---|
| Claude Code | `~/.claude/settings.json`|
| Cursor | `~/.cursor/mcp.json`|
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
| Codex | `~/.codex/config.toml` |
| Antigravity | `~/.gemini/antigravity/mcp_config.json` |

**Restart your AI tool** after running `ice mcp setup` — it reads config at startup.

### Use it

Ask your AI agent to work on an issue:

```
Implement the requirements from PROJ-123
```

The agent calls `analyze_issue("PROJ-123")` automatically, reads the structured context, and proceeds with the implementation using `acceptance_criteria` as its checklist.

### Selecting an LLM profile from MCP

The `analyze_issue` tool accepts an optional `profile` parameter. Pass it to select which configured LLM profile ICE uses for the analysis:

```json
{
  "issue_ref": "PROJ-123",
  "profile": "work"
}
```

The tool description returned by `ice mcp run` always lists the profiles currently available in your config so agents can choose the right one. When `profile` is omitted, ICE uses the active default profile.

### Print all config snippets

```bash
ice mcp config
```

### Remove ICE from a tool

```bash
ice mcp remove --host cursor
```

---

## MCP transport

ICE uses **stdio transport** — the AI tool spawns `ice mcp run` as a child process and communicates over stdin/stdout using MCP JSON-RPC. No background daemon, no open port, no service to manage.

---

## CI and headless environments

On servers and CI pipelines there is no GUI keyring daemon. ICE automatically falls back to environment variables. When a credential is stored as plaintext (keyring unavailable), ICE prints the exact variable name to set.

| Secret | Environment variable |
|---|---|
| Jira API token for `example.atlassian.net` | `ICE_JIRA_TOKEN_EXAMPLE_ATLASSIAN_NET` |
| LLM text-channel API key for profile `personal` | `ICE_LLM_TEXT_PERSONAL` |
| LLM image-channel API key for profile `personal` | `ICE_LLM_IMAGE_PERSONAL` |
| OAuth access token for `example.atlassian.net` | `ICE_OAUTH_ACCESS_EXAMPLE_ATLASSIAN_NET` |
| OAuth refresh token for `example.atlassian.net` | `ICE_OAUTH_REFRESH_EXAMPLE_ATLASSIAN_NET` |
| OAuth client secret for `example.atlassian.net` | `ICE_OAUTH_SECRET_EXAMPLE_ATLASSIAN_NET` |

**Naming rule:** take the internal account name, replace every non-alphanumeric character with `_`, uppercase it, and prepend `ICE_`. Examples:

| Account name (internal) | Environment variable |
|---|---|
| `jira_token:mycompany.atlassian.net` | `ICE_JIRA_TOKEN_MYCOMPANY_ATLASSIAN_NET` |
| `llm_text:my-fast` | `ICE_LLM_TEXT_MY_FAST` |
| `llm_image:my-fast` | `ICE_LLM_IMAGE_MY_FAST` |
| `oauth_access:mycompany.atlassian.net` | `ICE_OAUTH_ACCESS_MYCOMPANY_ATLASSIAN_NET` |
| `oauth_refresh:mycompany.atlassian.net` | `ICE_OAUTH_REFRESH_MYCOMPANY_ATLASSIAN_NET` |
| `oauth_secret:mycompany.atlassian.net` | `ICE_OAUTH_SECRET_MYCOMPANY_ATLASSIAN_NET` |

Set these in your shell profile or CI secrets manager — never inline in a command (that leaks them to shell history).

```bash
# ~/.bashrc or ~/.zshrc — not in a command
export ICE_JIRA_TOKEN_EXAMPLE_ATLASSIAN_NET="your_api_token"
export ICE_LLM_TEXT_PERSONAL="sk-..."
export ICE_LLM_IMAGE_PERSONAL="sk-..."   # only if image channel is configured
```

A config file (`~/.ice/config.json`) is still required — run `ice connection --add` once on a desktop machine, copy the config (without tokens) to the server, and supply tokens via env vars.

**Headless OAuth:** On a headless server with no browser, `ice connection --add` → OAuth PKCE prints the authorization URL to the terminal so you can complete login from any other device. See the [OAuth PKCE section](#oauth-pkce-for-sso-enforced-orgs) for details.

---

## All commands

```
ice connection --add     Connect to an issue tracker (API token or OAuth)
ice connection --remove  Remove a saved connection
ice model --add          Configure LLM provider / add a named LLM profile
ice model --active       Set the active LLM profile
ice analyze <url|key>    Fetch and analyze an issue ticket
  --profile NAME           Use a specific LLM profile for this request
                           (does not change the active default profile)
ice status               Show connections and LLM config
ice logout               Remove all saved credentials

ice mcp setup            Write ICE MCP entry to detected/specified AI tool
ice mcp remove           Remove ICE MCP entry from AI tool
ice mcp config           Print config snippets and file locations for all tools
ice mcp run              (Internal) Spawned by the AI tool — not run manually

Flags available on all commands:
  --debug      Show verbose step-by-step output (fetched fields, attachments, prompt sent to LLM)
  --traceback  Show the full Python traceback alongside the error panel. Combine with --debug for maximum detail.
  -v           Print version and exit
```

---

## Troubleshooting

**"Authentication failed. Check your email and API token."**
Your org may have disabled API tokens (common with SSO). Use OAuth PKCE (`ice connection --add` → option 2) or ask your IT admin to enable tokens at `admin.atlassian.com`.

**Token input appears to do nothing on Windows**
The token field is hidden. Use right-click to paste — Ctrl+V does not work in hidden input fields on Windows terminals.

**OAuth fails with 401 at token exchange**
You need both the **Client ID** and the **Client Secret** from your OAuth app at `developer.atlassian.com`. Both are required by Atlassian even with PKCE.

**`ice mcp setup` says "No known MCP host config directories detected"**
Use `--host` explicitly: `ice mcp setup --host cursor`. This happens when the tool's config directory does not exist yet.

**"Selected model does not support image input"**
Your configured `image_model` is text-only. Re-run `ice model --add` and either choose a vision-capable model (`llava` for Ollama, `gpt-4o` for OpenAI) or type `none` to disable vision — attachments will be processed with OCR only.

**LLM returns poor results**
Run `ice analyze <key> --debug` to see the raw prompt and response. More capable models (`gpt-4o`, `claude-3-opus`) give the best structured output.

**Tab completion not working on Windows**
Run in native PowerShell (not Git Bash): `ice --install-completion powershell`, then restart PowerShell.

**`images` field is populated**
ICE always attaches Base64 images to the output when the ticket has image attachments. A heuristic check still runs for log warnings (confidence below 0.8, very little OCR text, or a Bug ticket with no reproduction steps), but these no longer gate whether images are included. The images are always there for you or your agent to inspect directly.

**`completeness_score` is 0.79 for a Story or Task with a spreadsheet**
ICE caps the score at 0.79 when a Story, Task, or Epic has spreadsheet attachments but the LLM output contains no `### [TECHNICAL SCHEMA:]` or `### [TECHNICAL LOGIC:]` block. This means the structured data from the spreadsheet was not captured. Run `--debug` to inspect the full prompt and LLM response; switching to a more capable model (`gpt-4o`, `claude-3-opus`) typically resolves this.

**"Profile 'NAME' not found. Available profiles: ..."**
The `--profile` value must match a profile name in your config exactly. Run `ice status` to see configured profiles, or `ice model --add` to add a new one.

---

## Security

To report a vulnerability, please use [GitHub Security Advisories](https://github.com/althaf-space/ice/security/advisories/new) rather than opening a public issue. See [sceuirty.md](scurity.md) for the full policy, threat model, and response process.
