Ctrl K
ComunidadGuías…

AGENTS.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# BetterShot contributor and agent rules

These rules apply to changes in this repository. Read the relevant implementation
and [CONTRIBUTING.md](CONTRIBUTING.md) before editing. Preserve the current UI and
behavior unless the task explicitly asks to change them. This file is the shared
source of instructions for coding agents; `CLAUDE.md` imports it.

For maintainer tasks, push completed changes directly to `main`; do not create
a PR unless explicitly requested.

## Stack and scope

- The macOS app in `Sources/` uses SwiftUI, AppKit, CoreGraphics, AVFoundation,
  and ScreenCaptureKit. Use native controls and existing project primitives.
- The deployment target is macOS 14.0, set by `minimumOS` in `version.json`.
  Gate macOS 15 and 26 APIs with `#available` and give each a working fallback
  on macOS 14. Read `project.yml` for actual compiler
  settings: the app currently uses Swift 5 language compatibility with main-actor
  default isolation and approachable concurrency. Standalone checks use Swift 6.
  Do not change toolchain settings as a side effect of a feature or UI fix.
- `bettershot-landing/` is a separate Next.js/React/Tailwind website. Web libraries
  and CSS rules do not belong in the native app.
- Search for existing callers and shared rendering paths before adding code.
  Fix the shared cause, keep the diff focused, and avoid speculative abstractions
  or new dependencies when existing code or the platform covers the need.

## Required native UI patterns

### Identity and icons

- Preserve BetterShot's bundled clover identity: `AppIcon` for the app and
  `MenuBarIcon` for the menu tray. Do not replace either with a generic camera,
  a website logo file, or a newly generated icon unless explicitly requested.
- Use Apple SF Symbols for action, tool, settings, and navigation icons:
  `Image(systemName:)`, `Label(_:systemImage:)`, or AppKit's
  `NSImage(systemSymbolName:accessibilityDescription:)`.
- Do not reintroduce Nucleo, third-party UI icon packs, or asset-mapping wrappers.
  Choose symbols available on the deployment target; installing the SF Symbols
  design app is not an application dependency. `scripts/check-sf-symbols.py`
  enforces this in `scripts/run-checks.sh`.
- Keep cloud sharing recognizable with `icloud.and.arrow.up`. Use the same
  symbol for the same action across editors, menus, settings, and capture bars.

### Layout and chrome

- Both editors keep their inspector on the left. Image tools belong in one
  toolbar; do not duplicate tool, aspect-ratio, or redaction controls in the
  image sidebar.
- Video inspector tabs are Background, Cursor, Camera, Effects, and Zoom & Clips.
  Keep its effect cards expanded with no outer disclosure chevrons. Advanced
  controls may use the existing Advanced section.
- Reuse `EditorChrome`, `EditorButtonStyle`, `studioGlass`, `studioEffectCard`,
  `InspectorMetrics`, and the existing inspector components.
- Preserve classic frosted chrome, subtle borders, and compact spacing. In dark
  appearance, effect cards are lighter grey than the darker sidebar. Use system
  colors, readable disabled states, and the existing blue selection accent.
- Respect both light and dark appearances, Reduce Transparency, and Reduce Motion.
  Do not introduce a new Liquid Glass redesign as an incidental cleanup.
- Use `InspectorSlider` for all app sliders, including Settings and timeline zoom.
  Its 0.4.0 compact track contains
  the label and has a separate editable value on the right. Hide the TextField
  label in Forms to prevent duplicate labels and clipped values. Preserve keyboard input, units,
  bounds, precision, and undo grouping; do not substitute another slider style.
- Hide scroll indicators in both editors while preserving scrolling. Check narrow
  windows so tools, labels, values, and actions are not clipped or unreachable.
- Keep one shared capture bar. Reuse `BarMetrics`: capture height 64 pt, recording
  height 38 pt. The recording row contains Stop/timer, Pause, Restart, and Discard.

### Interactions and accessibility

- A second click on an active image tool returns to Select. Clicking video Crop
  again cancels the uncommitted crop; do not destroy the previously applied crop.
  Blur and Pixelate must be visible and toggle out of mask editing on a second click.
