pyproject.toml Configuration

Nib reads project settings from the [tool.nib] section of pyproject.toml. This lets you define build defaults so that nib run and nib build work without any flags.

Sections overview

Section Purpose
[tool.nib] Entry point and top-level settings
[tool.nib.build] Build configuration (name, icon, version, etc.)
[tool.nib.build.plist] Info.plist options (category, dock icon, URL schemes, etc.)
[tool.nib.build.plist.usage] Privacy permission descriptions
[tool.nib.build.plist.custom] Arbitrary Info.plist keys
[[tool.nib.build.plist.document_types]] File type associations

[tool.nib]

Top-level project settings.

Key Type Description
entry string Path to the entry point script. Used by nib run and nib build when no script argument is given. Default: src/main.py
[tool.nib]
entry = "src/main.py"

[tool.nib.build]

Build configuration. All keys are optional. Sensible defaults are used when omitted.

Key Type Default Description
name string Project name App display name shown in the menu bar and Finder
identifier string com.nib.<name> macOS bundle identifier
version string 1.0.0 App version string (CFBundleShortVersionString)
icon string src/assets/icon.png Path to icon file (.icns or .png: PNG is auto-converted)
min_macos string 14.0 Minimum macOS version required to run the app (the runtime needs 14.0)
exclude list[string] [] Files and directories under the script's directory not to copy, on top of tests, scripts, dist, build, .venv, .git
extra_deps list[string] [] Additional pip packages to include if auto-detection misses them
launch_at_login bool false Register the app to start automatically at login (requires signed app)
arch string Current machine Target architecture: arm64 or x86_64
python_version string Python running nib Python major.minor to bundle, for example "3.13". Bytecode is compiled by the bundled interpreter, so it need not match the host
native bool false Compile Python to native .so via Cython
obfuscate bool false Strip source paths and line numbers from .pyc bytecode
optimize bool false Optimize bundle size (strip binaries, prune stdlib)
sign_identity string - (ad hoc) codesign identity, e.g. Developer ID Application: Name (TEAMID)
[tool.nib.build]
name = "Weather Widget"
identifier = "com.example.weatherwidget"
version = "2.1.0"
icon = "src/assets/icon.png"
min_macos = "14.0"
extra_deps = ["requests", "pillow"]
launch_at_login = true

Dependency detection

If your pyproject.toml has a [project].dependencies list, Nib uses those packages directly instead of auto-detecting imports via AST analysis. The nib package itself is automatically excluded.


[tool.nib.build.plist]

Controls values written to the app's Info.plist. These affect how macOS treats your application.

Key Type Default Description
copyright string none Human-readable copyright string
category string none App Store category (e.g., public.app-category.utilities)
notification_style string none Notification display style: banner, alert, or none
dock_icon bool false Show the app in the Dock (default: menu bar only)
background_only bool false Run as a background daemon with no UI
build_number string Same as version Internal build number (CFBundleVersion), separate from the display version
allow_http bool or list[string] false Allow insecure HTTP connections. true allows all domains; a list allows specific domains only
url_schemes list[string] none Register custom URL schemes (e.g., ["myapp"] for myapp://)
[tool.nib.build.plist]
copyright = "Copyright 2025 Your Name"
category = "public.app-category.utilities"
notification_style = "banner"
dock_icon = false
build_number = "42"
url_schemes = ["myapp"]

allow_http

By default, macOS enforces App Transport Security (HTTPS only). You can relax this globally or per-domain:

# Allow HTTP to all domains
allow_http = true

# Allow HTTP to specific domains only
allow_http = ["api.example.com", "cdn.example.com"]

Document type associations

Register your app as a handler for specific file types using TOML array-of-tables syntax.

Key Type Description
name string Display name for the document type
extensions list[string] File extensions to associate (without the dot)
role string Viewer or Editor
[[tool.nib.build.plist.document_types]]
name = "Text Document"
extensions = ["txt", "md"]
role = "Viewer"

[[tool.nib.build.plist.document_types]]
name = "JSON File"
extensions = ["json"]
role = "Editor"

[tool.nib.build.plist.usage]

Privacy permission descriptions. macOS requires a usage string for each protected resource your app accesses. If the user's code references Permission.CAMERA or Permission.MICROPHONE, Nib auto-detects them with generic descriptions. But you should provide your own.

Key Plist key Description
camera NSCameraUsageDescription Camera access
microphone NSMicrophoneUsageDescription Microphone access
location NSLocationUsageDescription Location services
apple_events NSAppleEventsUsageDescription Controlling other apps via Apple Events
contacts NSContactsUsageDescription Contacts database
photos NSPhotoLibraryUsageDescription Photo library
calendars NSCalendarsUsageDescription Calendar data
reminders NSRemindersUsageDescription Reminders
bluetooth NSBluetoothAlwaysUsageDescription Bluetooth
speech_recognition NSSpeechRecognitionUsageDescription Speech recognition
desktop_folder NSDesktopFolderUsageDescription Desktop folder
downloads_folder NSDownloadsFolderUsageDescription Downloads folder
network_volumes NSNetworkVolumesUsageDescription Network volumes
removable_volumes NSRemovableVolumesUsageDescription Removable volumes
accessibility NSAccessibilityUsageDescription Accessibility features
[tool.nib.build.plist.usage]
camera = "This app uses the camera for video preview."
microphone = "This app uses the microphone for voice commands."
location = "This app uses your location to show local weather."

[tool.nib.build.plist.custom]

An escape hatch for arbitrary Info.plist keys. Values in this section are merged last and can override anything set by other options.

[tool.nib.build.plist.custom]
NSSupportsAutomaticTermination = true
NSSupportsSuddenTermination = true
MyCustomKey = "custom value"

Complete example

A fully annotated pyproject.toml with all available options:

[project]
name = "weather-widget"
version = "2.1.0"
description = "A macOS menu bar weather app"
requires-python = ">=3.10"
dependencies = [
    "requests",
    "pillow",
]

[tool.nib]
# Entry point script, used by `nib run` and `nib build`
entry = "src/main.py"

[tool.nib.build]
# App display name
name = "Weather Widget"

# Bundle identifier
identifier = "com.example.weatherwidget"

# App version (overrides [project].version for the bundle)
version = "2.1.0"

# Icon file (.icns or .png; PNG is converted)
icon = "src/assets/icon.png"

# Minimum macOS version
min_macos = "14.0"

# Packages to exclude from bundling
exclude = []

# Additional dependencies if auto-detection misses them
extra_deps = []

# Start at login (requires signed app)
launch_at_login = false

[tool.nib.build.plist]
copyright = "Copyright 2025 Jane Developer"
category = "public.app-category.weather"
notification_style = "banner"
dock_icon = false
background_only = false
build_number = "42"
allow_http = ["api.weather.com"]
url_schemes = ["weather-widget"]

# File type associations
[[tool.nib.build.plist.document_types]]
name = "Weather Data"
extensions = ["weather", "json"]
role = "Viewer"

# Privacy descriptions
[tool.nib.build.plist.usage]
location = "Weather Widget uses your location to show local forecasts."
camera = "Weather Widget uses the camera for sky condition detection."

# Custom plist keys (escape hatch)
[tool.nib.build.plist.custom]
NSSupportsAutomaticTermination = true