vink 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. vink-0.1.0/.env.example +24 -0
  2. vink-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +37 -0
  3. vink-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. vink-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
  5. vink-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  6. vink-0.1.0/.github/dependabot.yml +14 -0
  7. vink-0.1.0/.github/workflows/ci.yml +62 -0
  8. vink-0.1.0/.github/workflows/release.yml +50 -0
  9. vink-0.1.0/.gitignore +51 -0
  10. vink-0.1.0/.pre-commit-config.yaml +21 -0
  11. vink-0.1.0/.python-version +1 -0
  12. vink-0.1.0/CHANGELOG.md +29 -0
  13. vink-0.1.0/CODE_OF_CONDUCT.md +22 -0
  14. vink-0.1.0/CONTRIBUTING.md +111 -0
  15. vink-0.1.0/LICENSE +21 -0
  16. vink-0.1.0/PKG-INFO +236 -0
  17. vink-0.1.0/README.md +202 -0
  18. vink-0.1.0/SECURITY.md +30 -0
  19. vink-0.1.0/docs/adr/0001-ports-and-adapters.md +44 -0
  20. vink-0.1.0/docs/adr/0002-transcripts-without-data-api.md +58 -0
  21. vink-0.1.0/docs/adr/0003-separate-extraction-from-styling.md +47 -0
  22. vink-0.1.0/docs/architecture.md +112 -0
  23. vink-0.1.0/docs/configuration.md +54 -0
  24. vink-0.1.0/docs/mcp.md +90 -0
  25. vink-0.1.0/docs/releasing.md +69 -0
  26. vink-0.1.0/pyproject.toml +147 -0
  27. vink-0.1.0/src/vink/__init__.py +10 -0
  28. vink-0.1.0/src/vink/adapters/__init__.py +6 -0
  29. vink-0.1.0/src/vink/adapters/cache/__init__.py +6 -0
  30. vink-0.1.0/src/vink/adapters/cache/caching_source.py +74 -0
  31. vink-0.1.0/src/vink/adapters/cache/filesystem.py +50 -0
  32. vink-0.1.0/src/vink/adapters/cache/serialization.py +95 -0
  33. vink-0.1.0/src/vink/adapters/render/__init__.py +5 -0
  34. vink-0.1.0/src/vink/adapters/render/markdown.py +111 -0
  35. vink-0.1.0/src/vink/adapters/sinks/__init__.py +5 -0
  36. vink-0.1.0/src/vink/adapters/sinks/local.py +51 -0
  37. vink-0.1.0/src/vink/adapters/youtube/__init__.py +6 -0
  38. vink-0.1.0/src/vink/adapters/youtube/oembed.py +63 -0
  39. vink-0.1.0/src/vink/adapters/youtube/transcript_source.py +126 -0
  40. vink-0.1.0/src/vink/bootstrap.py +85 -0
  41. vink-0.1.0/src/vink/config.py +71 -0
  42. vink-0.1.0/src/vink/domain/__init__.py +56 -0
  43. vink-0.1.0/src/vink/domain/errors.py +86 -0
  44. vink-0.1.0/src/vink/domain/models.py +188 -0
  45. vink-0.1.0/src/vink/domain/video_ref.py +81 -0
  46. vink-0.1.0/src/vink/interfaces/__init__.py +6 -0
  47. vink-0.1.0/src/vink/interfaces/cli/__init__.py +5 -0
  48. vink-0.1.0/src/vink/interfaces/cli/app.py +187 -0
  49. vink-0.1.0/src/vink/interfaces/logging_setup.py +16 -0
  50. vink-0.1.0/src/vink/interfaces/mcp/__init__.py +5 -0
  51. vink-0.1.0/src/vink/interfaces/mcp/schemas.py +27 -0
  52. vink-0.1.0/src/vink/interfaces/mcp/server.py +180 -0
  53. vink-0.1.0/src/vink/ports/__init__.py +14 -0
  54. vink-0.1.0/src/vink/ports/cache.py +19 -0
  55. vink-0.1.0/src/vink/ports/metadata_source.py +19 -0
  56. vink-0.1.0/src/vink/ports/renderer.py +27 -0
  57. vink-0.1.0/src/vink/ports/sink.py +22 -0
  58. vink-0.1.0/src/vink/ports/transcript_source.py +22 -0
  59. vink-0.1.0/src/vink/processing/__init__.py +23 -0
  60. vink-0.1.0/src/vink/processing/chunking.py +49 -0
  61. vink-0.1.0/src/vink/processing/cleaning.py +47 -0
  62. vink-0.1.0/src/vink/processing/filenames.py +40 -0
  63. vink-0.1.0/src/vink/processing/paragraphs.py +105 -0
  64. vink-0.1.0/src/vink/processing/timecode.py +20 -0
  65. vink-0.1.0/src/vink/processing/track_selection.py +114 -0
  66. vink-0.1.0/src/vink/py.typed +0 -0
  67. vink-0.1.0/src/vink/services/__init__.py +10 -0
  68. vink-0.1.0/src/vink/services/export_service.py +69 -0
  69. vink-0.1.0/src/vink/services/transcript_service.py +102 -0
  70. vink-0.1.0/src/vink/styles/__init__.py +46 -0
  71. vink-0.1.0/src/vink/styles/clean-transcript.md +28 -0
  72. vink-0.1.0/src/vink/styles/detailed-notes.md +38 -0
  73. vink-0.1.0/tests/__init__.py +0 -0
  74. vink-0.1.0/tests/conftest.py +68 -0
  75. vink-0.1.0/tests/fakes.py +77 -0
  76. vink-0.1.0/tests/fixtures/expected/chunk.md +5 -0
  77. vink-0.1.0/tests/fixtures/expected/transcript.md +19 -0
  78. vink-0.1.0/tests/integration/__init__.py +0 -0
  79. vink-0.1.0/tests/integration/test_youtube_live.py +38 -0
  80. vink-0.1.0/tests/unit/__init__.py +0 -0
  81. vink-0.1.0/tests/unit/adapters/__init__.py +0 -0
  82. vink-0.1.0/tests/unit/adapters/test_cache.py +118 -0
  83. vink-0.1.0/tests/unit/adapters/test_local_sink.py +39 -0
  84. vink-0.1.0/tests/unit/adapters/test_markdown_renderer.py +66 -0
  85. vink-0.1.0/tests/unit/adapters/test_oembed.py +62 -0
  86. vink-0.1.0/tests/unit/adapters/test_youtube_transcript_source.py +160 -0
  87. vink-0.1.0/tests/unit/domain/__init__.py +0 -0
  88. vink-0.1.0/tests/unit/domain/test_models.py +59 -0
  89. vink-0.1.0/tests/unit/domain/test_video_ref.py +58 -0
  90. vink-0.1.0/tests/unit/interfaces/__init__.py +0 -0
  91. vink-0.1.0/tests/unit/interfaces/conftest.py +27 -0
  92. vink-0.1.0/tests/unit/interfaces/test_cli.py +117 -0
  93. vink-0.1.0/tests/unit/interfaces/test_mcp_server.py +133 -0
  94. vink-0.1.0/tests/unit/processing/__init__.py +0 -0
  95. vink-0.1.0/tests/unit/processing/test_chunking.py +54 -0
  96. vink-0.1.0/tests/unit/processing/test_cleaning.py +31 -0
  97. vink-0.1.0/tests/unit/processing/test_paragraphs.py +79 -0
  98. vink-0.1.0/tests/unit/processing/test_text_helpers.py +36 -0
  99. vink-0.1.0/tests/unit/processing/test_track_selection.py +87 -0
  100. vink-0.1.0/tests/unit/services/__init__.py +0 -0
  101. vink-0.1.0/tests/unit/services/test_export_service.py +55 -0
  102. vink-0.1.0/tests/unit/services/test_transcript_service.py +78 -0
  103. vink-0.1.0/tests/unit/test_config.py +49 -0
  104. vink-0.1.0/tests/unit/test_styles.py +20 -0
  105. vink-0.1.0/uv.lock +1775 -0
