Keep the personal half of the desktop in one place, and ask before installing it

Agent instructions, skills, SSH host aliases and expansion triggers are worth
having identical on every machine one person owns, and belong in none of the
shared configuration. They live in user/ now, with a manifest saying where each
piece goes and a link-user stage that puts it there.

That stage does nothing unless the machine said yes. Somebody who clones Panama
to try the desktop keeps their own ~/.claude/CLAUDE.md exactly where it was;
the question names the destinations and defaults to no. Anything displaced goes
to config/old rather than being deleted.

~/.claude/CLAUDE.md and ~/.codex/AGENTS.md were byte-identical copies of one
file, which is the drift this exists to prevent.

Also adds the vitals toggles for the battery and Claude usage readouts, which
had preferences and no way to reach them.
This commit is contained in:
Gabriel Brown
2026-08-22 08:54:43 -04:00
parent 8b96d907a1
commit 89761a7da3
156 changed files with 16439 additions and 6 deletions
@@ -0,0 +1,44 @@
# Deepening
How to deepen a cluster of shallow modules safely, given its dependencies. Assumes the vocabulary in
[SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**.
## Dependency categories
Classify a candidate's dependencies before deepening it. The category decides how the deepened module
is tested across its seam.
| Category | What it is | How it is tested |
|---|---|---|
| **In-process** | Pure computation, in-memory state, no I/O | Merge the modules, test through the new interface directly. No adapter needed. |
| **Local-substitutable** | Has a local stand-in (PGLite for Postgres, an in-memory filesystem, a framework's own local test backend) | Deepenable once the stand-in exists. The stand-in runs in the test suite; the seam stays internal, with no port at the external interface. |
| **Remote but owned** | Your own services across a network boundary | Define a **port** at the seam. The deep module owns the logic; the transport is an injected **adapter**. In-memory adapter in tests, HTTP/RPC/queue adapter in production. |
| **True external** | Third-party services you do not control | The module takes the dependency as an injected port; tests supply a mock adapter. |
Where the categories usually land in this stack: pure TypeScript logic is in-process; a database with
a local runner is local-substitutable; Convex functions called across the network from a Next.js
client are remote-but-owned; Jira, Infisical, Stripe, and similar are true external. Confirm what
local test harness a framework actually ships before assuming one exists.
The recommendation for a remote-but-owned dependency reads: *"Define a port at the seam, implement an
HTTP adapter for production and an in-memory adapter for testing, so the logic sits in one deep
module even though it is deployed across a network."*
## Seam discipline
- **One adapter means a hypothetical seam. Two adapters means a real one.** Do not introduce a port
unless at least two adapters are justified, typically production plus test. A single-adapter seam
is indirection wearing a design's clothes.
- **Internal seams are not external seams.** A deep module may have internal seams, private to its
implementation and used by its own tests. Do not expose one through the interface merely because a
test reaches for it.
## Testing strategy: replace, do not layer
- Old unit tests on the shallow modules become waste once tests exist at the deepened module's
interface. Delete them; leaving both is how a suite doubles in size while covering the same
behaviour twice.
- Write the new tests at the deepened module's interface. **The interface is the test surface.**
- Assert on observable outcomes through the interface, never on internal state.
- A test that must change when the implementation changes is testing past the interface. That is the
tell, and the fix is the test, not the module.
@@ -0,0 +1,68 @@
# Design It Twice
Explore several interfaces for one module in parallel, because the first idea is unlikely to be the
best. Uses the vocabulary in [SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**,
**leverage**.
## Gate: is this worth the ceremony?
This pattern spends several agents on one decision. It earns that only where the solution space is
genuinely wide and the choice is expensive to reverse:
- **Run it when** the module is load-bearing, several plausibly-good interfaces exist, and callers
will be written against whichever one wins.
- **Skip it when** one obvious interface fits, the module is small, or the decision is cheap to
change later. Design it once, in this context window, and move on.
A single agent that finishes the job in one pass should just finish it. Reach for the fan-out for
breadth, not for routine work.
## Process
### 1. Frame the problem space
Before spawning anything, write a user-facing explanation of the problem space:
- The constraints any new interface must satisfy
- The dependencies it relies on, and their category from [DEEPENING.md](DEEPENING.md)
- A rough code sketch to make the constraints concrete. This grounds the discussion; it is not a
proposal.
Show it, then proceed immediately. The reading happens while the agents work.
### 2. Spawn the designers
Spawn three or more agents in parallel, each producing a **radically different** interface. Give each
a separate technical brief (file paths, coupling details, dependency category, what sits behind the
seam) and a different design constraint:
| Agent | Constraint |
|---|---|
| 1 | Minimise the interface: one to three entry points, maximum leverage per entry point |
| 2 | Maximise flexibility: support many use cases and extension |
| 3 | Optimise for the most common caller: make the default case trivial |
| 4 (where relevant) | Design around ports and adapters for cross-seam dependencies |
**These agents design, they do not write.** Each returns a proposal; none edits a file, so there is
no file ownership to divide and no chance of a collision. Say so in each brief.
Include both the [SKILL.md](SKILL.md) vocabulary and the project's `CONTEXT.md` vocabulary in every
brief, so the proposals name things consistently and can actually be compared.
Each agent returns:
1. The interface: types, entry points, params, plus invariants, ordering, and error modes
2. A usage example showing how callers use it
3. What the implementation hides behind the seam
4. Its dependency strategy and adapters
5. Trade-offs: where leverage is high, where it is thin
### 3. Present and compare
Present the designs one at a time so each can be absorbed, then compare them in prose along
**depth** (leverage at the interface), **locality** (where change concentrates), and **seam
placement**.
Finish with your own recommendation: which design is strongest and why. Where elements from different
designs combine well, propose the hybrid. Be opinionated. The point of the fan-out is a strong read,
not a menu.
+139
View File
@@ -0,0 +1,139 @@
---
name: codebase-design
description: Use when designing or changing a module's interface, deciding where a seam goes, judging whether code is too shallow to be worth its surface, making something testable, or when another skill needs the deep-module vocabulary.
---
# Codebase Design
Design **deep modules**: a lot of behaviour behind a small interface, placed at a clean seam,
testable through that interface. The aim is leverage for callers, locality for maintainers, and
testability for everyone. This is the reference for that language; it is consulted, not run.
## Glossary
Use these terms exactly. Do not substitute "component", "service", "API", or "boundary": the
consistent language is the whole point, because a shared word is what lets a design discussion stay
about the design.
**Module**: anything with an interface and an implementation. Deliberately scale-agnostic: a
function, a class, a package, or a tier-spanning slice. *Avoid*: unit, component, service.
**Interface**: everything a caller must know to use the module correctly. The type signature, but
also invariants, ordering constraints, error modes, required configuration, and performance
characteristics. *Avoid*: API, signature, which are too narrow because they name only the type-level
surface.
**Implementation**: what is inside a module, its body of code. Distinct from **adapter**: a thing can
be a small adapter with a large implementation (a Postgres repository) or a large adapter with a
small implementation (an in-memory fake). Reach for "adapter" when the seam is the topic,
"implementation" otherwise.
**Depth**: leverage at the interface. The amount of behaviour a caller or a test can exercise per
unit of interface it has to learn. A module is **deep** when a large amount of behaviour sits behind
a small interface, **shallow** when the interface is nearly as complex as the implementation.
**Seam** *(Michael Feathers)*: a place where you can alter behaviour without editing in that place;
the *location* at which a module's interface lives. Where to put the seam is its own design decision,
separate from what goes behind it. *Avoid*: boundary, which is overloaded with DDD's bounded context.
**Adapter**: a concrete thing that satisfies an interface at a seam. Names a *role*, the slot it
fills, not its substance.
**Leverage**: what callers get from depth. More capability per unit of interface learned. One
implementation pays back across N call sites and M tests.
**Locality**: what maintainers get from depth. Change, bugs, knowledge, and verification concentrate
in one place instead of spreading across callers. Fix once, fixed everywhere.
## Deep vs shallow
A **deep module** is a small interface over a large implementation:
```
┌─────────────────────┐
│ Small interface │ ← few entry points, simple params
├─────────────────────┤
│ │
│ Deep implementation │ ← complex logic hidden
│ │
└─────────────────────┘
```
A **shallow module** is a large interface over a thin implementation, and is the thing to avoid:
```
┌─────────────────────────────────┐
│ Large interface │ ← many entry points, complex params
├─────────────────────────────────┤
│ Thin implementation │ ← mostly passes through
└─────────────────────────────────┘
```
When designing an interface, ask: can I reduce the number of entry points, simplify the parameters,
or hide more complexity inside?
## Principles
- **Depth is a property of the interface, not the implementation.** A deep module can be internally
composed of small, swappable parts; they simply are not part of the interface. A module can have
**internal seams**, private to its implementation and used by its own tests, as well as the
**external seam** at its interface.
- **The deletion test.** Imagine deleting the module. If complexity vanishes, it was a pass-through.
If complexity reappears across N callers, it was earning its keep.
- **The interface is the test surface.** Callers and tests cross the same seam. Wanting to test
*past* the interface means the module is probably the wrong shape.
- **One adapter means a hypothetical seam. Two adapters means a real one.** Introduce a seam only
when something actually varies across it.
## Designing for testability
Good interfaces make testing natural.
**Accept dependencies, do not create them:**
```typescript
// Testable: the seam is a parameter
function processOrder(order: Order, gateway: PaymentGateway) {}
// Hard to test: the dependency is welded in
function processOrder(order: Order) {
const gateway = new StripeGateway();
}
```
**Return results, do not produce side effects:**
```typescript
// Testable: the outcome is the return value
function calculateDiscount(cart: Cart): Discount {}
// Hard to test: the outcome is a mutation
function applyDiscount(cart: Cart): void {
cart.total -= discount;
}
```
**Keep the surface small.** Fewer entry points mean fewer tests; fewer params mean simpler setup.
## Relationships
- A **module** has exactly one **interface**, the surface it presents to callers and tests.
- **Depth** is a property of a **module**, measured against its **interface**.
- A **seam** is where a **module**'s **interface** lives.
- An **adapter** sits at a **seam** and satisfies the **interface**.
- **Depth** produces **leverage** for callers and **locality** for maintainers.
## Rejected framings
- **Depth as the ratio of implementation lines to interface lines** (Ousterhout): rewards padding the
implementation. Depth-as-leverage is the definition used here.
- **"Interface" as the TypeScript `interface` keyword, or a class's public methods**: too narrow. The
interface includes every fact a caller must know, including the ones the types cannot carry.
- **"Boundary"**: overloaded with DDD's bounded context. Say **seam** or **interface**.
## Going deeper
- **Deepening a cluster given its dependencies**: [DEEPENING.md](DEEPENING.md) covers the dependency
categories, seam discipline, and replace-don't-layer testing.
- **Exploring several interfaces for one module**: [DESIGN-IT-TWICE.md](DESIGN-IT-TWICE.md) covers
the parallel design pattern, and the gate for when it is worth the ceremony.
@@ -0,0 +1,3 @@
interface:
display_name: Codebase Design
short_description: Deep-module vocabulary: module, interface, depth, seam, adapter, leverage, locality.