Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 0 additions & 94 deletions CONTRIBUTING.md

This file was deleted.

78 changes: 40 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,57 @@
# OpenAppLock

OpenAppLock is an open-source iOS Screen Time app. You define recurring
**rules** that block selected apps — by schedule window, daily time limit, or
number of opens — with an optional **Hard Mode** that makes an active block
impossible to lift, edit, or delete until its window ends. The interface is
intentionally plain, native iOS (List/Form/NavigationStack).
OpenAppLock is a free, open source app blocker for iOS using Apple's Family Controls API. At this time, it has been created primarily with Claude Code.

It is built on Apple's Screen Time APIs — FamilyControls, ManagedSettings, and
DeviceActivity — so blocking is enforced by the system, not by a VPN or DNS
shim.
Join the [TestFlight](https://testflight.apple.com/join/5ymbrmns) beta! The App Store link will come...soon.

## Requirements
## Features

- Xcode 26+ and an iOS 26 simulator (to build and run the tests).
- An Apple Developer account is only needed to run on a physical device; real
app-blocking and usage tracking are observable on-device, not in the
simulator.
- Create app blocking rules
- **Schedule**: block apps on a schedule
- **Time limit**: block apps after using them for a set period of time
- **Open limit**: block apps after opening them a number of times
- Define custom app lists to use with any of these rules
- Hard mode
- If this is on, the rule cannot be disabled while it is active
- Uninstall protection
- Prevent app uninstallation to work around hard mode, if hard mode is on

## Getting started
## Building

You need Xcode 26+ and an iOS 26 simulator to build and run the tests. To see the app blocking in action, you'll need a real device.

You'll need to follow some steps to use your own development team/certificate/provisioning profile after cloning.

1. Clone the repository. Do *not* open it in Xcode yet.
2. Create a folder titled `SharedXcodeSettings` *next to the cloned repository*. Then, create a file `DeveloperSettings.xcconfig` in that folder. The structure should look like this:

```sh
git clone git@github.com:brendan-ch/OpenAppLock.git
cd OpenAppLock
open OpenAppLock.xcodeproj
```
directory/
SharedXcodeSettings/
DeveloperSettings.xcconfig
OpenAppLock/ # the cloned repository
OpenAppLock.xcodeproj
```

3. In that folder, create a file `DeveloperSettings.xcconfig` and include the following line:

```
DEVELOPMENT_TEAM = <the team ID of your Apple Developer account>
```

4. Open the project in Xcode

Pick an **iOS Simulator** destination and build. No code signing is required
for simulator builds or tests. To run on a device, see the signing and
identifier steps in [CONTRIBUTING.md](CONTRIBUTING.md).
This setup was stolen from [NetNewsWire](https://github.com/Ranchero-Software/NetNewsWire/blob/main/README.md#building); go check them out!

## Project layout
By default, the app will attempt to read this file, falling back to an empty development team if the file doesn't exist. This will work for simulator testing, but not for real device testing.

| Path | What |
|---|---|
| `OpenAppLock/` | App target (SwiftUI + SwiftData): models, pure logic, services, views |
| `Shared/` | Code compiled into the app and all three extensions |
| `OpenAppLockMonitor/` | DeviceActivityMonitor extension (limits, resets, session expiry) |
| `OpenAppLockShieldConfig/` | ShieldConfiguration extension (shield UI) |
| `OpenAppLockShieldAction/` | ShieldAction extension (Open button handling) |
| `Config/` | Build configuration (`.xcconfig`) — see CONTRIBUTING.md |
| `Docs/` | Feature spec and Swift guidelines |
Note that Xcode may also try to automatically write a development team to the `xcodeproj` file if it can't detect one. If it does this, you may need to undo that change through Git and follow the approach listed above. Note that **PRs containing hardcoded development team IDs will not be accepted**.

Deeper architecture notes live in [AGENTS.md](AGENTS.md); feature behavior is
specified in [Docs/AGENT_RULES_FEATURE_SPEC.md](Docs/AGENT_RULES_FEATURE_SPEC.md).
There's probably a better way to handle this. Please reach out using my email below, or post on the [Discussions](https://github.com/brendan-ch/OpenAppLock/discussions) section, if you have suggestions.

## Contributing

Changes land on `main` only through reviewed pull requests. Branch with a
`feat/`, `fix/`, or `chore/` prefix and open a PR — see
[CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow.
If you're encountering a bug, please open an [issue](https://github.com/brendan-ch/OpenAppLock/issues) and I will look into it! For feature ideas, please raise them in the [Discussions](https://github.com/brendan-ch/OpenAppLock/discussions) section first. Because I'm still heavily developing the app, I may not accommodate all feature requests.

## License
My email is `me [at] bchen.dev` if you have any questions!

[MIT](LICENSE) © 2026 Brendan Chen
Loading