- Video mask scope uses Crop Only for the selected rectangle and Full Frame for
  the whole source frame. Keep preview, export, and project persistence consistent.
- Scissors starts unselected. Once selected, it stays active across repeated cuts
  until deselected by clicking it or pressing S. Preserve cut badges below the
  filmstrip, removed-duration labels, and hover previews of source footage.
- Keep native keyboard/focus behavior for standard controls. Icon-only actions
  need accessible names; tooltips alone are insufficient. Preserve selected and
  disabled states, text entry, copy/paste, and keyboard navigation.
- Confirm destructive actions using the existing native alerts. Show recoverable
  errors beside the action with a useful retry or next step.
- Reuse `TransferStatusCard` for export/share progress, completion, and failures.
  Present it through `TransferToast` in a separate panel at the screen-top toast
  position on the editor's display, outside the editor canvas. Preserve native
  progress and Copy/Open/Reveal/Retry actions.
- Do not add animation unless requested. For new interaction feedback, prefer
  opacity or transforms, ease-out, and at most 200 ms. Never animate large blur
  surfaces, make progress dependent on a decorative animation, or add perpetual
  motion. Respect reduced-motion settings. Existing specialized capture/video
  motion is not a reason to redesign unrelated UI.

## Capture, image quality, and recording

- Shortcut defaults: `⌘⇧4` region screenshot, `⌘⇧3` fullscreen screenshot,
  `⌘⇧2` shared capture bar, `⌘⇧5` Recording options, `⌘⇧O` OCR, `⌘⇧C` color picker,
  `⌘⇧1` Capture Previous Region. `⌘⇧2` always opens the capture bar.
  Use `ShortcutService` as the source for UI labels and settings. Migrations must
  preserve customized bindings and disabled states.
- Region screenshots default to BetterShot's adjustable AppKit selector. Use native
  macOS region selector in Settings > Capture > Region (off by default) routes
  them through `screencapture -i` without activating BetterShot, so open menus and
  popovers survive. Native selection always captures on release and shows the live
  screen, so Capture as soon as I let go and Freeze the screen while selecting are
  disabled there. It does not update the remembered rectangle; Capture Previous
  Region keeps the last area chosen with BetterShot's selector, and scrolling
  capture and recording areas still need it. With BetterShot's selector, Capture
  as soon as I let go chooses capture on mouse release or adjustment before
  confirmation. Window screenshots use macOS's native window selector. Recording
  areas use the adjustable AppKit selector and system crosshair. By default it
  opens with the previous area selected, so Return captures it again; Start with
  the last area selected in Settings > Capture > Region turns that off for every
  use of the selector without forgetting the area. Its edges resize it,
  and a drag anywhere, even inside it, draws a new area. OCR keeps macOS's native `screencapture` selector. Do not describe the
  recording selector as Apple's system recording picker.
- Preserve capture-window exclusion, correct display/coordinate conversion,
  cancellation, and focus restoration. Never start a recording after cancellation.
  Check Screen Recording access at capture time through `ScreenCapturePermission`,
  never at launch.
- Keep untouched capture pixels and editable project sources. Full-resolution
  image previews are the default; an optional low-resolution preview must never
  become the source for saving, copying, or export. Keep screenshot framing aligned
  to integer pixels and preserve lossless PNG behavior.
- All screenshot modes stage privately. Copy never exports to the configured
  folder; Edit, Pin, Share, and drag-out retain working files internally. Only
  explicit Save/Export, capture-and-save, or enabled automatic saving of normal
  captures writes a deliverable. Automatic screenshot saving defaults on for new
  installs; upgrades preserve both explicit choices and the previous unset/off
  behavior. Explicit Copy, Edit, and Pin shortcuts bypass it. Keeping previews
  open is independent of automatic saving. Preserve preview/editor behavior and retain
  failed automatic saves for retry. Editor Save
  must work for untouched screenshots, and clipboard file references must
  survive dismissing the capture card.
