callstack / callstack/agent-device

feat: workspace-scoped device pinning (lock a project to one device)

Open
#2,161 2 comments 0 reactions 0 assignees View on GitHub
needs-triage
Dominant language
TypeScript
Stars
4.6k
Forks
299
Avg merge
10h 14m
Merged PRs (30d)
537

Description

## Motivation

User feedback (local-environment, client project):

> I had tons of issues with agent-device always trying to open iPhone simulator (default) when I really wanted the session to be scoped to a particular iPad only when I was working with real client's project. Solved it by wrapping every agent-device command with my custom bash script. I think simlock might be a good tool to enforce that.

Today the only way to target a specific device is to pass `--platform/--device/--udid/--serial` on every invocation. When an agent (or human) forgets, inventory selection falls back to its booted-device heuristics and picks the default iPhone simulator — on a client project that is not a nuisance but a correctness failure. Users are resorting to wrapper scripts to enforce scoping.

This is adjacent to but distinct from #1320: device claims fence *other* worktrees' daemons off a device; they do nothing to stop *your own* commands from selecting the wrong device. Enforcement of user intent at selection time is the missing piece.

## Proposal

A workspace-scoped device pin that both **defaults** and **enforces**:

- A pin source, in precedence order: env (`AGENT_DEVICE_PIN`-style selector) and/or a per-workspace config the daemon/CLI reads from the project root. The repo currently has no project config file surface, so the env form may be the v1.
- Selector-less commands inherit the pin: `open com.example.app` targets the pinned iPad, never the default iPhone.
- Commands with an explicit selector that CONTRADICTS the pin fail with a structured error naming the pin and its source — consistent with the #1880 principle that selection conflicts fail instead of retargeting. (An explicit selector that refines the pin — same device — passes.)
- `devices`/`doctor` surface the active pin so agents can discover why selection is constrained.
- The error and `--help` text must teach the escape hatch (edit/unset the pin), not invite per-command overrides that defeat the point.

## Non-goals

- Cross-worktree exclusion (that is #1320's device claims).
- Provider/remote lease semantics.

## Acceptance

- With a pin set and no selector flags, every device-targeting command resolves to the pinned device or fails if it is unavailable — it never falls back to another device.
- A conflicting explicit selector fails with a structured error naming the pin, its source, and the pinned device.
- No wrapper scripts required: the pin is honored by `open`, sessionless mutations (`boot`, `install`, ...), and inventory-based selection alike.

Contributor guide

Open the contributing guide

Research direction

Start by tracing device selection for open, sessionless mutations such as boot and install, and inventory-based selection. Read the current CLI help and selection-conflict handling, then identify how devices and doctor could expose an active pin. Done means pinned commands never fall back, conflicting selectors fail with structured details, and the escape hatch is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, mobile-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.