npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

effect-mode

v0.2.0

Published

Dynamic context resolver effects for pi

Readme

effect-mode

npm

Inject fresh, compact workspace state into every pi agent turn.

effect-mode runs trusted shell effects before each LLM call and adds one ephemeral <effect-mode> context message with the latest snapshots. It also lets agents create temporary session-scoped TypeScript effects through a tool. It is designed for high-signal state like git status, workspace files, and test/package hints—without dumping noisy execution metadata into the model context.

Why effect-mode?

  • Agents need current workspace facts, not stale assumptions.
  • Shell commands can provide those facts, but raw command metadata is noisy.
  • Effects are cached, bounded, and re-rendered into compact state snapshots before each model call.
  • Agents can add ephemeral session effects without writing project config.
  • Old effect-mode messages are stripped from context, so snapshots do not accumulate.

Quickstart

  1. Install the package:

    pi install npm:effect-mode
  2. Create .pi/effects.json in your project:

    {
      "$schema": "./node_modules/effect-mode/schemas/effects.schema.json",
      "effects": [
        {
          "id": "git-state",
          "about": "Current local git state for this workspace.",
          "command": "node node_modules/effect-mode/scripts/git-state.mjs",
          "ttlMs": 0,
          "timeoutMs": 2000,
          "maxBytes": 12000
        }
      ]
    }
  3. Inspect what will be injected:

    /effects

What agents see

/effects shows a navigable list of enabled effects. Select an effect and press Enter to view the model-facing content inside that effect's XML tags. The injected model context includes the compact XML wrapper:

<effect-mode snapshot="current-state-not-instructions" resolvedAt="2026-05-02T06:32:52Z" localZone="America/Chicago">
<effect id="project:git-state" about="Current local git state for this workspace.">
git:
  branch: main
  head: c314523
  upstream: origin/main, up-to-date
  remote: checked 56s ago via git-fetch
  workingTree: clean
  lastCommit: chore(effects): tighten git-state context
</effect>
</effect-mode>

Wrapper and effect attributes:

  • snapshot="current-state-not-instructions": tells the model this is state, not user instruction.
  • resolvedAt: ISO UTC render time.
  • localZone: IANA local timezone.
  • id: stable global:<id>, project:<id>, or ephemeral session:<id> effect identity.

The wrapper timestamp replaces separate clock effects for most uses. Omitted normal/default fields mean nothing notable for bundled effects; custom effect stdout remains freeform.

Failed effects

Failed effects stay terse and actionable in model context:

<effect id="project:git-state" about="Current local git state for this workspace." status="error">
unavailable: command exited 128
reason: fatal: not a git repository
agentAction: Explain that project:git-state context is unavailable; continue without assuming it. Suggest the user run /effects-debug if details matter.
</effect>

Full stdout/stderr, command, cwd, duration, and truncation details are debug-only.

Recipes

These snippets are individual effect objects you can place in the effects array.

Bundled git state

{
  "id": "git-state",
  "about": "Current local git state for this workspace.",
  "description": "Concise local git state snapshot for this workspace.",
  "command": "node node_modules/effect-mode/scripts/git-state.mjs",
  "ttlMs": 0,
  "timeoutMs": 2000,
  "maxBytes": 12000,
  "options": {
    "remoteMode": "background",
    "remoteTtlMs": 900000,
    "remoteErrorTtlMs": 300000,
    "remoteTimeoutMs": 15000
  }
}

Top-level workspace files

{
  "id": "workspace-files",
  "about": "Top-level workspace files.",
  "command": "find . -maxdepth 2 -type f | sort | head -80",
  "ttlMs": 30000,
  "maxBytes": 8000
}

Screenshot / image effects

Set format: "image" when an effect prints a single image file path. The extension reads the image, encodes it as base64, and injects it as a separate multimodal image message alongside the compact XML summary.

{
  "id": "app-screenshot",
  "about": "Latest screenshot of the locally running web app.",
  "format": "image",
  "command": "bash .pi/scripts/screenshot-effect.sh",
  "ttlMs": 5000,
  "timeoutMs": 15000,
  "maxBytes": 4000
}

Supported image extensions: png, jpg/jpeg, gif, webp. The image message carries a short text label plus the base64 payload. If the file is missing or unreadable, the effect falls back to XML error text in the model context.

Package manager snapshot

{
  "id": "package-scripts",
  "about": "Available package scripts for this workspace.",
  "command": "node -e \"const p=require('./package.json'); for (const [k,v] of Object.entries(p.scripts||{})) console.log(k+': '+v)\"",
  "ttlMs": 30000,
  "maxBytes": 4000
}

