Profiles and runtime configuration
Profile sources, the default safe profile, runtime config generation, override merging, and Kumo-owned keys.
Profile Sources
Kumo models profiles with ProfileSource:
remote(URL)for subscription URLs.file(URL)for local Clash or Mihomo YAML files.inlinefor generated fallback profiles.
The first version supports a default local profile and remote refresh through the CLI.
Kumo can also import a profile generated by the bundled Sub-Store backend. In
that case profile metadata records the original Sub-Store download path and
refresh rebuilds the request against the current local backend URL with
target=ClashMeta and noCache=true.
Default Profile
If no default profile exists, ProfileRepository returns a minimal direct profile:
proxies: []
proxy-groups:
- name: Proxy
type: select
proxies:
- DIRECT
rules:
- MATCH,DIRECTThis lets the app start with a safe empty state instead of crashing on missing configuration.
Runtime Config Generation
RuntimeConfigBuilder appends Kumo-controlled runtime settings to the selected profile:
external-controllersecretmixed-portmodeallow-lanlog-levelipv6find-process-mode- Geo data settings
- TUN and paired DNS settings when Kumo TUN is enabled
The goal is to keep user profiles portable while ensuring Kumo can control the running core.
Kumo sets find-process-mode: always by default so the Mihomo controller
returns processPath metadata for active connections; the macOS Connections
view uses that path to display native application icons.
Overrides
Kumo plans an ordered override layer:
- Selected profile YAML.
- Profile-specific overrides.
- Global overrides.
- Kumo-controlled runtime settings.
The final layer always wins for controller address, ports, mode, and other Kumo-owned keys.
When Kumo TUN is enabled, the final layer also owns the top-level tun and
dns blocks so UI settings such as stack, auto route, route exclusions, MTU,
DNS hijack, ICMP forwarding, fake-IP range, and nameservers are reflected in the
generated runtime configuration.
Current Merge Strategy
The current implementation parses YAML into structured values before merging:
- The selected profile provides the base document.
- Later overrides recursively merge mapping values.
- Array and scalar values replace earlier values by default.
- Explicit sequence operators can prepend, append, or delete array entries.
- Kumo-owned runtime keys are removed from user-provided documents.
- Kumo-controlled runtime settings are appended last and always win.
Kumo supports Sparkle-style sequence operators (+rules, rules+, and the
same shape for other array keys) and Clash Verge Rev-style rule operators
(prepend-rules, append-rules, delete-rules). These operator keys are
consumed during generation and are not written to the final runtime
configuration. A key ending in ! replaces the target value directly instead
of recursively merging nested mappings.
This gives deterministic precedence for common Mihomo configuration sections without introducing JavaScript transforms or a privileged service dependency. Full YAML comments and formatting are not preserved because the generated runtime file is serialized from structured values.
TUN advanced setting edits are persisted to CoreRuntimeSettings.tun. Applying
them while Mihomo is running restarts the core, matching Mihomo's expectation
that interface-level TUN changes are loaded from the generated runtime YAML
rather than patched piecemeal.
Future Work
- Track subscription user info from response headers.
- Add profile metadata and multiple profile selection.
- Add advanced YAML override files.
- Add JavaScript transforms only after the YAML override flow and sandbox strategy are stable.
- Expand Sub-Store import helpers after the bundled backend API surface is stable.
Mihomo runtime and controller
How Kumo supervises the Mihomo process, the controller API surface it consumes, transport details, and error handling.
macOS SwiftUI interface
KumoApp's scene structure, navigation model, toolbar behavior, Settings, status item, App Intents, and the UI constraints that keep daily workflows first.