Metadata-Version: 2.4
Name: standup-bot
Version: 0.2.6
Summary: Generate daily standup summaries from your git history using local or free cloud LLMs.
Author: SemTiOne
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ollama<1.0.0,>=0.1.7
Requires-Dist: groq<2.0.0,>=0.4.0
Requires-Dist: gitpython<4.0.0,>=3.1.40
Requires-Dist: pyperclip<2.0.0,>=1.8.2
Requires-Dist: rich<16.0.0,>=13.0.0
Requires-Dist: requests<3.0.0,>=2.31.0
Requires-Dist: keyring<26.0.0,>=24.0.0
Requires-Dist: cryptography<50.0.0,>=41.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: ruff<1.0.0,>=0.4.4; extra == "dev"
Requires-Dist: mypy<3.0.0,>=1.10.0; extra == "dev"
Requires-Dist: types-requests>=2.31.0; extra == "dev"
Requires-Dist: bandit<2.0.0,>=1.7.8; extra == "dev"
Requires-Dist: pip-audit<3.0.0,>=2.7.3; extra == "dev"
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

﻿# StandupBot

Generate standup updates from recent git activity with a local Ollama model or Groq's free cloud tier.

![Tests](https://github.com/SemTiOne/standup-bot/actions/workflows/tests.yml/badge.svg)
[![codecov](https://codecov.io/gh/SemTiOne/standup-bot/graph/badge.svg)](https://codecov.io/gh/SemTiOne/standup-bot)
![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
![License: MIT](https://img.shields.io/badge/license-MIT-green)

## What is new (unreleased)

Since 0.2.4: a full security/correctness audit (private-IP redaction, a config-mutation bug that could leak an API key across process calls, a broken Linux systemd unit, and a few other fixes), plus a follow-up fix for missing secret-detection patterns (GitHub tokens, AWS keys, Slack tokens, LLM API keys, credentialed URIs) reported via #2. See `CHANGELOG.md` for the full list.

## Quick Start

```bash
# Install dependencies
pip install -e .

# Configure StandupBot
standup --setup

# Generate a standup
standup
```

For Ollama, install and pull a model first:

```bash
ollama pull llama3
```

## Providers

| Provider | Cost | Privacy | Best for |
|---|---|---|---|
| Ollama | Free | Fully local | Private, offline workflows |
| Groq | Free tier | Cloud | Fast generation without local model setup |

Groq API keys should be supplied through `GROQ_API_KEY` when possible.

## Core Commands

```bash
# Standard generation
standup
standup --hours 48
standup --week
standup --provider groq

# Output options
standup --copy
standup --slack
standup --raw
standup --template slack
standup --verbose

# Cache and filtering controls
standup --no-cache
standup --no-filter

# Maintenance
standup doctor
standup usage
standup logs
standup logs --tail 50
standup logs --clear
standup models
standup templates
standup history
standup history --limit 25
standup history --clear
standup history --clear --days 30
standup warm-up
standup warm-up --install-startup
standup warm-up --uninstall-startup
standup --maintenance
```

## Templates

Built-in templates:

- `default`
- `slack`
- `minimal`
- `detailed`
- `jira`

You can also define custom templates in config. StandupBot extracts `yesterday`, `today`, and `blockers` from the LLM output, then renders the final format with these variables:

- `{yesterday}`
- `{today}`
- `{blockers}`
- `{date}`
- `{time}`
- `{commit_count}`
- `{repos}`
- `{provider}`
- `{author_email}`

## Config

StandupBot reads `~/.standup.json`.

```json
{
  "repos": [
    "/path/to/repo1",
    "/path/to/repo2"
  ],
  "author_email": "you@example.com",
  "hours_lookback": 24,
  "tone": "casual",
  "slack_webhook_url": "",
  "provider": {
    "name": "ollama",
    "ollama": {
      "base_url": "http://localhost:11434",
      "model": "llama3"
    },
    "groq": {
      "api_key": "",
      "model": "llama-3.1-8b-instant"
    }
  },
  "rate_limit": {
    "cooldown_minutes": 30,
    "max_calls_per_day": 10,
    "enabled": true
  },
  "quality": {
    "enabled": true,
    "min_score": 0,
    "show_breakdown": false
  },
  "noise_filter_enabled": true,
  "template": "default",
  "custom_templates": {
    "my_format": "Done: {yesterday} | Doing: {today} | Help needed: {blockers}"
  },
  "auto_warm_up": false
}
```

## Caching and History

Every generated standup is stored locally in `~/.standup_history.db`.

- Cache keys are based on a SHA256 fingerprint of sorted commit hashes.
- Cache reuse is limited to the same day, tone, and provider.
- The database stores standup text, provider metadata, repo names, lookback hours, and quality score.
- Raw commit messages are not stored in the database.

## Quality Scoring

After generation, StandupBot can score the standup from 0-100 and show a colored badge.

- Green: 80+
- Yellow: 60-79
- Red: below 60

When `quality.min_score` is above zero, StandupBot retries low-quality outputs up to two times with refined guidance.

## Warm-Up

Use `standup warm-up` to pre-load the configured model before your first real run.

- Ollama: sends a minimal warm-up request to keep the selected model ready in memory.
- Groq: runs a lightweight availability ping.
- `auto_warm_up` can trigger a silent warm-up when the model has not been used recently.

## Security

StandupBot treats config, git metadata, templates, provider responses, and local storage as hostile inputs until proven otherwise.

- `~/.standup.json`, `~/.standup_usage.json`, `~/.standup_history.db`, and `~/.standup.log` use restricted permissions on Unix/macOS.
- Commit messages are scanned for common secret formats — passwords/tokens/API keys, private IPs, internal hostnames, bearer tokens, GitHub PATs, LLM provider keys, AWS access keys, Slack tokens, and credentialed URIs — and redacted before they reach a prompt, storage, or the terminal.
- Repo paths go through explicit path-safety checks to block traversal tricks, network paths, and unsafe symlinks.
- Commit messages and LLM responses are length-capped before they reach prompts, storage, or terminal rendering.
- Custom templates only substitute a fixed allowlist of variables and reject Python-style format syntax.
- All history database queries are parameterized, and stored standup text is sanitized before persistence.
- User-facing exception messages are sanitized so file paths, emails, and API-key-shaped values are not echoed back to the terminal.
- `standup doctor` now checks log health, DB size, schema version, WAL mode, file permissions, and full config validity.

## Development

```bash
python -m pytest tests/ -q
```

If your environment restricts Python temp directories or `__pycache__` writes, set a writable `--basetemp` or `PYTHONDONTWRITEBYTECODE=1` while testing.

## License

MIT