Script options via environment

Use options for small scalar knobs. They are passed as JSON in PI_EFFECT_OPTIONS_JSON, not interpolated into the shell command.

{
  "id": "recent-files",
  "about": "Recently changed source files.",
  "command": "node -e \"const opts=JSON.parse(process.env.PI_EFFECT_OPTIONS_JSON||'{}'); const limit=Number(opts.limit||20); require('child_process').execFileSync('git',['diff','--name-only','HEAD'],{stdio:'inherit'}); console.log('limit:', limit)\"",
  "ttlMs": 10000,
  "maxBytes": 4000,
  "options": {
    "limit": 20,
    "includeUntracked": true
  }
}

options values must be scalar: string, number, boolean, or null. Arrays and nested objects are rejected.

Agent-authored session effects

Agents can call the effect_mode_session_effect tool to create, replace, or delete ephemeral session-scoped effects. These effects live only in extension memory and disappear on reload/restart. They are not written to .pi/effects.json.

A set operation writes a generated TypeScript file under the OS temp directory, executes it immediately, and registers it only if execution succeeds within the configured timeout. Reusing an id replaces the prior session effect; failed replacements leave the old effect intact.

Example tool payload:

{
  "operation": "set",
  "id": "package-scripts",
  "about": "Available package scripts for the current package.",
  "code": "const pkg = JSON.parse(await ctx.fs.readText('package.json'));\nreturn pkg.scripts ?? {};",
  "cwd": "packages/effect-mode",
  "ttlMs": 30000
}

Authored code is a TypeScript function body. The normalized return value is the model-facing output; if there is no return value, stdout is used. Objects and arrays are rendered as pretty JSON.

Available ctx API:

type EffectCtx = {
  id: string;
  scopedId: string;
  cwd: string;
  projectRoot: string;
  options: Record<string, string | number | boolean | null>;
  $: (strings: TemplateStringsArray, ...values: Array<string | number | boolean>) => Promise<{
    ok: boolean;
    exitCode: number | null;
    stdout: string;
    stderr: string;
    durationMs: number;
    command: string;
  }>;
  fs: {
    readText(path: string): Promise<string>;
    exists(path: string): Promise<boolean>;
    list(path: string): string[];
  };
};

ctx.$ is tagged-template only. Interpolated scalar values are shell-quoted as single arguments; null/undefined interpolation is rejected. It uses a minimal environment and the effect cwd. ctx.fs is read-only, non-recursive for list, and path-constrained to the effect cwd.

Session effect limits:

| Field | Default | Limit | | --- | --- | --- | | code | required | 20,000 chars | | ttlMs | 2000 | 0..300000; 0 means no success cache | | errorTtlMs | 10000 | 0..300000; 0 means no error cache | | timeoutMs | 3000 | 100..30000 | | maxBytes | 12000 | 0..50000 |

The runtime is Bun first when available, then Node if a cached probe confirms native TypeScript execution. If neither runtime can execute .ts files, the tool returns an environment error and does not register the effect. just-bash is installed as a package dependency for future/implementation use, while authored code should use only ctx.$.

Session effects are guardrailed code execution, not a security sandbox. The tool rejects obvious unsupported patterns such as imports, require, process.env, direct child-process use, and filesystem writes, but those checks are lint-like guardrails. Effects are intended to observe state; shell commands can still mutate if authored that way.

Commands

/effects
  Shows a navigable list of enabled global, project, and session effects.
  Select an effect and press Enter to view the model-facing content inside that effect's XML tags.

/effects-debug
  Uses the same navigation.
  Enter opens diagnostics: config, command or session script path, cwd, status, exit code, age, duration, ttl, raw stdout/stderr, truncation, bounded session code preview, and compact rendered form.

/effects-debug does not rerun commands with script-specific debug flags. To inspect verbose bundled git output, configure or run node node_modules/effect-mode/scripts/git-state.mjs --debug.

Configuration reference

Create project effects in .pi/effects.json, or global effects in ~/.pi/agent/effects.json for effects available in every project.

