191 lines
30 KiB
Markdown
191 lines
30 KiB
Markdown
# Conjure
|
||
|
||
A native macOS application launcher. Open it normally or activate it with a configured global shortcut, search for an application, and press Return to open it or bring its existing instance forward.
|
||
|
||
## Build, run, and install
|
||
|
||
Requires macOS 14 or later and a Swift 6 toolchain (Xcode 16 or later).
|
||
|
||
```sh
|
||
make run
|
||
```
|
||
|
||
This builds a release executable, assembles an ad-hoc-signed application at `.build/Conjure.app`, gracefully quits any running instance of that exact development bundle, and launches a fresh process through Launch Services. This ensures rebuilt code is loaded; simply opening an already-running app in Finder does not reload its executable. Other copies of Conjure are left running. The local signature is for development, not notarized distribution.
|
||
|
||
```sh
|
||
make build # Build the application without opening it.
|
||
make install # Install the application at /Applications/Conjure.app.
|
||
make test # Run behavior and installation safety tests.
|
||
```
|
||
|
||
`make install` rebuilds the signed bundle and installs it without launching it. To install for your user only, or if `/Applications` is not writable:
|
||
|
||
```sh
|
||
make install INSTALL_DIR="$HOME/Applications"
|
||
```
|
||
|
||
Installation verifies a temporary copy before replacing the entire existing bundle, so removed resources do not linger. Quit the app at the destination before reinstalling; other running copies are left alone. Unrelated apps and symbolic-link destinations are not replaced. Installation does not request administrator privileges, and the signature remains local/ad-hoc rather than notarized.
|
||
|
||
Open `Package.swift` in Xcode to edit the project. Use the bundled app above to run it with its application identity and metadata.
|
||
|
||
## Controls
|
||
|
||
- Type to filter applications, calculate an expression, or convert units and currencies; the first result is selected automatically.
|
||
- Up/Down or Control-K/Control-J changes the selection without leaving search or modifying its text.
|
||
- Return, keypad Enter, the footer button, or a double-click opens the selected application or copies a calculator answer and dismisses the launcher.
|
||
- Hold Command alone for one second to show numbered badges at the right edge of the first nine application results. Command already held when opening the launcher also counts: press Command-Space, release Space, and keep Command held. Newly discovered results start the delay once eligible. While still holding Command, press 1–9 to open that result or bring its running instance forward through the normal launch/history path. Numbers refer to the current ranked search results, not the selection or a scroll-relative position. Badges overlay the existing Application text, fading its right edge with an alpha mask while sliding in 14 points from the right over 160 milliseconds; Reduce Motion switches immediately. Releasing Command, pressing another key/modifier, losing focus, dismissing, or opening Actions/uninstall review cancels the hints. A cancelled hold does not restart just because results refresh or focus returns; release Command or reopen the launcher to start a new hold. Calculator/currency results and modal sheets do not enable numbered launching; missing result numbers do nothing.
|
||
- Command-K or the bottom-right Actions button opens a searchable selector for the selected application. **Open** is first and selected by default. Up/Down or Control-K/Control-J selects an action; Return executes it. Escape closes the selector and returns focus to search.
|
||
- Closing Actions with Escape while Command is released leaves numbered hints ready for the next Command hold; cancellation waits for a release only when Command was actually held.
|
||
- Escape or Command-W dismisses the launcher and restores the previously active application. Switching focus away dismisses it without stealing focus back.
|
||
- Reopen from Finder to show it again with an empty search. Dismissal leaves the process running; Command-Q quits it.
|
||
- Every activation brings the launcher to the currently active macOS Space, including full-screen Spaces, without switching desktops.
|
||
- Standard macOS text-editing shortcuts work in the search field.
|
||
- Command-comma opens the native Settings window.
|
||
- Right-click the launcher background for Settings and Quit.
|
||
- Drag the panel background to move it freely. Three stippled guides mark the target left, right, and top edges: the launcher is horizontally centered, its top edge sits one-fifth down the current display's usable area, and the side guides are exactly one launcher-width apart. Each axis brightens within its 12-point snap range, but the window snaps only when the mouse button is released. Releasing outside the range leaves that axis untouched; dismissal cancels without snapping. Guides remain continuous underneath the frosted launcher rather than being cut out around it. They disappear on release or dismissal and do not intercept input.
|
||
- The final dragged or snapped position is saved locally with the display's stable identifier and restored across restarts. Before showing the launcher, Conjure checks that the saved display is connected and the whole panel fits its current usable area. Missing displays, invalid coordinates, or off-screen positions fall back to the default centered, one-fifth-down alignment on an available display; the fallback is kept inside the usable area when the panel fits. First launch uses the same default alignment.
|
||
|
||
Conjure runs as a native accessory app: no Dock icon, app-switcher entry, or menu-bar menus. Keyboard menu shortcuts remain available while its window is focused.
|
||
|
||
## Global shortcut
|
||
|
||
Show the launcher and press `⌘,`, or right-click its background and choose **Settings…**. Click **Record Shortcut…** and press a combination containing Command, Option, or Control. Shift can be added. The shortcut is saved locally and restored when Conjure starts. No shortcut is claimed until you choose one; **Clear** disables it.
|
||
|
||
For Command-Space, click **Use ⌘Space**. If it conflicts, open **System Settings → Keyboard → Keyboard Shortcuts** and disable or change the conflicting Spotlight or Input Sources binding, or another app's shortcut, then try again. The Settings window includes an **Open Keyboard Settings…** button. Conjure reports conflicts rather than modifying macOS preferences, and a failed change preserves your working shortcut.
|
||
|
||
The global shortcut shows the launcher with an empty query and search focused. Press it again while the launcher is focused to dismiss it and return to the previously active app. If Conjure is running in the background, the shortcut brings it forward. Recording temporarily pauses global activation; Escape, moving focus out of the recorder, or closing Settings cancels recording and restores the saved binding.
|
||
|
||
Activation uses the native macOS hotkey API, without an Accessibility permission or a global keyboard monitor. It works only while Conjure is running; it does not launch a quit app or enable launch at login.
|
||
|
||
## Launch at login
|
||
|
||
Open Settings with `⌘,` and enable **Launch at login**. Conjure uses macOS's native login-item service and reads its actual registration status rather than storing a separate preference. If macOS requires approval, Settings explains this and offers **Open Login Items Settings…**. Registration errors are shown beside the control, and the checkbox returns to the actual system state. Install Conjure in `/Applications` before enabling it; disable the toggle to unregister it.
|
||
|
||
Shortcut modifier guidance uses secondary text rather than error red. Shortcut and login-operation failures and unresolved uninstall recovery use red feedback; ordinary instructions and completed recovery use secondary text.
|
||
|
||
Conjure recognizes the native [login-launch Apple event](https://developer.apple.com/documentation/coreservices/1556410-launch_apple_event_constants) and starts without showing a window or taking focus, while still registering its saved global shortcut. Opening it manually from Finder still shows the launcher, including when it is already running. If shortcut registration fails at login, the error is retained and shown in Settings when you next open Conjure manually. Normal manual launches continue to report startup errors immediately.
|
||
|
||
## Discovery and search
|
||
|
||
Applications are discovered in `/Applications`, `/System/Applications`, `/System/Library/CoreServices/Applications`, and `~/Applications`, including nested folders. Discovery runs off the UI thread and refreshes whenever the launcher is presented. Hidden items, invalid bundles, and helpers inside application packages are excluded; symlinked applications are deduplicated by their canonical paths.
|
||
|
||
Discovery supports both standard (`APPL`) and XPC-backed (`XPC!`) `.app` bundles, including Apple Passwords, provided they contain a valid executable.
|
||
|
||
Search is case- and accent-insensitive for applications and built-in commands alike. Ranking is exact name, full-name prefix, word prefix, ordered word initials, substring, then ordered-subsequence fuzzy matches. Fuzzy matches favor smaller gaps and earlier starts. Equally good text matches put favorites first, then order by launch count, most recent launch, and alphabetically. Neither favorites nor usage promote a weaker text match above a stronger one or change which entries match. Hover over an application to see its path. Application launch failures appear in a native alert without dismissing the launcher.
|
||
|
||
Words are runs of letters or numbers separated by spaces, punctuation, or symbols. For example, `settings` matches the second word of System Settings, `gc` matches Google Chrome, and `ss` matches System Settings. Initials must occur in order but can skip words: both `vsc` and `vc` match Visual Studio Code.
|
||
|
||
With an empty search, favorites appear first, separated from the remaining entries by a 12-point gap when both groups are present. Typed searches have no group spacing. Within both favorite and non-favorite groups, applications and commands are ordered together by launch count, then most recent launch, then alphabetically. Favorites and usage are stored locally by application bundle identity or stable built-in command identity and survive restarts; an application and a command with the same name remain independent. Successful application launches and opening a command through Conjure count; submitting translations inside a command does not. Entries without history remain alphabetical within their group.
|
||
|
||
Background discovery preserves the selected entry even if its row changes. If that entry disappears, the first remaining result is selected. Changing the query or reopening the launcher selects the first result.
|
||
|
||
Applications with identical display names show a muted containing-folder hint beside the name. Copies sharing the same folder show their full application bundle paths instead. Home paths abbreviate to `~`, and long hints truncate in the middle. Unique names have no hint; locations are recalculated whenever discovery refreshes.
|
||
|
||
## Conjure Translate
|
||
|
||
Search for **Conjure Translate**, labeled **Command**, and open it with Return, double-click, or **Open Command**. The launcher fades into an English → Japanese translation tool; the existing search bar becomes the English input and retains the launcher's placeholder styling. Escape returns to the previous search.
|
||
|
||
The visible Back chevron and Escape return to the previous launcher query with search focused. Escape also works from the API-key field and translation output.
|
||
|
||
The command participates in the same text matching, usage ranking, and favorites as applications (`ct` matches its initials). Return, double-click, **Open Command**, numbered shortcuts, and **Actions → Open** all record an opening. Its Actions menu offers **Open**, **Favorite / Remove Favorite**, and **Reset ranking**, but not Finder, Quit, or Uninstall. Reset ranking clears usage without removing its favorite status.
|
||
|
||
Choose **MyMemory (no key)** or **OpenAI · gpt-6-luna** from the provider dropdown. MyMemory is the initial default, and the selection is saved locally. Switching providers cancels pending work and clears the previous translation; there is no automatic fallback. Press Return from the English input or click **Translate** in the bottom-right launcher-style action pill, beside its Return key badge, to send text to the selected provider.
|
||
|
||
Provider privacy information and MyMemory limits remain visible separately from transient feedback. Validation, Keychain, and service errors use red text; guidance, progress, and success use the secondary text color. Editing input or credentials clears stale output and error styling without sending a request.
|
||
|
||
[MyMemory](https://mymemory.translated.net/doc/spec.php) requires no account or key. Anonymous use allows 500 UTF-8 bytes per request and [5,000 characters per day](https://mymemory.translated.net/doc/usagelimits.php). Oversized input is rejected before sending; quota and service errors appear in the tool. Text is sent to a third-party translation service: avoid sensitive content.
|
||
|
||
If MyMemory's top translation is blank, Conjure uses the first nonblank exact English→Japanese match in that same response. Approximate matches are not substituted, and service/quota failures still surface as errors.
|
||
|
||
For **OpenAI**, enter an API key and choose **Save Key** (or translate to save it first). Keys are stored in macOS Keychain, not preferences; **Forget Key** removes the saved key. This provider uses OpenAI's Responses API with exactly `gpt-6-luna`. Your account must have access to that model and sufficient API billing. Requests disable API response storage (`store: false`); OpenAI's own data-retention policies still apply. MyMemory never reads or sends the OpenAI key.
|
||
|
||
Translations appear as selectable Japanese text; use Command-C to copy a selection. Editing input or leaving the tool cancels the pending request and prevents stale results from appearing. Typing alone never sends text. Application-only actions and numbered launching are disabled inside the tool.
|
||
|
||
## Calculator, unit and currency conversion
|
||
|
||
Type directly into search, as with [Raycast's calculator](https://manual.raycast.com/calculator). A recognized expression or conversion replaces application results with one **Calculator** or **Daily rates** row. Return, keypad Enter, double-click, or **Copy Answer** copies the displayed answer and dismisses the launcher, restoring the previously active application. Conversion answers include the destination unit or currency code. Application actions are disabled for calculator results; calculations do not affect launch ranking.
|
||
|
||
Arithmetic supports `+`, `-`, `*` (also `x` or `×`), `/` (also `÷`), parentheses, scientific notation, and right-associative `^` powers. Powers bind more tightly than unary signs: `-2^2` is `-4`, while `(-2)^2` is `4`. Functions are `sqrt`, `abs`, `round`, `floor`, `ceil`, `sin`, `cos`, `tan`, `log` (base ten), and `ln`; use parentheses around their arguments. Trigonometric arguments are radians; constants are `pi`/`π` and `e`. A trailing `%` divides by 100; `%` before an unsigned operand is remainder, and `mod` accepts signed operands. Percentage queries such as `52% of 900` and `20% off 80` also work.
|
||
|
||
Convert with `<expression> <source unit> to <target unit>`; `in` and `as` also work. Spaces between numbers and units are optional, and most units accept abbreviations and singular/plural English names.
|
||
|
||
| Unit family | Supported units | Example query |
|
||
| --- | --- | --- |
|
||
| Length | mm, cm, m, km, in, ft, yd, mi | `10ft in m` |
|
||
| Mass | mg, g, kg, oz, lb | `1 kg to pounds` |
|
||
| Temperature | Celsius, Fahrenheit, Kelvin | `32 f to c` |
|
||
| Volume | mL, L, US teaspoon, tablespoon, fluid ounce, cup, pint, quart, gallon | `1 cup to fl oz` |
|
||
| Duration | milliseconds, seconds, minutes, hours, days, weeks | `2 hours in minutes` |
|
||
| Speed | m/s, km/h, mph | `60 mph to km/h` |
|
||
| Area | cm², m², km², in², ft²; also `square` names | `144in² to ft²` |
|
||
| Data | bits/bytes, decimal kilo/mega/giga/tera and binary kibi/mebi/gibi/tebi | `1 GiB to MiB` |
|
||
|
||
Data abbreviations distinguish lowercase `b` (bits) from uppercase `B` (bytes): `8b to B` gives `1 B`. Decimal `KB` is 1,000 bytes; binary `KiB` is 1,024. Culinary volumes use US customary measures, not imperial measures or the 240 mL legal cup.
|
||
|
||
Arithmetic and physical/data unit conversion are offline, with no added dependencies or script evaluation. Output uses a decimal point and up to 12 significant digits; physical units generally use Foundation's native conversion precision, with exact defining Fahrenheit ratios and consistent US customary volume subdivisions. Division by zero, invalid function domains, nonfinite results, and incompatible unit families show a non-copyable error. Ordinary app names, standalone numeric literals, incomplete expressions, and unsupported syntax remain application searches. Input is bounded to 512 UTF-8 bytes and recursive parser depth below 16 to keep live search safe.
|
||
|
||
### Daily currency rates
|
||
|
||
Convert traditional currencies and crypto with currency codes, for example `100 USD to DKK`, `50 eur in usd`, `0.5 BTC to ETH`, or `(100 + 25) GBP as EUR`. Codes are case-insensitive; `to`, `in`, and `as` work just like unit conversions. Answers include the destination code when copied. Supported codes depend on the provider's available rates; unsupported currency codes show a non-copyable error rather than an invented rate.
|
||
|
||
Rates come from the community-maintained [currency-api](https://github.com/fawazahmed0/exchange-api), using its daily EUR-based snapshot for both fiat and crypto conversions. These are **daily rates, not live market prices**. The provider's actual snapshot date is shown in the result detail; it is a data date, not a market quote timestamp. Treat the result as an estimate, not a guaranteed trading or payment quote.
|
||
|
||
A complete, recognized currency query fetches rates over the internet without an account or API key. While loading, there is no copyable answer. Conjure keeps one snapshot in memory and reuses it across queries, with at most one fetch in flight. The next recognized currency query after the local day changes refreshes the cache; there is no background polling or fetch per keystroke. Cached answers keep their snapshot date visible, and an older cache is marked stale while refreshing. The cache is not saved across app restarts.
|
||
|
||
If fetching fails, Conjure shows a non-copyable currency error instead of silently using old or fake rates; any retained snapshot date remains visible. Change the query to retry. Application searches, arithmetic, and physical/data unit conversions still work offline.
|
||
|
||
This is not full Raycast parity: calendar/date/time-zone calculations, design units, and unrestricted natural-language math are not supported.
|
||
|
||
## Application actions and uninstall
|
||
|
||
Select an application and open **Actions ⌘K**. **Open** is the first, default-selected action and uses the same launch path, successful-launch history tracking, dismissal, and error reporting as Return in the application list. Filtering resets selection to the first matching action; an empty result does nothing on Return. Up/Down or Control-K/Control-J navigates actions without changing the selected application.
|
||
|
||
- **Favorite / Remove Favorite** toggles the selected application's persisted favorite status, updates ranking immediately, and preserves the selection without recording a launch. Favorited results show a filled star immediately to the left of the **Application** label. Open remains the default action. Reset ranking clears usage but does not remove a favorite.
|
||
- **Show in Finder** reveals the selected application bundle and dismisses the launcher without restoring the previous application's focus. Its icon is the native monochrome Finder glyph; macOS versions without that symbol use Finder's application icon.
|
||
- **Reset ranking** clears only the selected bundle's launch count and last-launch timestamp, including persisted history. Results reorder immediately while retaining the selected application; other copies and applications keep their history. Future launches start counting again.
|
||
- **Quit application** sends a normal macOS quit request to running instances of that exact bundle, not another copy with the same name or bundle identifier. A non-running application is a no-op. The launcher dismisses after an accepted request; the application may still present save prompts or cancel quitting. Rejected requests show a native alert. Conjure never force-quits the application.
|
||
|
||
The red **Uninstall application** action morphs the existing launcher into a file-review screen with checkboxes, paths, sizes, and a selected-item count; it does not create another window or review sheet. A native 180-millisecond resize and content crossfade runs in both directions, or switches immediately with Reduce Motion. The filter uses a centered, intrinsic-height text field without built-in search/cancel icons, beside an explicit back chevron. Filtering files by name or path does not change file selections. Up/Down or Control-K/Control-J highlights files; Return toggles the highlighted eligible file, including from the filter input, and Space also toggles when the list has focus. Back or Escape restores the original launcher frame, query, and selection. Temporary review geometry is not saved as the launcher position. Leaving is blocked during confirmation or an uninstall operation. Command-Return or the uninstall button opens a native final confirmation dialog; nothing is moved merely by entering review. The confirmation control uses the launcher's frosted rounded pill with separate Command and Return key badges. The launcher Actions control likewise shows separate Command and K badges matching its Open Return badge.
|
||
|
||
The application's name and keyboard guidance remain visible throughout file review: Return toggles inclusion; Command-Return opens confirmation. Filtering preserves discovery progress or errors until discovery succeeds, then shows selection counts and no-match feedback without changing checked files.
|
||
|
||
Keyboard file toggles update the existing checkbox without reloading or fading the list, preserving both the highlighted row and scroll position. The launcher's footer Open and Actions labels use 12-point medium text. All custom shortcut hints—in the launcher footer, numbered application rows, uninstall footer, and actions selector—use `ShortcutIndicator` from `Sources/Conjure/ShortcutIndicator.swift` (for example, `ShortcutIndicator("⌘", "K")`). It owns 12-point medium key text, square 18×18-point containers, visible-glyph centering, border styling, and 2-point gaps between adjacent keys; callers position or hide the whole indicator, and numbered rows update their single key without rebuilding the cell. Native menus and shortcut-recording controls retain their platform styling.
|
||
|
||
Numbered row overlays use 13-point numbers in 22×22-point boxes with a lighter opaque warm-brown backing. Their label fade begins 36 points before the badge, twice the original lead-in; other shortcut hints retain their 12-point text and 18×18-point boxes.
|
||
|
||
The actions selector is an arrowless panel inside the launcher, aligned to the bottom and right edges of the footer action pill, replacing it visually while open rather than floating above it. It shares the launcher's frosted Sunset background, 38-point selection row height, 22×22-point icon boxes with 12-point icon-to-text spacing, 14-point action and search text, rounded selection styling, and Return key badge; selection width follows the panel. Application and command rows use the same sizing constants. SF Symbol optical alignment insets are removed so command icons render inside the same bounds as application icons. The application name appears at the top and borderless action search sits eight points from the bottom, without a divider. Native animations crossfade the panel and footer pill: 160 milliseconds to open and 120 milliseconds to close, with unchanged geometry. Reduce Motion disables the animation. Rapid reopening invalidates stale dismissal completions, and closing panels immediately stop intercepting input. Escape, Command-K, an outside click, or switching away closes it and restores the pill. Closing while Conjure remains active restores launcher search focus; switching away does not steal focus back. Return in action search executes the highlighted action: Open launches the application, while Uninstall opens its review.
|
||
|
||
Action symbols use the adjacent title's font size with the native small optical scale and are never enlarged to fill the icon box. Their artwork stays at text height, while the reserved 22×22-point icon boxes, title positions, and row heights remain unchanged.
|
||
|
||
Discovery includes the application bundle and exact bundle-ID paths in your Library: Preferences, Caches, Application Support, Logs, Saved Application State, Application Scripts, and Containers. Embedded extension identifiers are included. App-group entitlements are read from validated native code signatures; related shared Group Containers and Application Scripts remain unchecked because other applications may use them. Conjure does not guess name-based leftovers or include package receipts. This is conservative discovery, not a guarantee that every associated file is found.
|
||
|
||
System-managed applications, Conjure itself, invalid bundles, symbolic-link paths, locked items, and files owned by another user are not removable. Locked candidates show a reason. A locked application bundle can still have eligible user-owned associated data; removing that data does not remove the locked application itself. No administrator authorization is requested. Running instances of the selected application and its embedded applications are asked to quit gracefully; refusal or timeout stops the operation before moving files.
|
||
|
||
Uninstall freezes the selected paths and records filesystem identities, then stages items by exclusive same-volume moves into private quarantine directories. A durable journal records each intended move before it happens. Staging failure attempts reverse-order restoration without overwriting recreated original paths. Only after every item is staged is the operation committed and finalized into Trash. A finalization failure retains committed quarantine data rather than trying to undo an already committed uninstall.
|
||
|
||
Interrupted operations are recovered on startup: uncommitted operations restore their originals; committed operations finish moving items to Trash. Unresolved operations block new uninstalls. Failure feedback offers **Retry recovery** and identifies retained journal/quarantine paths. Startup recovery feedback and retry remain available in Settings without taking focus during a login launch. Authenticated journals live under `~/Library/Application Support/Conjure/UninstallTransactions`; completed journals retain original-to-Trash mappings in `Completed`.
|
||
|
||
Files are never permanently deleted by uninstall. Trash moves preserve file metadata, but Finder's **Put Back** metadata is not created; restore completed items manually using the retained original-path mappings. Rollback is best-effort, not atomic: inaccessible or disconnected volumes and recreated paths can require manual recovery. Same-user malicious code with access to the journal key is outside the journal-authentication guarantee. Unsupported filesystem semantics fail closed.
|
||
|
||
## Native UI
|
||
|
||
The launcher keeps its Raycast-inspired 750 × 474-point, titlebar-free rounded panel, large borderless search field, compact icon rows, right-aligned application labels, and bottom-right launch pill. Its Sunset palette uses a dark brown background, soft amber and rust glows, warm cream text, and orange accents on the caret, selection, and action outline.
|
||
|
||
The scrolling result list extends 16 points beneath the transparent section-label and footer areas, behind their controls, and fades to transparent over 32 points at each edge. Matching content insets keep resting endpoint rows clear of the controls. The fade stays fixed to the viewport while results scroll; the search bar and footer controls remain crisp.
|
||
|
||
The launch pill uses a 20%-opaque dark-brown fill over the launcher's existing frosted background rather than adding a second, darker popover material. Its rounded orange outline and controls remain distinct.
|
||
|
||
The application icon uses the same orange `sparkles` SF Symbol on a self-contained, rounded dark-brown tile. `Scripts/icon.swift` renders every standard and Retina icon size, and `make build` packages the resulting `.icns` in the signed bundle for Finder and other system icon surfaces. Conjure remains an accessory app; adding an application icon does not add a Dock or app-switcher entry.
|
||
|
||
Settings shares the launcher's dark appearance, frosted HUD material, Sunset background glows, cream headings, and orange control accents. The material and tint extend behind the title bar, while controls stay below it. Native window controls and shortcut recording behavior remain available.
|
||
|
||
The brown tint is 35% opaque over an active, behind-window `NSVisualEffectView` using the native HUD material. This exposes macOS's blurred backdrop while retaining the warm palette and glows; the system material supplies an opaque fallback when Reduce Transparency is enabled. The panel uses a native rounded alpha mask alongside layer clipping, keeping material inside its rounded outline and making the window shadow follow the same shape.
|
||
|
||
AppKit still provides text editing, table navigation, scrolling, application icons, controls, menus, fonts, and visual-effect materials. The background uses cached native radial gradients that fade to transparent: static soft blobs, without animations, timers, image assets, blur filters, or third-party UI dependencies. Decorative drawing does not intercept clicks. Increased-contrast settings strengthen the selection outline, and text colors are tuned for readability across the glows and selection.
|
||
|
||
- `Sources/Conjure`: application lifecycle, launcher, Settings, contextual actions and uninstall review windows, and application launching.
|
||
- `Sources/ConjureKit`: filesystem discovery, search ranking, launch history, calculator and unit/currency conversion, global shortcut registration, launcher alignment geometry, associated-file discovery, and journaled uninstall/recovery.
|
||
- `Tests/ConjureKitTests`: deterministic discovery, ranking, history, calculator precedence/conversion/error boundaries, shortcut validation, alignment boundaries, installation safety, and uninstall failure/recovery checks.
|
||
|
||
The launcher uses Apple's [visual-effect materials](https://developer.apple.com/documentation/appkit/nsvisualeffectview), [table row selection drawing](https://developer.apple.com/documentation/appkit/nstablerowview/drawselection(in:)), [application launching](https://developer.apple.com/documentation/appkit/nsworkspace/openapplication(at:configuration:completionhandler:)), and [reopen lifecycle](https://developer.apple.com/documentation/appkit/nsapplicationdelegate/applicationshouldhandlereopen(_:hasvisiblewindows:)).
|