| 命令 | 数据目录 | LaunchAgent label | |
|---|---|---|---|
| 线上 | free |
~/.free/ |
app.saaskit.free.daemon |
| 开发 | free-dev |
~/.free-dev/ |
app.saaskit.free.daemon-dev |
两套环境完全隔离(daemon 进程、session 数据、credentials、日志各自独立)。./run dev 启动的是开发环境。
Run pnpm run check:deps:madge to verify circular dependencies. Zero cycles allowed.
Run pnpm run check:deps:layers to verify sync layer has no static imports from @/components/* or @/realtime/*.
Use pnpm run check:deps to run both checks together.
- Types/constants in separate files — When a file both exports types and imports its consumers (e.g. a registry that imports components and exports
ToolViewProps), the types MUST live in a dedicated file (e.g.types.ts). Consumers import types from that file, not from the registry. - Unidirectional dependencies —
storage(state layer) must NOT import fromsync(business layer). When reverse communication is needed, use the callback registration pattern:storage.tsexposesregisterXxxCallback(), andsync.tsregisters at init time. - Lazy require for cross-cutting concerns — When a module only calls another module inside event handlers or callbacks (not at init time), use
require()inside the function body instead of a top-level import, to avoid creating a static dependency edge.
app/(app)/ is an Expo Router directory — only page components (files with export default) belong here. Data files, utilities, hooks, and types must go under @/ (e.g. @/dev/, @/utils/). Every Stack.Screen in _layout.tsx must have a corresponding .tsx file.
All debug logging must use the unified telemetry Logger — never console.log for debug output.
import { Logger } from '@agentbridge/core/telemetry';
const logger = new Logger('layer/component/name');
logger.debug('message', { key: value });
logger.error('message', { error: String(e) });console.log/erroris reserved for user-facing terminal output only (CLI chalk messages, QR codes)- Logs are written to JSONL files with automatic
traceIdcorrelation across App → Server → CLI → Agent - Verification:
grep -r "sources/log\|ui/logger\|DANGEROUSLY_LOG" . --include="*.ts"must return zero results
所有包含 TextInput / MultiTextInput 的页面必须处理键盘适配:
ItemList(推荐):已内置automaticallyAdjustKeyboardInsets,直接使用无需额外配置。- 裸
ScrollView:手动加automaticallyAdjustKeyboardInsets={Platform.OS === 'ios'}。 - 底部固定输入框(如 AgentInput):使用
KeyboardAvoidingViewfromreact-native-keyboard-controller,behavior="padding",keyboardVerticalOffset不传(库会自动测量 view 位置)。 - 禁止使用 RN 原生
KeyboardAvoidingView(fromreact-native),在 iOS 上动画不可靠。 editable={false}的只读 TextInput 不需要处理。
When adding any workaround — pnpm patches, Metro/Babel config hacks, Expo config plugins
used to fix third-party bugs, or dependency version pins for compatibility reasons —
always update docs/workarounds.md with:
- What the workaround does
- Why it's needed (root cause, bug link if available)
- Trigger conditions
- Removal condition (what version/event makes it safe to delete)