Skip to content

Repository files navigation

BilineIME logo
BilineIME

Type Chinese. Glance at English. Stay in flow.

macOS 14+ Swift 6 InputMethodKit Rime GPL-3.0

Core model Type pinyin, browse Chinese candidates, preview English only when it is ready.
Runtime lane Developer/tester lane with BilineIMEDev.app, Settings, broker, and local host smoke.
Current boundary Chinese candidate ranking, paging, raw cursor editing, and commit state remain source of truth.

Product Model

BilineIME has one primary interaction model:

  1. Type Chinese pinyin.
  2. Browse Chinese candidates.
  3. Optionally inspect English preview for visible Chinese candidates.
  4. Commit either the Chinese candidate or its ready English preview.

The boundary is strict:

  • Chinese candidate generation, ranking, paging, and commit state remain the source of truth.
  • English preview is an overlay, not a separate input mode.
  • Turning bilingual capability off yields a plain Chinese-first pinyin workflow.
  • Translation preview must never block Chinese typing, browsing, raw cursor editing, or commit.

Interaction Highlights

Workflow Behavior
Candidate browsing =/] expand and move down while preserving the intended column across short rows; -/[ move up and collapse at the top.
Layer switching Shift+Tab switches between Chinese commit and ready English commit for the highlighted cell.
Uppercase Latin Shift+letter inserts uppercase Latin directly when idle; while composing it stays in marked composition as an uppercase Latin segment, with marked preedit showing parser syllable or initial spaces around it.
Raw pinyin cursor Option+/ moves by pinyin block; Command+/ jumps to start/end.
Composition deletion Option+Backspace deletes one pinyin block; Command+Backspace deletes to the raw cursor start.
Candidate panel The custom AppKit panel shows only candidates in candidate mode; raw-buffer-only composition keeps a compact raw buffer fallback.

Plain / only browse candidates when the raw pinyin cursor is at the end of the composition. If the cursor is in the middle, those keys continue moving the raw pinyin cursor inside the marked text instead of touching the host document.

What Ships Today

  • Native macOS InputMethodKit input method app: BilineIMEDev.app.
  • SwiftUI Settings app with Translation, Input Settings, Appearance, and Status.
  • Rime-backed simplified and traditional schemas with user dictionaries.
  • Rime language-model support through librime-octagram, with grammar model assets bundled in the dev app.
  • Custom AppKit bilingual candidate panel with compact and expanded presentation.
  • Inline marked-text preedit with raw pinyin cursor editing.
  • Broker-mediated Settings/IME coordination through BilineBrokerDev, BilineCommunicationHub, shared configuration storage, and shared credential storage.
  • Alibaba Cloud translation behind user-managed shared Keychain credentials.
  • Unified dev lifecycle through bilinectl, with Make targets as thin wrappers.
  • Local real-host smoke harness for TextEdit: candidate-popup, browse, browse-boundary, commit, mixed-uppercase, settings-refresh, and full.
  • Local performance harness covering package synthetic suites, TextEdit host hot paths, and first-launch cold path.
  • Unsigned tester removal packages for safe uninstall and two-phase deep clean; install/update packaging is paused until it can reuse the full transaction.

Current Status

Core model Established. Chinese-first bilingual preview is the fixed product boundary.
Dev lane Usable. Install, remove, reset, diagnose, broker coordination, tester packaging, and host smoke are supported workflows.
Host smoke The harness covers popup, browsing, boundary navigation, mixed uppercase, commit, and safe-boundary settings refresh. The current post-lifecycle-change real-host baseline is pending a fresh artifact-backed run.
Release lane Paused. The reserved BilineIME target remains, but notarized release packaging is not currently supported.

Quick Start

Full machine handoff lives in docs/development-handoff.md. The shortest dev path is:

make bootstrap
make project
make test
make build-ime
make install-ime

Useful day-to-day commands:

make build-settings
make build-broker
make remove-ime
make reset-ime
make prepare-release-env
make diagnose-ime
make dev-pkg
make verify

Notes:

  • Build products go to ~/Library/Caches/BilineIME/DerivedData.
  • BilineIME.xcodeproj is generated from project.yml; regenerate it locally instead of committing it.
  • Do not launch the IME app directly with open; let imklaunchagent own activation.

Install, Enrollment, Smoke

The repository treats host verification as three observable phases:

  1. Install bundles.
  2. Bring the input source to an enabled, selectable state.
  3. Run source-ready host smoke.

Use these entrypoints:

make install-ime
make smoke-ime-host-check
make smoke-ime-host-prepare
make smoke-ime-host SMOKE_SCENARIO=full
make perf-ime-smoke
make perf-ime-host PERF_SCENARIO=full
make perf-ime-host-first-launch

What each step means:

  • make install-ime installs the dev IME, Settings app, broker, and local diagnostics state. Routine reinstalls preserve the stable bundle paths and input-source registration; they do not force-enable the source or perform a global LaunchServices reset.
  • Tester install/update pkg generation is paused. Fresh installs and updates use the checkout's transaction-based bilinectl install lane, which owns the app pair, broker, registration, verification, and rollback together.
  • make smoke-ime-host-check reports readiness as bundle-missing, source-missing, source-disabled, source-not-selectable, source-not-selected, or ready.
  • make smoke-ime-host-prepare only opens System Settings and prints remediation. During a local agent session, Computer Use may complete the ordinary System Settings steps and then re-run the readiness check.
  • make smoke-ime-host is the supported automated real-host behavior smoke entrypoint. It is local-only, never a CI gate, and drives exactly one existing untitled, unmodified, blank TextEdit document. Host smoke and host performance targets run through scripts/with-test-awake.sh, so macOS keeps the display and user session awake only for the command's lifetime.
  • make perf-ime-host uses the same TextEdit safety rules for host performance baselines. Performance artifacts omit typed text by default; opt in with PERF_INCLUDE_TEXT=1 only when the content is safe to retain. make perf-ime-host-first-launch measures cold input-method launch from source selection and first probe key through app launch, input-controller initialization, first composition, panel render, and first candidate commit.
  • first-launch is not a clean pkg first-use measurement. Clean first-use must be recorded separately on a clean user or VM because source enrollment and macOS trust prompts are outside the IME process.

Readiness only proves that macOS registers the source as enabled/selectable. On macOS 26, TISSelectInputSource may report the new source globally while an already-focused host still uses its previous input context. The harness therefore requires a fresh TextEdit-owned composition snapshot from one IME process and performs a Finder → TextEdit focus round trip before retrying. A one-time logout may still be necessary when a newly installed source does not appear in System Settings at all; it is not part of routine reinstalls.

For any other interactive test, use the same bounded wrapper directly:

./scripts/with-test-awake.sh <command> [arguments...]

The wrapper releases its power assertions automatically when the command exits. It keeps display/idle-sleep assertions bound to that command and renews macOS's short-lived user-active assertion while the command is alive. It does not bypass an explicit lock, lid close, or authentication prompt.

For local development, the default is automated real-host verification: bilinectl owns repeatable key sequences, assertions, telemetry, and state restoration; Computer Use prepares or inspects UI-only state. Manual typing is an additional exploratory check, not the default completion gate.

Storage And Coordination

The IME and Settings app coordinate through the broker:

  • BilineBrokerDev is the user-scoped coordination process.
  • BilineCommunicationHub is the shared client facade used by both the IME and the Settings app.
  • Shared configuration is persisted through the broker-backed configuration store.
  • Alibaba credentials are persisted through a shared Keychain-backed vault, with legacy file fallback retained only for migration/recovery.
  • Engine-sensitive settings apply only at safe lifecycle boundaries, not in the middle of live composition.

Tester Packages

For prerelease tester distribution:

make dev-pkg

Each run produces two new unsigned, no-payload removal packages in build/dist:

  • BilineIMEDev-Uninstall-<version>.pkg
  • BilineIMEDev-DeepClean-<version>.pkg

Install/update pkg generation is intentionally paused. The current package environment has no package-aware bilinectl transaction or app/broker protocol compatibility handshake, so an app-only update could pair new apps with an incompatible old broker, while a package-local broker restart would duplicate the lifecycle and weaken rollback. Fresh installs and all updates therefore use the checkout's transaction-based bilinectl install dev --scope user|system lane. The build removes stale install/update pkg artifacts from build/dist so they cannot be mistaken for current output. Older safe-uninstall and deep-clean versions may remain for rollback/recovery; the command lists the two files created by the current run.

DeepClean is intentionally destructive and requires a logged-in non-root console user. It first runs the user-scope cleanup as that user so Keychain, defaults, and user data never resolve to /var/root; only after that succeeds does it run the root-owned system cleanup. Either phase failing fails the package with its diagnostic output intact.

The removal packages are unsigned; see docs/development-handoff.md for exact lifecycle guidance.

Documentation Map

development handoff New machine setup, lifecycle, smoke, credentials, failure recovery.
architecture Product model, module boundaries, broker/storage, verification model.
engineering standards Coding, testing, and host-smoke engineering rules.
acceptance checklist Delivery, behavior, install, and verification checklist.
IME risks Known risks, gaps, and next high-value host smoke coverage.
ADRs Architectural decisions and historical context.

Roadmap

Now
  • Keep simplified and traditional Rime schemas stable.
  • Keep Chinese candidate quality and consumed-span behavior correct.
  • Keep raw pinyin cursor editing reliable in marked text.
  • Keep Shift+ASCII letter aligned with Apple Chinese input behavior: direct uppercase Latin insertion while idle, marked-composition uppercase Latin segments while composing, and continued pinyin composition after those segments. Marked preedit may show parser syllable or abbreviated-initial spaces, but raw input and committed candidate text stay unspaced.
  • Keep broker-backed Settings/IME coordination boring and predictable.
  • Keep the unsigned tester removal lane fail-closed and restore install/update packaging only after it can reuse a package-aware bilinectl transaction.
Next
  • Expand host smoke beyond the current baseline into punctuation, raw-buffer behavior, editing keys, Shift+Tab persistence, phrase/tail commits, and mixed Chinese/Latin stress cases, including uppercase Latin segments followed by more pinyin inside composition and marked preedit syllable/initial spacing.
  • Turn current engine-side future toggles into real behavior where appropriate, especially smart spelling and emoji candidates.
  • Tighten docs and diagnostics around source enrollment edge cases after transactional install, reset, and two-phase deep clean.
Later
  • Restore a supported release packaging lane for the reserved BilineIME target.
  • Add broader host coverage beyond TextEdit once the baseline lane stays stable.
  • Revisit richer release/distribution UX after the dev/tester lane no longer needs frequent recovery guidance.

Repository Policy

BilineIME is GPL-3.0 licensed. Runtime dependencies, bundled data, and major architecture decisions should stay documented and attributable. Generated build artifacts and local project files remain untracked.

About

A macOS bilingual input method with inline translation preview

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages