Skip to content

About

A small iOS app that blocks apps and websites on a schedule. You pick what to block, which days, and what hours. It runs in the background and gets out of your way.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Cactus

A small iOS app that blocks apps and websites on a schedule. You pick what to block, which days, and what hours. It runs in the background and gets out of your way.

This is the open-source release of Cactus, made by Kiln.

What's here

iOS 26, SwiftUI, and Apple's Screen Time APIs (FamilyControls + ManagedSettings

  • DeviceActivity). Five targets:
Target What it does
Cactus The app: rules, schedules, breaks, hard mode
CactusDeviceActivityMonitor Applies and lifts blocks when a schedule starts or ends
CactusShieldConfiguration Draws the lock screen shown over a blocked app
CactusShieldAction Handles taps on that lock screen
CactusShare Safari share-sheet extension for adding a website to a rule

All five share one App Group's UserDefaults. Cactus/Models/CactusRule.swift, AppGroupStore.swift and ShieldPlan.swift are compiled into every target — ShieldPlan is the single place the contents of a block are computed.

Building

You need Xcode 26, an Apple Developer account (the Screen Time APIs need a provisioned App ID — they don't work with a personal free team), and XcodeGen.

brew install xcodegen && xcodegen generate && open Cactus.xcodeproj

Cactus.xcodeproj is generated from project.yml and is not in git — run xcodegen generate again whenever you add or remove a source file.

What you must change first

Everything below is marked CHANGE ME in the source.

  1. project.yml — bundleIdPrefix, DEVELOPMENT_TEAM, and the PRODUCT_BUNDLE_IDENTIFIER / APP_GROUP_ID pair in all five targets.
  2. Apple Developer portal — register the five App IDs, enable the Family Controls capability on each, and register the App Group and enable it on all five. Miss one extension and it silently reads empty storage: no crash, just a blocker that never blocks.
  3. Cactus/Models/ShieldPlan.swift → CactusSelfProtection.protectedBundleIDs — your app's own bundle IDs. This is what stops the app shielding itself out of existence; get it wrong and you lock yourself out of the only screen where a rule can be lifted.
  4. Cactus/AppConfiguration.swift — support email, website, App Store ID. All optional: leave one empty and the menu row it feeds disappears rather than opening a dead link.
  5. Cactus/Info.plist — UIApplicationShortcutItemType must match AppConfiguration.contactShortcutType.

DEVELOPMENT_TEAM is deliberately blank. To keep it out of git, put DEVELOPMENT_TEAM = ABCDE12345 in a Local.xcconfig (already gitignored) or set it in Xcode's Signing & Capabilities pane.

What this repo does not include

The rule engine is the whole of what ships here. The App Store build's artwork, writing, and one of its two modes are not part of the release:

  • No artwork at all. No app icons (and no alternate-icon picker), no illustrations. The home screen's title is the word alone, where the shipping app puts a mark beside it. Every glyph left in the app is an SF Symbol, and Assets.xcassets holds one colour. The build has no AppIcon asset — add yours and set ASSETCATALOG_COMPILER_APPICON_NAME in project.yml.
  • No welcome screen. The shipping app opens on a pitch — hero image, manifesto, feature list — before it lets you do anything. With the artwork and the voice stripped out there was nothing left of it worth keeping, so a first run lands straight on home, where an empty-state card offers to build the first rule. That card's button is also where the Screen Time permission is requested; if you put a welcome screen back, move the ask into it.
  • One quote instead of nine. The shipping app makes you type back a borrowed line — Woolf, Thoreau, Weil — before it grants a break. Those are other people's words and aren't ours to relicense, so Copy.quotesLong carries a single generic line. Add your own, and check you have the right to ship anything you borrow.
  • Less voice. The shield used to lead with a line of its own and push "<app> is blocked." into the subtitle; here that status is the whole shield. What's left throughout is functional copy — the app's tone is yours to write.
  • No whole-phone mode. The shipping app has a second mode that locks everything except a short allowlist, with its own count-up tile, midnight auto-end, and priced exits. It's gone: the tile, the .all(except:) lockdown policy, the day-stamped state, and the DeviceActivity monitor that ended it. What survives from that work is CactusSelfProtection — the app is always exempt from its own shields, which matters for ordinary rules too, since nothing stops a user picking Cactus in the app picker.
  • No overflow menu. Home has one toolbar button, +. The shipping app's ⋯ menu (contact, about, share, icon picker) is gone, and with it the share sheet and the rating prompt.

Grep for ADD YOUR OWN to find every spot.

Credits

Cactus is made by Kiln.

License

GPL-3.0-only. Use it, study it, change it, ship it — but anything you distribute has to carry its complete source under the same license.

One trap specific to iOS: GPL 3 forbids piling extra restrictions on top of the freedoms it grants, and the App Store's DRM and per-device limits are exactly that. A GPL build is not something you can put on the App Store — this is what got VLC pulled from it in 2010. Sideload, or run it on your own devices.

The App Store build of Cactus is not this code, and is not GPL. That isn't a loophole: the license is a grant to everyone else and leaves the copyright holder's own rights untouched, so Kiln ships a proprietary build while this base stays free. Qt and MySQL have worked this way for decades.

Pull requests aren't accepted, for that same reason — merged code would be GPL-only and could never ship in the App Store build. Issues, bug reports and questions are welcome, and what needs fixing gets fixed.

The GPL covers the code, not the brand. The name "Cactus" and the Kiln marks aren't licensed; ship your fork under your own name.

Copyright © 2026 Kiln.

About

A small iOS app that blocks apps and websites on a schedule. You pick what to block, which days, and what hours. It runs in the background and gets out of your way.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages