Skip to main content

Python CLI for creating concise briefs from text, files, URLs, YouTube videos, and PDFs.

Project description

Briefly AI

Python CLI for creating concise briefs from text, files, URLs, YouTube videos, and PDFs.

Supported Inputs

  • Plain text
  • Local text/Markdown files
  • Local and remote PDFs
  • Web pages
  • YouTube videos with captions
  • YouTube videos without captions via Groq Whisper fallback
  • Stdin

Quickstart

1. Clone the repo

git clone https://github.com/Rahat-Kabir/briefly-ai
cd briefly-ai

2. Install dependencies

uv sync

On Windows, if uv cache or hardlink warnings appear, use the project-local cache and copy mode:

$env:UV_CACHE_DIR='.uv-cache'
$env:UV_LINK_MODE='copy'
uv sync

3. Set your API key

For OpenAI models, set OPENAI_API_KEY:

$env:OPENAI_API_KEY='your_openai_api_key'

This sets the key for the current PowerShell session. To save it permanently for your Windows user:

[Environment]::SetEnvironmentVariable('OPENAI_API_KEY', 'your_openai_api_key', 'User')

Open a new terminal after setting it permanently.

Other providers use their own environment variables, such as ANTHROPIC_API_KEY, GEMINI_API_KEY, or other provider keys supported by LiteLLM.

Common provider keys:

$env:OPENAI_API_KEY='your_openai_api_key'
$env:ANTHROPIC_API_KEY='your_anthropic_api_key'
$env:GEMINI_API_KEY='your_gemini_api_key'
$env:GROQ_API_KEY='your_groq_api_key'
$env:OPENROUTER_API_KEY='your_openrouter_api_key'

Example model ids:

uv run briefly "Hello" --model openai/gpt-4o-mini
uv run briefly "Hello" --model anthropic/claude-sonnet-4-5
uv run briefly "Hello" --model groq/llama-3.1-8b-instant
uv run briefly "Hello" --model openrouter/openai/gpt-4o-mini

4. Set a default model

uv run briefly config init --model <model-id>

Example:

uv run briefly config init --model openai/gpt-4o-mini

The example above uses an OpenAI model, so it requires OPENAI_API_KEY.

5. Run your first brief

uv run briefly "Briefly turns long content into concise briefs."

Or pass a model for one command:

uv run briefly "Briefly turns long content into concise briefs." --model openai/gpt-4o-mini

Usage

Briefly needs an LLM model for briefing. You can either save a default model once, or pass --model on each command.

Set a default model

uv run briefly config init --model <model-id>

This writes ~/.briefly/config.json. After that, regular commands can omit --model:

uv run briefly "Paste or type any text here."
uv run briefly notes.txt
uv run briefly https://example.com

To use a different model for one command:

uv run briefly notes.txt --model <model-id>

One valid model id is openai/gpt-4o-mini; use any LiteLLM-supported model id that matches your API keys.

You can also define named model presets in ~/.briefly/config.json:

{
  "model": "provider/model-id",
  "models": {
    "fast": "provider/model-id"
  }
}

Then run:

uv run briefly notes.txt --model fast

config init refuses to overwrite an existing config unless --force is passed.

Common examples

uv run briefly "Paste or type any text here."
uv run briefly "Long article text..." --length short
uv run briefly "Long article text..." --length long
uv run briefly "Meeting notes..." --brief-type action
uv run briefly https://example.com

Current state: early CLI foundation. Briefly can resolve text/file/stdin input, print extracted text, and generate length-controlled text briefs through LiteLLM. Brief types shape the prompt for standard, executive, action, study, and decision-focused output. Config-backed model selection, trafilatura-backed HTML URL briefing, YouTube caption briefing, Groq Whisper fallback, token streaming, structured JSON output, and local cache are available. YouTube transcript timestamps are available in extract and briefing input.

Brief a file

uv run briefly notes.txt
uv run briefly paper.pdf
uv run briefly paper.pdf --extract
uv run briefly https://example.com/paper.pdf --extract

Local and remote PDF input uses pdfplumber; the title comes from PDF metadata when present, otherwise the filename or URL. Scanned/image-only PDFs raise a clear error.

Brief a YouTube video

uv run briefly https://youtu.be/v4F1gFy-hqg
uv run briefly https://www.youtube.com/watch?v=v4F1gFy-hqg --extract
uv run briefly https://www.youtube.com/watch?v=v4F1gFy-hqg --extract --timestamps
uv run briefly https://youtu.be/v4F1gFy-hqg --extract --json

Briefly fetches the video's captions through YouTube's Android InnerTube API. Works for youtube.com, youtu.be, /shorts, /embed, and /live URLs. Use --timestamps to print transcript lines with [m:ss] or [h:mm:ss] timestamps.

If YouTube captions are missing, Briefly can fall back to Groq Whisper. Install yt-dlp and set GROQ_API_KEY:

$env:GROQ_API_KEY='your_groq_api_key'
uv run briefly "https://youtu.be/example" --extract

Extract mode

Extract mode resolves and prints input without an LLM call.

uv run briefly "Some text" --extract
uv run briefly README.md --extract
uv run briefly https://example.com --extract
uv run briefly https://example.com --extract --json
echo "Piped text" | uv run briefly - --extract