@@ -0,0 +1,24 @@
1
+ # Copy to .env and adjust. Every setting is optional.
2
+ # See docs/configuration.md for details.
3
+
4
+ # Preferred transcript languages, in order (comma-separated language codes).
5
+ VINK_LANGUAGES=en
6
+
7
+ # Fall back to YouTube's machine translation when no track matches.
8
+ VINK_ALLOW_TRANSLATION=true
9
+
10
+ # Where generated Markdown files are written.
11
+ VINK_OUTPUT_DIR=output
12
+
13
+ # Local transcript cache. Leave unset to use the platform's user cache directory.
14
+ # VINK_CACHE_DIR=
15
+ VINK_USE_CACHE=true
16
+
17
+ # Target length of one chunk, in seconds (used by the MCP get_chunk tool).
18
+ VINK_CHUNK_SECONDS=600
19
+
20
+ # Network timeout for metadata requests, in seconds.
21
+ VINK_HTTP_TIMEOUT=10
22
+
23
+ # DEBUG, INFO, WARNING, or ERROR.
24
+ VINK_LOG_LEVEL=WARNING
@@ -0,0 +1,37 @@
1
+ name: Bug report
2
+ description: Something does not work as expected
3
+ labels: [bug]
4
+ body:
5
+ - type: textarea
6
+ id: what-happened
7
+ attributes:
8
+ label: What happened?
9
+ description: What did you expect, and what happened instead?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: reproduce
14
+ attributes:
15
+ label: Steps to reproduce
16
+ description: The exact command or MCP tool call, and the video URL if it is public.
17
+ placeholder: uv run vink transcript https://youtu.be/... --lang hi
18
+ validations:
19
+ required: true
20
+ - type: textarea
21
+ id: output
22
+ attributes:
23
+ label: Error output
24
+ description: Run with `-v` and paste the full output.
25
+ render: text
26
+ - type: input
27
+ id: version
28
+ attributes:
29
+ label: vink version
30
+ placeholder: output of `vink --version`
31
+ validations:
32
+ required: true
33
+ - type: input
34
+ id: environment
35
+ attributes:
36
+ label: OS and Python version
37
+ placeholder: macOS 15, Python 3.12
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability
5
+ about: Please report security issues privately, not as public issues.
@@ -0,0 +1,28 @@
1
+ name: Feature request
2
+ description: Suggest a new capability, format, destination or note style
3
+ labels: [enhancement]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: Problem
9
+ description: What are you trying to do that vink does not support today?
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: proposal
14
+ attributes:
15
+ label: Proposed solution
16
+ description: How would you like it to work? Example commands or output help.
17
+ - type: dropdown
18
+ id: area
19
+ attributes:
20
+ label: Area
21
+ options:
22
+ - Transcript source / languages
23
+ - Output format
24
+ - Destination (Notion, Obsidian, ...)
25
+ - Note style / prompts
26
+ - CLI
27
+ - MCP server
28
+ - Other
@@ -0,0 +1,18 @@
1
+ ## What
2
+
3
+ <!-- What does this change do? -->
4
+
5
+ ## Why
6
+
7
+ <!-- What problem does it solve? Link the issue: Closes #123 -->
8
+
9
+ ## How to test
10
+
11
+ <!-- Commands or steps a reviewer can run. -->
12
+
13
+ ## Checklist
14
+
15
+ - [ ] `ruff format`, `ruff check`, `mypy` and `pytest` pass locally
16
+ - [ ] Tests added or updated for new behavior
17
+ - [ ] `CHANGELOG.md` updated under `[Unreleased]` (if user-visible)
18
+ - [ ] Docs updated (README / `docs/`) for new options or behavior
@@ -0,0 +1,14 @@
1
+ version: 2
2
+ updates:
3
+ # youtube-transcript-api tracks YouTube internals; stay current.
4
+ - package-ecosystem: uv
5
+ directory: /
6
+ schedule:
7
+ interval: weekly
8
+ groups:
9
+ dev-tools:
10
+ dependency-type: development
11
+ - package-ecosystem: github-actions
12
+ directory: /
13
+ schedule:
14
+ interval: monthly
@@ -0,0 +1,62 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ schedule:
8
+ # Weekly run of the live YouTube tests to catch upstream breakage early.
9
+ - cron: "0 6 * * 1"
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: ${{ github.workflow }}-${{ github.ref }}
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ checks:
21
+ name: Lint and type check
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
26
+ - run: uv sync --locked
27
+ - run: uv run ruff format --check .
28
+ - run: uv run ruff check .
29
+ - run: uv run mypy
30
+
31
+ test:
32
+ name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
33
+ runs-on: ${{ matrix.os }}
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ os: [ubuntu-latest]
38
+ python-version: ["3.11", "3.12", "3.13"]
39
+ include:
40
+ - os: macos-latest
41
+ python-version: "3.12"
42
+ - os: windows-latest
43
+ python-version: "3.12"
44
+ steps:
45
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
47
+ with:
48
+ python-version: ${{ matrix.python-version }}
49
+ - run: uv sync --locked
50
+ - run: uv run pytest --cov --cov-report=term-missing
51
+
52
+ integration:
53
+ name: Live YouTube tests
54
+ if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
55
+ runs-on: ubuntu-latest
56
+ # Cloud runner IPs are sometimes blocked by YouTube; don't fail the workflow for that.
57
+ continue-on-error: true
58
+ steps:
59
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
60
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
61
+ - run: uv sync --locked
62
+ - run: uv run pytest -m integration
@@ -0,0 +1,50 @@
1
+ name: Release
2
+
3
+ # Publishes to PyPI when a version tag (e.g. v0.1.0) is pushed.
4
+ # Uses PyPI trusted publishing (OIDC): no API token is stored in GitHub.
5
+ # One-time setup is described in docs/releasing.md.
6
+
7
+ on:
8
+ push:
9
+ tags: ["v*"]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ name: Build distributions
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
21
+ - name: Check tag matches package version
22
+ run: |
23
+ version=$(uv version --short)
24
+ if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
25
+ echo "Tag ${GITHUB_REF_NAME} does not match pyproject version ${version}" >&2
26
+ exit 1
27
+ fi
28
+ - run: uv sync --locked
29
+ - run: uv run pytest
30
+ - run: uv build
31
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
32
+ with:
33
+ name: dist
34
+ path: dist/
35
+
36
+ publish:
37
+ name: Publish to PyPI
38
+ needs: build
39
+ runs-on: ubuntu-latest
40
+ environment:
41
+ name: pypi
42
+ url: https://pypi.org/project/vink/
43
+ permissions:
44
+ id-token: write # required for trusted publishing
45
+ steps:
46
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
vink-0.1.0/.gitignore ADDED
@@ -0,0 +1,51 @@
1
+ # ---------------------------------------------------------------------------
2
+ # Internal
3
+ # ---------------------------------------------------------------------------
4
+ # Team engineering standards
5
+ standards/
6
+
7
+ # ---------------------------------------------------------------------------
8
+ # Python
9
+ # ---------------------------------------------------------------------------
10
+ __pycache__/
11
+ *.py[cod]
12
+ *.so
13
+ *.egg-info/
14
+ .eggs/
15
+ build/
16
+ dist/
17
+ wheels/
18
+
19
+ # Virtual environments
20
+ .venv/
21
+ venv/
22
+ env/
23
+
24
+ # Tooling caches
25
+ .mypy_cache/
26
+ .ruff_cache/
27
+ .pytest_cache/
28
+ .coverage
29
+ .coverage.*
30
+ htmlcov/
31
+ coverage.xml
32
+
33
+ # ---------------------------------------------------------------------------
34
+ # Project runtime data
35
+ # ---------------------------------------------------------------------------
36
+ # Local transcript cache and generated output
37
+ .vink-cache/
38
+ output/
39
+
40
+ # Secrets and local config
41
+ .env
42
+ .env.*
43
+ !.env.example
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Editors / OS
47
+ # ---------------------------------------------------------------------------
48
+ .vscode/
49
+ .idea/
50
+ *.swp
51
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ # Runs the same checks as CI before each commit.
2
+ # Install once with: uv run pre-commit install
3
+ repos:
4
+ - repo: local
5
+ hooks:
6
+ - id: ruff-format
7
+ name: ruff format
8
+ entry: uv run ruff format
9
+ language: system
10
+ types: [python]
11
+ - id: ruff-check
12
+ name: ruff check
13
+ entry: uv run ruff check --fix
14
+ language: system
15
+ types: [python]
16
+ - id: mypy
17
+ name: mypy
18
+ entry: uv run mypy
19
+ language: system
20
+ types: [python]
21
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-11-14
11
+
12
+ ### Added
13
+
14
+ - `vink transcript` command: fetch a YouTube transcript and save it as Markdown
15
+ with YAML front matter and clickable timestamps, or print it with `--stdout`.
16
+ - `vink languages` command: list the caption tracks available for a video.
17
+ - Language preferences with fallback (`--lang hi,en`), the special value
18
+ `original` for the spoken language, and optional YouTube machine translation.
19
+ - Cleaning of caption text into readable paragraphs: sound cues removed,
20
+ fragments merged, speaker changes and pauses respected.
21
+ - Local transcript cache.
22
+ - MCP server (`vink mcp`) with tools `list_languages`, `get_video_info`,
23
+ `get_chunk`, `get_transcript`, `save_transcript` and `save_notes`, and a
24
+ `make_notes` prompt with `detailed-notes` and `clean-transcript` styles.
25
+ - Configuration through `VINK_*` environment variables or a `.env` file.
26
+ - Distribution on PyPI (`uv tool install vink`, `uvx vink mcp`).
27
+
28
+ [Unreleased]: https://github.com/navinbhagat322/youtube-vink/compare/v0.1.0...HEAD
29
+ [0.1.0]: https://github.com/navinbhagat322/youtube-vink/releases/tag/v0.1.0
@@ -0,0 +1,22 @@
1
+ # Code of Conduct
2
+
3
+ This project adopts the
4
+ [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
5
+ as its code of conduct.
6
+
7
+ In short: be respectful, assume good intent, welcome newcomers, and keep
8
+ discussion focused on the work. Harassment, personal attacks and
9
+ discriminatory language are not tolerated in any project space: issues, pull
10
+ requests, discussions or chat.
11
+
12
+ ## Reporting
13
+
14
+ If you experience or witness unacceptable behavior, contact the maintainers
15
+ privately through the contact listed on the repository's GitHub profile, or by
16
+ opening a private security advisory if no other channel is available. All
17
+ reports are reviewed promptly and handled confidentially.
18
+
19
+ Maintainers may remove, edit or reject contributions that violate this code of
20
+ conduct, and may temporarily or permanently ban contributors for repeated or
21
+ serious violations, following the enforcement guidelines of the Contributor
22
+ Covenant.
@@ -0,0 +1,111 @@
1
+ # Contributing to vink
2
+
3
+ Thanks for helping. This guide covers setup, the development workflow, and
4
+ the conventions every change follows.
5
+
6
+ ## Development setup
7
+
8
+ You need Python 3.11+ and [uv](https://docs.astral.sh/uv/).
9
+
10
+ ```bash
11
+ git clone https://github.com/navinbhagat322/youtube-vink.git
12
+ cd youtube-vink
13
+ uv sync # creates .venv with runtime + dev dependencies
14
+ uv run pre-commit install # runs format, lint and type checks before each commit
15
+ ```
16
+
17
+ ## Running checks
18
+
19
+ Run the same checks CI runs:
20
+
21
+ ```bash
22
+ uv run ruff format --check .
23
+ uv run ruff check .
24
+ uv run mypy
25
+ uv run pytest --cov
26
+ ```
27
+
28
+ Tests that call real YouTube are excluded by default. Run them with:
29
+
30
+ ```bash
31
+ uv run pytest -m integration
32
+ ```
33
+
34
+ ## Project layout
35
+
36
+ ```
37
+ src/vink/
38
+ ├── domain/ # immutable models and errors (no I/O, no third-party imports)
39
+ ├── ports/ # Protocol interfaces the core depends on
40
+ ├── processing/ # pure functions: track selection, cleaning, paragraphs, chunks
41
+ ├── services/ # use cases that orchestrate ports and processing
42
+ ├── adapters/ # implementations: YouTube, cache, Markdown, local files
43
+ ├── interfaces/ # entry points: CLI and MCP server
44
+ ├── styles/ # note-style prompt templates (Markdown files)
45
+ ├── bootstrap.py # wires adapters into services
46
+ └── config.py # typed settings
47
+ ```
48
+
49
+ Read [docs/architecture.md](docs/architecture.md) before making structural
50
+ changes. The key rule is that dependencies point inward: services depend on
51
+ ports, never on adapters.
52
+
53
+ ## Common changes
54
+
55
+ **Add an output format** (e.g. PDF): implement the `Renderer` protocol in
56
+ `src/vink/adapters/render/`, register it in `bootstrap.py`, and add a golden
57
+ file test in `tests/unit/adapters/`.
58
+
59
+ **Add a destination** (e.g. Notion): implement the `Sink` protocol in
60
+ `src/vink/adapters/sinks/` and wire it in `bootstrap.py`. Put heavy
61
+ dependencies in an optional extra (`vink[notion]`) and import them inside the
62
+ adapter.
63
+
64
+ **Add a note style**: add a Markdown file to `src/vink/styles/`. It is
65
+ discovered automatically. Use `{output_language}` where the target language
66
+ belongs.
67
+
68
+ ## Conventions
69
+
70
+ - **Style:** PEP 8 via `ruff format`, line length 100, Google-style docstrings
71
+ on all public code, full type hints (`mypy --strict`).
72
+ - **Errors:** raise errors from `vink.domain.errors`. Adapters convert library
73
+ exceptions with `raise ... from exc`. Messages should tell the user what to
74
+ do next.
75
+ - **Logging:** `logging.getLogger(__name__)`, never `print()`. Nothing may
76
+ write to stdout from the MCP server.
77
+ - **Tests:** unit tests never touch the network. Use the fakes in
78
+ `tests/fakes.py`. Every bug fix starts with a failing test.
79
+
80
+ ## Commits and pull requests
81
+
82
+ We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):
83
+
84
+ ```
85
+ feat(youtube): fall back to auto-generated captions
86
+ fix(processing): keep Devanagari punctuation when merging segments
87
+ docs: explain MCP setup on Windows
88
+ ```
89
+
90
+ Scopes follow the architecture: `domain`, `processing`, `services`, `youtube`,
91
+ `cache`, `render`, `sinks`, `cli`, `mcp`, `config`, `deps`.
92
+
93
+ Before opening a pull request:
94
+
95
+ - [ ] All checks above pass.
96
+ - [ ] New behavior has tests.
97
+ - [ ] User-visible changes are noted under `[Unreleased]` in `CHANGELOG.md`.
98
+ - [ ] Docs are updated for new options or behavior.
99
+
100
+ Keep pull requests small and focused. They are squash-merged, so the PR title
101
+ becomes the commit message.
102
+
103
+ ## Reporting bugs
104
+
105
+ Open an issue with the video URL (if public), the command you ran, the full
106
+ error output, and `vink --version`. For security issues, see
107
+ [SECURITY.md](SECURITY.md).
108
+
109
+ ## Code of conduct
110
+
111
+ This project follows the [Code of Conduct](CODE_OF_CONDUCT.md).
vink-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vink contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.