| Field | Type | Default | Description / model-context impact | | --- | --- | --- | --- | | id | string | required | Unique slug-like id; rendered as global:<id> or project:<id>. | | command | string | required | Shell command executed for the effect. | | about | string | none | Short model-facing explanation; rendered as the effect about attribute. | | description | string | none | Human/debug explanation; used as about fallback when about is omitted. | | cwd | string | project | project or relative path inside project/config root. | | ttlMs | number | 2000 | Success cache TTL; 0 executes every model call. | | errorTtlMs | number | 10000 | Failed-result cache TTL. | | timeoutMs | number | 3000 | Per-effect timeout. | | maxBytes | number | 12000 | Combined stdout/stderr render budget; tail-truncated. | | enabled | boolean | true | Disabled effects are omitted from model context and shown disabled in debug. | | includeMetadata | boolean | ignored | Reserved for compatibility with existing configs; model context is always compact. | | format | string | "text" | "text" renders stdout as XML text. "image" reads stdout as an image file path and injects a separate image message. | | options | object | {} | Scalar values passed through PI_EFFECT_OPTIONS_JSON. |

Unknown fields are rejected. Invalid config blocks all effects and injects a compact diagnostic message.

Effect environment

Each command inherits pi's environment plus:

| Variable | Value | | --- | --- | | PI_EFFECT_ID | Effect id from config. | | PI_EFFECT_SCOPE | global or project. | | PI_EFFECT_CWD | Absolute resolved working directory. | | PI_EFFECT_OPTIONS_JSON | JSON string of scalar options, or {}. |

Options are passed only through the child-process environment, not interpolated into the shell command.

Bundled git-state

node node_modules/effect-mode/scripts/git-state.mjs provides a compact local git snapshot tuned for model context.

Compact default output

By default, it does not fetch and renders from local refs:

git:
  branch: main
  head: c314523
  upstream: origin/main, up-to-date
  remote: local refs only; no remote refresh configured
  workingTree: clean
  lastCommit: chore(effects): tighten git-state context

Abnormal fields such as dirty files, stashes, missing upstreams, linked worktrees, remote refresh failures, and option warnings are preserved.

Debug output

Use --debug or --verbose for diagnostic output:

node node_modules/effect-mode/scripts/git-state.mjs --debug
node node_modules/effect-mode/scripts/git-state.mjs --verbose

Background remote checks

Opt into low-latency background remote checks through effect options:

"options": {
  "remoteMode": "background",
  "remoteTtlMs": 900000,
  "remoteErrorTtlMs": 300000,
  "remoteTimeoutMs": 15000,
  "remoteLockTtlMs": 120000
}

Supported remoteMode values are off and background. Background mode renders immediately from local refs/cache, then starts a detached worker when stale. The worker runs git fetch --prune --no-tags --quiet origin with GIT_TERMINAL_PROMPT=0, stores concise cache/lock files under the git common dir, and intentionally mutates local remote-tracking refs when opted in.

Omitted defaults

Compact output omits normal/default details so unusual state stands out:

  • clean stash (stash: none)
  • zero change counts
  • no changed files
  • current worktree row
  • no linked worktrees
  • normal origin/root/cwd details

Security model

  • Configured global/project effects execute arbitrary shell commands through the platform shell.
  • Configured global/project commands inherit pi's environment and permissions.
  • Agent-authored session effects execute generated TypeScript scripts in a child process with a minimal allowlisted environment. They are guardrailed, not sandboxed.
  • Only enable project effects from trusted repositories.
  • Global effects in ~/.pi/agent/effects.json run across projects.
  • Do not put secrets in effect stdout; successful stdout is sent to the model.
  • Background git-state remote checks run git fetch and mutate remote-tracking refs when opted in.
  • Prefer small, bounded, read-only commands; set timeoutMs and maxBytes.

Troubleshooting

No effect-mode context is injected

Verify the package is installed, the config file is in .pi/effects.json or ~/.pi/agent/effects.json, effects are enabled, and /effects shows enabled effects.

Config invalid

Unknown fields are rejected. Run /effects-debug and validate your config against schemas/effects.schema.json.

Effect command fails or times out

Inspect /effects-debug, check cwd, increase timeoutMs if the command is legitimately slow, or simplify the command.

Output is too large or missing earlier lines

maxBytes tail-truncates combined stdout/stderr. Increase the budget or make the command emit a shorter summary.

Remote state looks stale

Background mode renders immediately from cache/local refs, then refreshes asynchronously. Run /effects again after the refresh completes.

Status and roadmap

Implemented now:

  • global ~/.pi/agent/effects.json and project-local .pi/effects.json
  • sequential effect execution
  • per-effect TTL, error TTL, timeout, max output bytes, and scalar options
  • compact model-context rendering with ISO UTC resolvedAt and IANA localZone
  • /effects navigable model-facing content command
  • /effects-debug navigable diagnostic command
  • JSON Schema at schemas/effects.schema.json

Intentionally deferred:

  • durable persisted session effects
  • user-facing session effect lifecycle commands
  • deterministic shell selection
  • gh, git ls-remote, and synchronous remote checks for git-state