URL extraction uses trafilatura first, with BeautifulSoup fallback. Use --output-format markdown to preserve Markdown-style headings and links.

Brief types

--brief-type changes the purpose of the brief while --length still controls size.

uv run briefly report.pdf --brief-type executive
uv run briefly meeting.txt --brief-type action
uv run briefly article.md --brief-type study
uv run briefly proposal.pdf --brief-type decision

Available types:

Type Purpose
standard General concise brief; this is the default and preserves existing behavior
executive Business or leadership brief focused on takeaways, impact, risks, and attention areas
action Decisions, action items, owners, deadlines, blockers, and follow-ups without inventing missing details
study Core concepts, definitions, examples, and review points for learning
decision Options, tradeoffs, risks, supported recommendation, and missing evidence

Options

uv run briefly --help
Flag Description
--extract Print resolved input without briefing
--model TEXT LLM model id or configured model preset
--length TEXT Brief length: short, medium, long, xl, xxl, or a char count like 500
--brief-type TEXT Brief type: standard, executive, action, study, or decision
--output-format TEXT Output format: text or markdown
--max-input-chars TEXT Truncate input to this many characters, e.g. 50k
--max-tokens TEXT Maximum output tokens
--stream TEXT Streaming mode: on, off, or auto (TTY)
--json Print structured JSON; streaming is disabled in JSON mode
--timestamps Include YouTube transcript timestamps when available
--skip-cache Skip cache reads and writes

Cache

Briefly stores URL extraction and summary results in ~/.briefly/cache.sqlite.

uv run briefly cache stats
uv run briefly cache clear
uv run briefly https://example.com --skip-cache

Default TTLs: URL extraction cache expires after 7 days; summary cache expires after 30 days. Override both with:

{
  "cache": {
    "ttlDays": 14
  }
}

Development

uv run pytest
uv run ruff check

On Windows, use the repo-local uv cache if the default cache fails:

$env:UV_CACHE_DIR='.uv-cache'; uv run pytest
$env:UV_CACHE_DIR='.uv-cache'; uv run ruff check

Project Structure

briefly-ai/
|-- pyproject.toml
|-- uv.lock
|-- AGENTS.md
|-- CLAUDE.md
|-- LICENSE
|-- README.md
|
|-- docs/
|   |-- RELEASE_v0.2.md
|   |-- progress.md
|   |-- tech_spec.md
|   `-- testing.md
|
|-- packages/
|   |-- briefly-core/
|   |   |-- pyproject.toml
|   |   `-- src/briefly_core/
|   |       |-- __init__.py
|   |       |-- briefing.py
|   |       |-- cache.py
|   |       |-- content.py
|   |       |-- config.py
|   |       |-- flags.py
|   |       |-- input.py
|   |       |-- llm.py
|   |       |-- pdf.py
|   |       `-- youtube.py
|   |
|   `-- briefly-cli/
|       |-- pyproject.toml
|       `-- src/briefly_cli/
|           |-- __init__.py
|           |-- main.py
|           `-- commands/
|               |-- __init__.py
|               |-- brief.py
|               |-- cache.py
|               |-- config.py
|               |-- daemon.py
|               |-- slides.py
|               `-- transcriber.py
|
|-- tests/
|   |-- cli/
|   |   |-- conftest.py
|   |   |-- test_cache_cli.py
|   |   |-- test_cache_commands.py
|   |   |-- test_config_init.py
|   |   |-- test_config_model.py
|   |   |-- test_extract.py
|   |   |-- test_help.py
|   |   |-- test_json_output.py
|   |   |-- test_pdf_cli.py
|   |   |-- test_stream.py
|   |   `-- test_youtube_cli.py
|   `-- core/
|       |-- test_briefing.py
|       |-- test_cache.py
|       |-- test_content.py
|       |-- test_config.py
|       |-- test_flags.py
|       |-- test_input.py
|       |-- test_llm.py
|       |-- test_pdf.py
|       `-- test_youtube.py

Docs: tech spec, progress, testing.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

briefly_ai-0.1.0.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

briefly_ai-0.1.0-py3-none-any.whl (31.7 kB view details)

Uploaded Python 3

File details

Details for the file briefly_ai-0.1.0.tar.gz.

File metadata

  • Download URL: briefly_ai-0.1.0.tar.gz
  • Upload date:
  • Size: 24.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for briefly_ai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d534ca2db65138f8deeb8192e6ef8aaa826142135c5163ff85d1b12a28bb0080
MD5 f4d4ee6f90e8964bbaf1fe0e20b034d3
BLAKE2b-256 786cf23bae366adf149e17d60d5e2d015ae8cccae90a0e5aeafd96915e89df3b

See more details on using hashes here.

File details

Details for the file briefly_ai-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: briefly_ai-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for briefly_ai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 232e0bbe87595702a5aef233ead6c1ae02e3d2cf9aa5e5e0996ddbd1ecae5558
MD5 9e00f4e212cb1b25cc0ed300d91a1491
BLAKE2b-256 4e66e01540a71d39401fb0f318e0ec69c3f2ba1e56a323708c29290e04a80f38

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page