dependency-management
Adds, upgrades and removes npm packages in Expo apps under a written policy - expo install, exact pins, 7-day release age, script review, licences.
Skill by zakariaf
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/zakariaf-dependency-management
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/dependency-management
What's inside
- Skill name
dependency-management- Description
- Adds, upgrades and removes npm packages in Expo apps under a written policy - expo install, exact pins, 7-day release age, script review, licences. Use when adding or bumping a package or on ETARGET. Not for SDK majors (expo-sdk-upgrade).
- License
- MIT
- Instructions
- 268 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Agent Skills spec issues
- files: referenced but missing: scripts/deps/check-deps.ts
Files (83)
- SKILL.md
- banned-packages.json · assets/
- expo-sdk-57-module-map.json · assets/
- npmrc-exclude-block.txt · assets/
- shared.json · assets/
- add-expo-haptics.md · examples/
- policy-contract.md · references/
- procedures.md · references/
- release-age-policy.md · references/
- supply-chain.md · references/
- versions.md · references/
- check-deps-policy.mjs · scripts/
- check-lib.mjs · scripts/
- policy.mjs · scripts/lib/
- plan-dependency.mjs · scripts/
- selftest.mjs · scripts/
- dependency-policy.json · templates/contracts/
- dot-npmrc · templates/
- audit-licenses.ts · templates/scripts/audit/
- license-policy.test.ts · templates/scripts/audit/
- license-policy.ts · templates/scripts/audit/
- system-clock.test.ts · templates/scripts/clock/
- system-clock.ts · templates/scripts/clock/
- banned-packages.test.ts · templates/scripts/deps/
- banned-packages.ts · templates/scripts/deps/
- check-deps.ts · templates/scripts/deps/
- check-npm-config.ts · templates/scripts/deps/
- dependency-policy.test.ts · templates/scripts/deps/
- dependency-policy.ts · templates/scripts/deps/
- effective-npm-config.test.ts · templates/scripts/deps/
- effective-npm-config.ts · templates/scripts/deps/
- engines-floor.test.ts · templates/scripts/deps/
- engines-floor.ts · templates/scripts/deps/
- expo-patch-age.test.ts · templates/scripts/deps/
- expo-patch-age.ts · templates/scripts/deps/
- release-age-excludes.test.ts · templates/scripts/deps/
- release-age-excludes.ts · templates/scripts/deps/
- unpinned-approvals.test.ts · templates/scripts/deps/
- unpinned-approvals.ts · templates/scripts/deps/
- workspace-lockstep.test.ts · templates/scripts/deps/
- workspace-lockstep.ts · templates/scripts/deps/
- package.json · tests/bases/monorepo/.agents/skills/vendored-skill/tests/fixtures/bad/
- uses.ts · tests/bases/monorepo/.agents/skills/vendored-skill/tests/fixtures/bad/src/
- app.config.ts · tests/bases/monorepo/apps/notes/
- package.json · tests/bases/monorepo/apps/notes/
- _layout.tsx · tests/bases/monorepo/apps/notes/src/app/
- app.config.ts · tests/bases/monorepo/apps/tasks/
- package.json · tests/bases/monorepo/apps/tasks/
- _layout.tsx · tests/bases/monorepo/apps/tasks/src/app/
- package-lock.json · tests/bases/monorepo/
- package.json · tests/bases/monorepo/
- package.json · tests/bases/monorepo/packages/core/
- task.ts · tests/bases/monorepo/packages/core/src/
- package.json · tests/bases/monorepo/packages/ui/
- expo-haptics-adapter.ts · tests/bases/monorepo/packages/ui/src/haptics/
- uses.ts · tests/bases/monorepo/skills/demo-skill/examples/
- uses.ts · tests/bases/monorepo/vendor/third-party-skill/examples/
- package.json · tests/bases/single-app/.agents/skills/vendored-skill/tests/fixtures/bad/
- uses.ts · tests/bases/single-app/.agents/skills/vendored-skill/tests/fixtures/bad/src/
- app.config.ts · tests/bases/single-app/
- …and 23 more
SKILL.md (first lines)
# Dependency management
Keeps every package of an Expo app on a written, verified set: the right version and specifier, in
the right place, old enough, not deprecated, reviewed, allowed to ship, and installed once. The facts
live in the app's `contracts/dependency-policy.json`; this skill seeds it, plans every change, and
proves the repo against it.
## Rules that must hold
1. **One written policy.** `contracts/dependency-policy.json` holds the versions table (version,
specifier, place, why), held-back majors, do-not-add, bans and the licence policy, seeded from
`templates/contracts/dependency-policy.json` (the canonical stack verified 2026-10-03, Expo SDK
57). A row changes in the same commit as `package.json` and `package-lock.json`. *Why:* npm
`latest` is the wrong major for several packages today (React Native 0.87, TypeScript 7, ESLint 10,
Jest 30); one written truth stops upgrades from memory.
2. **Install Expo-managed packages only with `npx expo install <pkg>@<row spec>`, and keep the
specifier it writes.** *Why:* Expo tests one native set per SDK and `expo install --check` verifies
it; without the spec, `npx expo install` writes whatever Expo's online list names today, which can
be a patch published that morning. A same-day Expo patch is a `WARN` with its due date, never an
install.
3. **Pin every other package exactly, in its place** (`save-exact=true`): runtime code in
`dependencies`, tools in `devDependencies`. *Why:* a patch of a native wrapper changes binaries;
Expo's checks only test that the installed version is inside its range, so the exact pin is what
makes each change a reviewed lockfile commit.
4. **One copy of everything.** Companions a row lets float are installed in the same command or
pinned in the root `overrides` (all ten `@typescript-eslint/*` at the `typescript-eslint` pin);
one `react`, one `react-native`; `npm ls <pkg>` shows one version. *Why:* two `@typescript-eslint`
plugins crash ESLint, and a native module can be compiled into a build only once.
5. **Commit `package-lock.json`, install clean trees with `npm ci` (EAS Build does too), and never
delete the lockfile, set `package-lock=false`, use `--force` / `--legacy-peer-deps` (on the
command line, in `.npmrc` or in an `NPM_CONFIG_*` variable), or set `EAS_NO_FROZEN_LOCKFILE`.**
*Why:* the lockfile is what makes every machine and CI build the same app: EAS Build runs
`npm ci` and fails on a lockfile out of sync, while `npm install` (what developers run, and EAS
Build under `EAS_NO_FROZEN_LOCKFILE`) ignores it under `package-lock=false`; `ETARGET` means too
young, `ERESOLVE` means off the SDK set, and `legacy-peer-deps=true` silences that for every
later install.
6. **`.npmrc` holds `min-release-age=7` (or a stricter number of days), `engine-strict=true`,
`save-exact=true` and `strict-allow-scripts=true`; the root `package.json` holds `engines`
`npm >=11.17.0` and `node >=22.18`; nothing weakens them: no later line, no `before=`, no
`NPM_CONFIG_*` variable in `eas.json` or CI, no `~/.npmrc` line the project file leaves open.** A
younger release enters only through a dated `# exclude-block expires=YYYY-MM-DD reason=…` block
the developer agreed to, naming exact packages, expiring on the publish date + the release age,
deleted (never extended) on that date. *Why:* a 7-day wait lets most malicious or broken releases
be pulled first; npm keeps the last value of a key and reads command line, then environment, then
project `.npmrc`, then `~/.npmrc`; `engine-strict` guards nothing without `engines`, and the npm
of the default EAS images ignores the release age and `allowScripts`.
7. **Review an install script before it runs, one package at a time.** With
`strict-allow-scripts=true` npm stops an install whose tree holds an unreviewed script before
anything runs (`ESTRICTALLOWSCRIPTS`); without it npm 11.17 runs the script and only prints a
notice afterwards. Read the script the plan prints, write its pinned key
(`"<pkg>@<x.y.z>": true`) into the root `allowScripts`, then install; a bump needs a new review.
Never a name-only approval (`"<pkg>": true`, `"<pkg>@*": true`): npm runs every future version's
script under it; a name-only `false` (deny every version, what `npm deny-scripts` writes) is
fine. npx and `npm exec` inside the repo follow `.npmrc` but never the root `allowScripts`: a
tool the repo runs is a devDependency (npx then runs the reviewed local copy), EAS CLI (expo-doctor
refuses it as a dependency) a global install with the policy flags, and `allow-scripts` stays out
of every `.npmrc` and variable. *Why:* an install script runs arbitrary code on every machine and
CI runner that installs.
8. **Never add a banned package:** the supply-chain floor (compromised or deprecated packages), plus
the app's own bans and opt-in profiles (`offline-only`, `no-telemetry`), all listed in the
policy's `banned`. *Why:* the app's own gate reads only the policy, so the list is complete there.
9. **No deprecated direct dependency without a written reason in its row.** *Why:* deprecated code
gets no fixes; a deliberate hold (ESLint 9, held back) stays visible instead of silent.
10. **Ship only allowed licences** (by default MIT, ISC, Apache-2.0, BSD-2/3-Clause, 0BSD, OFL-1.1,
CC0-1.0) or an approved exception with its exact licence and reason; audit the release bundle,
not the lockfile, and read the native SDKs a native module brings by hand. *Why:* only shipped
code carries obligations into the app, and the bundle audit sees JavaScript only: the CocoaPods
and Gradle SDKs under a native module (an ads or crash SDK) ship too.
11. **`npx expo install --check` and `npx expo-doctor` pass.** *Why:* they see SDK drift and
duplicate native modules that `tsc` and Jest cannot.
12. **Respect held-back majors until their written triggers; move Expo SDK majors only with the
expo-sdk-upgrade skill.** *Why:* each held-back major breaks a verified part of the stack.
13. **Install a package in the same change as the code that uses it.** *Why:* an unused package ages
unreviewed, and knip cannot see an unused native module once a shared package peers it.
14. **Stop and ask the developer before a package not in the policy, a dated exception, a licence
exception or a deprecation hold,** bringing the facts `plan-dependency.mjs --online` prints.
15. **Read a library's versioned docs before coding against it, never memory,** and re-verify a row
before trusting it when the policy's `verified` date is more than a few weeks old.
When multi-package (npm workspaces), rules 3 and 4 also mean: a native module is never in a shared
package's `dependencies` or at the root (Expo's checks verify only an app's direct dependencies, and
only one copy of a native module can be compiled); a shared package lists the native modules its code
imports as `"*"` peers; every app that depends on it installs them with one specifier; the root
`overrides` pin each peer at the apps' version, plus `react` and `react-native`. A JavaScript library
the apps and a shared package both import is one row whose `where` lists both places.
## Workflow
1. Name the task: add, upgrade, remove, the monthly pass, a dated exception, or a failing dependency
gate. A failing gate: go straight to "When a gate in this area fails" in
[references/supply-chain.md](references/supply-chain.md).
2. No `contracts/dependency-policy.json` yet: copy `templates/contracts/dependency-policy.json`,
delete the rows the app will never use, and read
[references/policy-contract.md](references/policy-contract.md). No `.npmrc`: copy
`templates/dot-npmrc` to `.npmrc`.
3. Read the package's row (and [references/versions.md](references/versions.md) for why the seed
says what it says), then the matching section of
[references/procedures.md](references/procedures.md).
4. Plan: `node ${CLAUDE_SKILL_DIR}/scripts/plan-dependency.mjs <pkg>[@<version>] . --online` (add
`--remove` to remove; when multi-package, `--peer-of <workspace>` when a shared package imports it;
offline, save `npm view <pkg>@<v> version time license scripts deprecated --json` to a file and
pass `--npm-view <file>`). A `FAIL` line (`banned`, `do-not-add`, `held-back`, `not-in-table`,
`version-differs`, `too-young`, `deprecated`, `licence`) means stop: fix the request, follow the
upgrade procedure, or ask the developer.
5. Too young but needed: read [references/release-age-policy.md](references/release-age-policy.md),
get the developer's agreement, fill `assets/npmrc-exclude-block.txt` (expiry = the publish date +
the `.npmrc` min-release-age; the plan's `too-young` fix line prints it) and append it to `.npmrc`
after one blank line.
6. Review before installing: when the plan prints a `review first` step, read that script and write
its pinned key into the root `allowScripts` ([references/supply-chain.md](references/supply-chain.md),
"Install scripts"). An install that stops with `ESTRICTALLOWSCRIPTS` ran nothing: review each
package it names the same way, then run the install again. A tool run through npx (EAS CLI, a
scaffolder) follows "npx and one-off tools inside the repo" in the same reference instead.
7. Run the printed install steps exactly, in order (companions in the same command; when
multi-package, the peer and its root override first, then every app in the same change). Then
`npm approve-scripts --allow-scripts-pending` must print `No packages with unreviewed install
scripts.`
8. A config plugin: one entry in the `plugins` list of `app.config.ts`, with a comment naming the
owning skill; never a second list, never an edit in the generated `ios/` or `android/`. A packageFrom zakariaf/ReactNative-Skills, MIT.
More from zakariaf/ReactNative-Skills
- 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
android-release-play
zakariaf
Ships Android App Bundles to Google Play: upload key, Play App Signing, AAB gate, versionCode, tracks, rollout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
architecture-and-boundaries
zakariaf
Places app code in the src/ layout and checks import boundaries: one-way zones, pure core, ports with fakes, one composition root.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
async-safety
zakariaf
Prevents silent async bugs: effect races, stale results, lost promises, leaked listeners and timers, AbortSignal gaps.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
audio-and-haptics-feedback
zakariaf
Builds SFX and haptics behind ports.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
auth-and-secure-storage
zakariaf
Builds sign-in - tokens in expo-secure-store, shared refresh, protected routes, OAuth PKCE, Apple sign-in.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
background-tasks
zakariaf
Builds expo-background-task jobs: idempotent, budgeted runs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9
Signals
- Stars
- 11
- Forks
- 2
- Open issues
- 0
- Last commit (this folder)
- Oct 17, 2026 (12 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/zakariaf/ReactNative-Skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from zakariaf
- 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9
Cite this page
dependency-management skill. Agent Mart. https://agentmart.dev/skills/zakariaf-dependency-management (last updated 2026-10-24)