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 |
Current system version | Minimum macOS version required to run the app |
exclude |
list[string] |
[] |
Packages to exclude from the bundle |
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 |
native |
bool |
false |
Compile Python to native .so via Cython |
obfuscate |
bool |
false |
Strip debug info from .pyc bytecode |
optimize |
bool |
false |
Optimize bundle size (strip binaries, prune stdlib) |
[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 |
-- | Human-readable copyright string |
category |
string |
-- | App Store category (e.g., public.app-category.utilities) |
notification_style |
string |
-- | 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] |
-- | 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 auto-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