Pennant for macOS: one open-source AI agent that does the work on your Mac, on a schedule, with any model. It asks before it publishes, sends, deletes or spends. Free, Apache-2.0.
See the codeThe AI agent that does the work.
Pennant is a free, open-source AI agent that lives on your Mac, with an iPhone companion. Give it jobs in plain words: it triages the inbox, writes the posts, watches production and fixes the code, on your schedule and with whatever model you choose. Before it publishes, sends, deletes or spends, it hands you a card and waits for your OK.
Download: pennant.dev or the latest release · macOS 15 or later, Apple silicon or Intel · signed and notarized by Apple · updates itself once you allow it
▶ Four short films on pennant.dev: the night shift and its approvals, memory, using your Mac, and coding.
| Your morning, waiting for you | Nothing goes out until you say so |
|---|---|
![]() | ![]() |
| Code changes in a thread of their own | Memory with receipts |
|---|---|
![]() | ![]() |
| Goals it works toward on its own | Every run, job and model costed |
|---|---|
![]() | ![]() |
Every person, company and number in these screenshots is fictional. The app renders them from a demo host in a throwaway folder (pennant-host --seed-demo).
SKILL.md format used by Claude Code, Codex and Agent Skills, in a git repository you own, with
every version kept. Pennant writes new versions when you give feedback, and you can teach one by doing the task once while
it watches.Pennant has no account with us, no telemetry and no cloud of its own.
~/Library/Application Support/Pennant. Export and import move it to your next Mac.ollama pull gemma4:e2b-it-qat.claude program installed and signed in. Pennant's own engine needs only a model.| Shortcut | Action |
|---|---|
| ⌘N | New thread |
| ⌘1 | Dashboard |
| ⇧⌘K | Every conversation, in a window of its own |
| ⇧⌘W | Close the thread |
| ⌘Return | Send |
| ⇧⌘. | Stop computer use (also in the menu bar) |
| ⌘+ / ⌘− / ⌘0 | Zoom in, zoom out, actual size |
You need macOS 15 or later, Xcode 27 and brew install xcodegen.
swift build # host, CLI and libraries
swift test --skip LiveInferenceTests # the test suites
Scripts/build-release.sh --open # release host + signed Pennant.app with the host inside → dist/Pennant.app
Scripts/generate-project.sh # Pennant.xcodeproj, for working in Xcode
Scripts/build-apps.sh # debug builds of the Mac and iPhone apps
build-release.sh signs with the first Apple Development or Developer ID identity in your keychain (or ad hoc if there is
none), so macOS keeps the Accessibility and Screen Recording grants across rebuilds. To build the iPhone app for a device, put
DEVELOPMENT_TEAM = <your team id> in Apps/Signing.local.xcconfig, which git ignores.
The host also runs on its own, with pennant as a terminal client for scripting and diagnostics:
swift run pennant-host --endpoint http://localhost:11434/v1 --model gemma4:e2b-it-qat
swift run pennant status # in another terminal
swift run pennant send "List the files in ~/Documents and summarise them"
swift run pennant watch # every event as it happens
The host keeps its database, artifacts, config and log in ~/Library/Application Support/Pennant. Choose a model in the
Mac app's Settings, or in config.json there:
{
"inference": {
"baseURL": "http://gpu-box.local:8000/v1",
"model": "deepseek-ai/DeepSeek-V4-Flash-Vision-Exp",
"contextWindowTokens": 128000,
"supportsVision": true,
"supportsTools": true
}
}
docs/RUNBOOK.md covers the endpoint flags vLLM and SGLang need, the ChatGPT and Apple on-device providers,
the macOS permissions in detail, running the host as a LaunchAgent, connecting an iPhone, coding runs and MCP sign-in. Every
setting in the apps has a command too: pennant coding folder <dir>, pennant goals, pennant skills import <source>,
pennant health enable.
The host's logic is tested without a screen, a network or a model: the task runtime and its approvals, the tool broker and sign-off rules, memory and its provenance, the scheduler and goals, skills, the store and its migrations, inference adapters against recorded responses, and the protocol. 421 tests, with 0 failures, measured on 30 September 2026:
| Module | Lines | Functions |
|---|---|---|
PennantCore | 87.0% (2106/2422) | 69.9% (413/591) |
PennantHostKit | 70.8% (17377/24547) | 61.2% (2974/4863) |
PennantClientKit | 35.1% (669/1906) | 36.1% (156/432) |
Scripts/coverage.sh # the tests, then this table
The SwiftUI views in PennantUI have almost no unit tests (0.3% of lines). They are checked by photographing the real Mac and
iPhone apps against the demo host, in light and dark, with Scripts/demo-shots.sh.
Scripts/release.sh builds a universal app, archives it, signs it with Developer ID, notarizes and staples it, packs the DMG,
zip and tarball with their checksums, and writes the signed update feed. Scripts/deploy-site.sh publishes the website in
www/ and the feed. See docs/RELEASE.md.
The screenshots on the site and in this README come from Scripts/demo-shots.sh, which seeds a demo host with fictional data
in a temporary folder and photographs the real apps against it; the seeder refuses to run in a folder that has data in it.
Sources/
PennantCore/ Models, the task state machine, event types and the client/host protocol. Shared by every target.
PennantHostKit/ The host: SQLite store, inference, desktop control, tool broker, task runtime, memory, skills,
goals, scheduler, MCP and the API server. macOS only.
PennantHost/ pennant-host, the service that runs in your user session
PennantClientKit/ Client session, WebSocket transport, cached state, sign-in, Bonjour discovery. Mac and iPhone.
PennantUI/ SwiftUI views shared by the Mac and iPhone apps
PennantCLI/ pennant, the terminal client
Apps/
PennantMac/ The Mac app: window, menu bar, settings, updates (Sparkle); embeds Pennant Host
PennantiOS/ The iPhone app
Tests/ XCTest suites for the core, the host and the UI
www/ pennant.dev: static HTML, CSS and JavaScript
Scripts/ build, release, site deploy, demo screenshots
docs/ Spec, architecture, protocol, design, runbook, decisions, status
The apps are generated into Pennant.xcodeproj by xcodegen from project.yml. The design spec is in
docs/SPEC.md, how the parts fit in docs/ARCHITECTURE.md, the wire protocol in
docs/PROTOCOL.md, the design system in docs/DESIGN.md, and what exists today and how it
is verified in docs/STATUS.md.
pennant diag, which shows whether the endpoint is reachable.~/Library/Application Support/Pennant/logs/host.log, and pennant watch for live events.Questions and ideas are welcome in Discussions, bugs in Issues. Start with CONTRIBUTING.md and the code of conduct. Report security issues privately, as described in SECURITY.md.
Pennant is licensed under the Apache License 2.0. The name and icon are not: see TRADEMARKS.md. Third-party code and marks are listed in THIRD_PARTY_NOTICES.md.
Swift
93.5%
HTML
5.5%
Pennant for macOS: one open-source AI agent that does the work on your Mac, on a schedule, with any model. It asks before it publishes, sends, deletes or spends. Free, Apache-2.0.
See the codeThe AI agent that does the work.
Pennant is a free, open-source AI agent that lives on your Mac, with an iPhone companion. Give it jobs in plain words: it triages the inbox, writes the posts, watches production and fixes the code, on your schedule and with whatever model you choose. Before it publishes, sends, deletes or spends, it hands you a card and waits for your OK.
Download: pennant.dev or the latest release · macOS 15 or later, Apple silicon or Intel · signed and notarized by Apple · updates itself once you allow it
▶ Four short films on pennant.dev: the night shift and its approvals, memory, using your Mac, and coding.
| Your morning, waiting for you | Nothing goes out until you say so |
|---|---|
![]() | ![]() |
| Code changes in a thread of their own | Memory with receipts |
|---|---|
![]() | ![]() |
| Goals it works toward on its own | Every run, job and model costed |
|---|---|
![]() | ![]() |
Every person, company and number in these screenshots is fictional. The app renders them from a demo host in a throwaway folder (pennant-host --seed-demo).
SKILL.md format used by Claude Code, Codex and Agent Skills, in a git repository you own, with
every version kept. Pennant writes new versions when you give feedback, and you can teach one by doing the task once while
it watches.Pennant has no account with us, no telemetry and no cloud of its own.
~/Library/Application Support/Pennant. Export and import move it to your next Mac.ollama pull gemma4:e2b-it-qat.claude program installed and signed in. Pennant's own engine needs only a model.| Shortcut | Action |
|---|---|
| ⌘N | New thread |
| ⌘1 | Dashboard |
| ⇧⌘K | Every conversation, in a window of its own |
| ⇧⌘W | Close the thread |
| ⌘Return | Send |
| ⇧⌘. | Stop computer use (also in the menu bar) |
| ⌘+ / ⌘− / ⌘0 | Zoom in, zoom out, actual size |
You need macOS 15 or later, Xcode 27 and brew install xcodegen.
swift build # host, CLI and libraries
swift test --skip LiveInferenceTests # the test suites
Scripts/build-release.sh --open # release host + signed Pennant.app with the host inside → dist/Pennant.app
Scripts/generate-project.sh # Pennant.xcodeproj, for working in Xcode
Scripts/build-apps.sh # debug builds of the Mac and iPhone apps
build-release.sh signs with the first Apple Development or Developer ID identity in your keychain (or ad hoc if there is
none), so macOS keeps the Accessibility and Screen Recording grants across rebuilds. To build the iPhone app for a device, put
DEVELOPMENT_TEAM = <your team id> in Apps/Signing.local.xcconfig, which git ignores.
The host also runs on its own, with pennant as a terminal client for scripting and diagnostics:
swift run pennant-host --endpoint http://localhost:11434/v1 --model gemma4:e2b-it-qat
swift run pennant status # in another terminal
swift run pennant send "List the files in ~/Documents and summarise them"
swift run pennant watch # every event as it happens
The host keeps its database, artifacts, config and log in ~/Library/Application Support/Pennant. Choose a model in the
Mac app's Settings, or in config.json there:
{
"inference": {
"baseURL": "http://gpu-box.local:8000/v1",
"model": "deepseek-ai/DeepSeek-V4-Flash-Vision-Exp",
"contextWindowTokens": 128000,
"supportsVision": true,
"supportsTools": true
}
}
docs/RUNBOOK.md covers the endpoint flags vLLM and SGLang need, the ChatGPT and Apple on-device providers,
the macOS permissions in detail, running the host as a LaunchAgent, connecting an iPhone, coding runs and MCP sign-in. Every
setting in the apps has a command too: pennant coding folder <dir>, pennant goals, pennant skills import <source>,
pennant health enable.
The host's logic is tested without a screen, a network or a model: the task runtime and its approvals, the tool broker and sign-off rules, memory and its provenance, the scheduler and goals, skills, the store and its migrations, inference adapters against recorded responses, and the protocol. 421 tests, with 0 failures, measured on 30 September 2026:
| Module | Lines | Functions |
|---|---|---|
PennantCore | 87.0% (2106/2422) | 69.9% (413/591) |
PennantHostKit | 70.8% (17377/24547) | 61.2% (2974/4863) |
PennantClientKit | 35.1% (669/1906) | 36.1% (156/432) |
Scripts/coverage.sh # the tests, then this table
The SwiftUI views in PennantUI have almost no unit tests (0.3% of lines). They are checked by photographing the real Mac and
iPhone apps against the demo host, in light and dark, with Scripts/demo-shots.sh.
Scripts/release.sh builds a universal app, archives it, signs it with Developer ID, notarizes and staples it, packs the DMG,
zip and tarball with their checksums, and writes the signed update feed. Scripts/deploy-site.sh publishes the website in
www/ and the feed. See docs/RELEASE.md.
The screenshots on the site and in this README come from Scripts/demo-shots.sh, which seeds a demo host with fictional data
in a temporary folder and photographs the real apps against it; the seeder refuses to run in a folder that has data in it.
Sources/
PennantCore/ Models, the task state machine, event types and the client/host protocol. Shared by every target.
PennantHostKit/ The host: SQLite store, inference, desktop control, tool broker, task runtime, memory, skills,
goals, scheduler, MCP and the API server. macOS only.
PennantHost/ pennant-host, the service that runs in your user session
PennantClientKit/ Client session, WebSocket transport, cached state, sign-in, Bonjour discovery. Mac and iPhone.
PennantUI/ SwiftUI views shared by the Mac and iPhone apps
PennantCLI/ pennant, the terminal client
Apps/
PennantMac/ The Mac app: window, menu bar, settings, updates (Sparkle); embeds Pennant Host
PennantiOS/ The iPhone app
Tests/ XCTest suites for the core, the host and the UI
www/ pennant.dev: static HTML, CSS and JavaScript
Scripts/ build, release, site deploy, demo screenshots
docs/ Spec, architecture, protocol, design, runbook, decisions, status
The apps are generated into Pennant.xcodeproj by xcodegen from project.yml. The design spec is in
docs/SPEC.md, how the parts fit in docs/ARCHITECTURE.md, the wire protocol in
docs/PROTOCOL.md, the design system in docs/DESIGN.md, and what exists today and how it
is verified in docs/STATUS.md.
pennant diag, which shows whether the endpoint is reachable.~/Library/Application Support/Pennant/logs/host.log, and pennant watch for live events.Questions and ideas are welcome in Discussions, bugs in Issues. Start with CONTRIBUTING.md and the code of conduct. Report security issues privately, as described in SECURITY.md.
Pennant is licensed under the Apache License 2.0. The name and icon are not: see TRADEMARKS.md. Third-party code and marks are listed in THIRD_PARTY_NOTICES.md.
Swift
93.5%
HTML
5.5%