- The Arrow cursor style uses the shared high-resolution, white-outlined stemless vector artwork with an arrow-tip hotspot. Keep the legacy `macOS` storage key. Hand is no longer offered, but
  legacy projects still render it with `NSCursor.pointingHand`. Preserve native
  hotspots and highest-resolution representations through `PointerArtworkCapture`.
- Custom cursor raster resolution is independent of its logical size and hotspot.
  Preserve transparent backgrounds, contrasting outlines, the highest-resolution
  recorded representation, and cached decoding. Do not regenerate cursor PNGs per frame.
- Keep Recorded/Arrow/Dark/Light/Dot (and legacy Hand), visibility, Natural/Smooth motion, press/ripple,
  and idle hiding consistent in preview, export, and saved projects. Imported
  footage with a baked-in cursor cannot be restyled; explain that in the UI.
- Camera frame ratios are independent of the video canvas ratio. Use
  `RecordingStudioLayout` for preview and export, keep the frame within the canvas,
  and default older projects/presets without a camera ratio to 1:1. Screen/camera
  layout presets apply to the whole video, default legacy projects to Bubble,
  and fall back to the screen when camera footage is unavailable or hidden.
- Plain typing is not recorded. Do not expand input capture as a shortcut to a
  cursor or keyboard-overlay feature.
- `ScreenshotFileNaming` is the only source for deliverable file names. Keep its
  renderer pure and Foundation-only, keep the default template rendering the
  pre-0.5.0 name, and never let a template reach the file system without the
  existing sanitizing. Recording package directory names are project identity,
  not deliverable names; do not rename them.

## Backgrounds and persistence

- `GradientPreset.presets` in `Sources/Models/BackgroundStyle.swift` is the source
  for the ten approved soft gradients: Blush, Peach, Mint, Powder Blue, Butter,
  Lilac, Sage, Coral, Aqua, and Mauve. Their gradients are media backgrounds,
  not a license to add decorative gradients to controls or chrome.
- Reuse the shared gradient drawing, stop positions, and highlights in Settings,
  both editors, and exports. Do not duplicate palettes or flatten them into thumbnails.
- Preserve old project decoding and stored artwork when replacing available presets.
- General > Default Look supplies background, padding, corner radius, and shadow
  for new images and videos. Do not add a separate video background default or
  let project edits overwrite General's defaults. Saved projects retain their look.
- Preserve raw captures, annotations, source movies, masks, crop, undo/redo, and
  saved share links. Use existing history/project resolvers and atomic writes.

## Verification and documentation

- Run checks appropriate to the change; use `make test` for native logic and
  rendering changes. Use existing standalone checks or editor/export integration
  checks against production code, not a copied implementation.
- Check compact layouts and both appearances for UI changes. Offscreen snapshots
  cannot prove live AVPlayer rendering, native window toolbars, global shortcuts,
  permissions, or interactive capture; report what was actually checked.
- Tests must use `BETTERSHOT_TESTING=1` through the provided runners and must not
  access real R2 credentials. Never log credentials or weaken release signing.
- `version.json` is the version source. The 0.5.1 changelog entry is dated
  2026-09-10 at the maintainer’s request. Publish release binaries only when explicitly
  requested; no 0.4.3 release.
  Preserve historical release entries and contributor credit.
- Update README and contributor guidance when behavior or workflows change.
  Keep `CLAUDE.md` a short import of shared instructions rather than a second rulebook.
- Do not modify unrelated work, commit local signing identities, publish releases,
  or remove installed apps/user data as a side effect of routine editing.

## Website-only rules

- Landing-page-only changes must not update or create README files or changelog
  entries unless explicitly requested. Report website changes and validation in
  the task response instead. This overrides the general documentation rule above.

For `bettershot-landing/`, use existing Tailwind tokens and the `cn` utility.
Reuse the installed Radix components; do not mix primitive systems within one
surface. Use accessible labels, existing alert dialogs, `h-dvh` and safe-area
insets for full-height/fixed layouts, and tabular numbers for data. Keep headings
balanced and body text readable without arbitrary letter spacing. Use
`motion/react` only when animation is requested; animate opacity/transforms,
respect reduced motion, and avoid layout or backdrop-filter animation. Do not
add effects solely for decoration or copy website branding into native app assets.