Download Latest .scriptable | Latest Release | Changelog | Contributing
A cyberpunk-style manual day tracker designed for the Scriptable medium widget on iPhone.
LensCycle was originally built to track how many days a pair of contact lenses has actually been worn, but it is not limited to contact lenses. By changing MAX_DAY, you can use it to track any item that should only count up when you manually use it, such as care cycles, consumables, replacement intervals, medication rounds, or habit streaks that should not auto-increase by calendar date.
The visual style is inspired by Trauma Team from Cyberpunk 2077. The icon is embedded directly in the script as Base64, so the project stays lightweight and self-contained with no external asset downloads.
If you just want the fastest setup path:
- Install
Scriptablefrom the App Store. - Download the latest
LensCycle.scriptablefile and open it withScriptable. - Add a medium Scriptable widget and set its script to
LensCycle.
Many "replace every N days" items should not be tracked by automatic calendar progression.
- Contact lenses should not keep counting on days you do not wear them.
- If you forget to log a day, you should be able to tap multiple times to catch up.
- Once the limit is reached, the widget should clearly tell you it is maxed out.
- The tracker should live on the Home Screen and stay fast, simple, and local.
LensCycle is built around that exact workflow:
- It only increments when you tap.
- It does not auto-increase while unused.
- It supports repeated taps for manual catch-up.
- It shows
MAXat the configured limit. - One more tap after max starts a fresh cycle.
- Built for the
Scriptablemedium widget on iPhone - Left panel tap to add
+1 day - Right panel tap on the Trauma Team logo to
Purgeand reset the record - Displays the timestamp of the latest increment
- Stores data locally in a JSON file
- No network requests, no dependencies, no external icon file
MAX_DAYis editable for any custom cycle length
When the count reaches MAX_DAY, the widget displays MAX.
Tapping the Trauma Team logo opens a confirmation dialog before wiping the record.
Download Scriptable from the App Store on your iPhone:
LensCycle.scriptable is a Scriptable export file that can be imported directly into the app.
Recommended import flow:
- Download
LensCycle.scriptableon your iPhone. - Open the file in the Files app.
- Tap Share or Open In.
- Choose
Scriptable. - Scriptable will import the script automatically.
If Scriptable does not show up immediately:
- Tap Share.
- Tap More.
- Enable
Scriptablein the app list. - Open the file again with
Scriptable.
After importing, open LensCycle in Scriptable and run it once manually.
This helps you:
- confirm that the import worked
- preview the medium widget layout
- verify that the UI looks correct before placing it on your Home Screen
Add a Scriptable medium widget to your iPhone Home Screen, or to the leftmost iOS Today View page:
- Long-press on an empty area of the Home Screen.
- Tap the
+button. - Search for
Scriptable. - Choose the medium widget size.
- Add it to the Home Screen or Today View.
Do not use the small widget. This project's layout and left/right interaction model are designed specifically for the medium widget.
After adding the Scriptable widget:
- Long-press the widget.
- Choose
Edit Widget. - Set
ScripttoLensCycle. - Close the edit panel.
The widget will now render this project.
Tap the Day N area on the left:
- the day count increases by
1 - the latest update timestamp is refreshed
- you can tap multiple times if you forgot to log earlier usage
The default value is MAX_DAY = 14.
- when the count reaches
14, the widget showsMAX - the next tap on the left panel resets the cycle to
0
That makes it a natural fit for bi-weekly contact lenses, while still working for any fixed-length usage cycle.
Tap the Trauma Team logo on the right:
- the script runs through Scriptable URL Scheme
- a
Purge Log?confirmation dialog appears - choosing
PURGEforce-resets the current record
Open LensCycle.scriptable and find:
const MAX_DAY = 14Change it to any number you want, for example:
7for weekly lenses14for bi-weekly lenses30for monthly lenses90for a quarterly supply or any longer cycle
The script stores its data in Scriptable's local documents directory as:
contactLensData.json
It keeps:
- the current count in
day - the most recent increment time in
lastIncrementAt
That means:
- all data stays local
- no network is required
- the count does not increase unless you explicitly tap it
This is not just a static widget. It uses Scriptable's widget APIs and URL Scheme support:
ListWidgetbuilds the medium widget UIWidgetStack.urlassigns tap actions to the left and right areasscriptable:///run?...triggersincrementandforceResetargs.queryParametersreads the action parametersScript.setWidget(widget)outputs the final widget
Because Purge needs a confirmation dialog, tapping the right side launches Scriptable to execute the action. That is expected behavior.
- contact lens wear tracking
- cosmetic lens care cycles
- razor blade replacement cycles
- filter or consumable replacement intervals
- medication, supplement, or care product rounds
- anything that should only count when you manually decide it was used
Here are a few practical examples beyond the default bi-weekly contact lens setup:
- Weekly lenses: set
MAX_DAY = 7for short replacement cycles - Monthly lenses: set
MAX_DAY = 30for longer wear tracking - Razor blade rotation: count only the days the blade was actually used
- Filter replacement: track active usage days instead of calendar days
- Medicine or supplement rounds: log only the days the item was really taken
LensCycle works best anywhere "days used" matters more than "days passed."
The right-side Purge action needs a confirmation dialog. Scriptable has to open the app to show that confirmation before wiping local data.
This project is intentionally manual. It only increments when you tap the left side, so skipped or non-usage days are not counted.
Open the iOS share sheet, tap More, then enable Scriptable in the app list. After that, try opening LensCycle.scriptable again.
The current layout and interaction zones are designed for the medium widget. A small widget does not provide enough space for the left counter area and the right reset area to stay clear and reliable.
LensCycle stores its local state in contactLensData.json inside Scriptable's documents directory. You can clear it by using the Purge action, or by removing the file manually from Scriptable's local storage if needed.
- Intended for iPhone and iOS users of Scriptable
- The current layout is designed for the medium widget
- Small widgets are not recommended for this interaction model
- Widget refresh timing is still subject to iOS scheduling
- Tap actions run immediately when the widget interaction is triggered
- Scriptable App Store: https://apps.apple.com/us/app/scriptable/id1405459188
- Scriptable Docs / ListWidget: https://docs.scriptable.app/listwidget/
- Scriptable Docs / WidgetStack: https://docs.scriptable.app/widgetstack/
- Scriptable Docs / args: https://docs.scriptable.app/args/
- Scriptable Docs / URLScheme: https://docs.scriptable.app/urlscheme/
- Scriptable Docs / Script: https://docs.scriptable.app/script/
This project is released under the MIT License.




