# Dependency Signal Monitor (`ishekofficial/dependency-signal-monitor`) Actor

Reads your repo's dependency manifests through a GitHub connector, scores each dependency for abandonment risk, and opens an issue listing the ones that are dying.

- **URL**: https://apify.com/ishekofficial/dependency-signal-monitor.md
- **Developed by:** [Abhishek Khanra](https://apify.com/ishekofficial) (community)
- **Categories:** Developer tools, Integrations
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Dependency Signal Monitor

### Find out which of your dependencies is quietly dying, before it becomes your problem

**Your security scanner tells you when a package is broken. Nothing tells you when a package has been abandoned.** This reads the dependencies in your repository, checks whether anyone is still looking after each one, and opens an issue in your repository listing the ones that look like they have stopped.

Tools like PkgWatch already score package health well. What they cannot do is read your repository, work out what to check, and file the result back in your own issue tracker without you handing anybody a token. That is what this does.

***

### Why this matters

A package you depend on gets abandoned. Nobody announces it. It keeps working, so you never notice.

Two years later a security problem turns up in it, and there is nobody left to fix it. Now you are doing an emergency migration under pressure instead of a calm one you could have planned twelve months earlier.

Everything you would need to see it coming is public. When it was last released. How many people are left maintaining it. Whether the project has been archived. Whether downloads are falling away. Nobody is watching it for you.

Express, one of the most used packages on the internet, depends on `escape-html`. It has had no new version since September 2015 and one person maintains it.

***

### Features

- **Reads your actual dependencies**, so you never maintain a list by hand
- **Tells you why, in a sentence**, not just a number. "No new version since September 2015, almost 11 years ago. Only one person looks after it"
- **Separates dying from finished.** A tiny package with no releases in years is often complete, not abandoned. This says so instead of raising a false alarm
- **Files the result in your own repository**, so it lands where you already work
- **Updates the same issue every run** instead of filling your tracker with duplicates
- **Notices when you close the issue** and starts a fresh one rather than editing something you have dealt with
- **Never sees your GitHub token.** Apify holds it and this Actor is only permitted three specific actions
- **Dry run by default**, so you can read the report before anything is written anywhere

***

### Usage

1. **Connect GitHub.** In Apify Console go to **Settings, API & Integrations, MCP connectors**, click **Add connector** and paste `https://api.githubcopilot.com/mcp/`. Choose **API key or bearer token** and paste a GitHub personal access token with Contents read, Issues read and write.
2. **Pick the repository to check.** Any repository you can read, including public ones you do not own.
3. **Choose where the issue goes.** By default it goes into the repository you checked. Set the two override fields to send it somewhere else.
4. **Run it with Dry run on** and read the report in the log.
5. **Turn Dry run off** when you are happy with it.
6. **Put it on a schedule.** Weekly is plenty. Abandonment happens over months.

#### Example input

| Field | Value |
| :--- | :--- |
| GitHub connector | `github-dependency-monitor` |
| Repository owner | `expressjs` |
| Repository name | `express` |
| Include dev dependencies | off |
| Report anything scoring at or below | 45 |
| Dry run | off |

***

### Screenshots

![The issue it opens in your repository](https://raw.githubusercontent.com/IshekKhal/dependency-signal-monitor/main/assets/issue-in-repo.png)
*What lands in your issue tracker. One table for things worth acting on, one for things to keep an eye on.*

![Choosing what to check](https://raw.githubusercontent.com/IshekKhal/dependency-signal-monitor/main/assets/console-input.png)
*Pick a connector and a repository. Everything else has a sensible default.*

![The same issue updated on the next run](https://raw.githubusercontent.com/IshekKhal/dependency-signal-monitor/main/assets/second-run-updates.png)
*The second run edits the issue it opened rather than filing a new one.*

***

### Output

One row per dependency, in the dataset.

| Field | What it is |
| :--- | :--- |
| `name` | Package name |
| `ecosystem` | `npm`, `pypi` or `go` |
| `versionSpec` | The version range in your manifest |
| `scope` | `runtime` or `dev` |
| `healthScore` | 0 to 100. Higher is healthier |
| `riskBand` | `at risk`, `watch` or `healthy` |
| `scoreReason` | Plain English explanation of the score |
| `signalConflict` | Set when the registry and the repository disagree about the package |
| `lowConfidence` | True when we could not check enough to be sure |
| `signals` | Every raw measurement: last release, maintainer count, downloads trend, repository activity |
| `healthScoreWithoutConnectorSignals` | The package's health ignoring your version constraint |
| `connectorContribution` | How much reading your manifest changed the score |

#### Example row

```json
{
  "name": "escape-html",
  "ecosystem": "npm",
  "versionSpec": "^1.0.3",
  "scope": "runtime",
  "healthScore": 35,
  "riskBand": "at risk",
  "scoreReason": "No new version since September 2015, almost 11 years ago. It used to get one about once a year. Nobody has touched the code in almost 4 years. Only one person looks after it, so there is nobody to take over if they stop.",
  "lowConfidence": false,
  "signalConflict": null,
  "signals": {
    "latestVersion": "1.0.3",
    "lastPublishAt": "2015-09-01T21:16:38.000Z",
    "releaseCount": 5,
    "maintainerCount": 1,
    "deprecated": false,
    "downloadsTrend": 0.98,
    "repoUrl": "https://github.com/component/escape-html",
    "archived": false,
    "daysSinceLastPush": 1414
  },
  "healthScoreWithoutConnectorSignals": 35,
  "connectorContribution": 0
}
```

***

### Supported ecosystems

| Manifest | Ecosystem | Status |
| :--- | :--- | :--- |
| `package.json` | npm | Full. Release history, maintainers, deprecation, downloads trend, repository activity |
| `requirements.txt` | PyPI | Full except maintainer count, which PyPI's API does not expose |
| `pyproject.toml` | PyPI | PEP 621 and Poetry tables. PDM and Hatch are not read yet |
| `go.mod` | Go | Last release date and repository activity only. The module proxy exposes no maintainer or download data |

Lock files are not read. The version range in your manifest is what gets checked, because that is what governs what you can receive.

***

### What it does not do

It does not check for security vulnerabilities. Dependabot and `npm audit` already do that well, and they answer a different question.

It cannot tell the difference between a package that has been abandoned and one that is simply finished. Nothing can, from the outside, because the difference is intent. Where the signals disagree it says so and asks you to look, rather than guessing.

# Actor input Schema

## `repoConnector` (type: `string`):

Your authorized GitHub MCP connector. The Actor reads your dependency manifests through it and opens the results issue through the same connection. Your token never reaches the Actor: Apify injects it server-side.

## `runMode` (type: `string`):

Maintenance option. Not shown in the form.

## `repoOwner` (type: `string`):

GitHub username or organization that owns the repository to analyse.

## `repoName` (type: `string`):

The repository whose dependencies you want checked. It does not have to be one you own: public repositories are readable by any token.

## `branch` (type: `string`):

Branch to read manifests from. Leave blank for the repository default.

## `manifestPaths` (type: `array`):

Files to read. Leave empty to auto-detect the standard manifests at the repository root.

## `includeDevDependencies` (type: `boolean`):

Dev dependencies rarely ship to production but a dead build tool still blocks you.

## `maxDependencies` (type: `integer`):

Caps the run. Signals are fetched per dependency, so this is the main cost control.

## `skipRepoSignals` (type: `boolean`):

Maintenance option. Not shown in the form.

## `issueOwner` (type: `string`):

Leave blank to use the analysed repository's owner. Set this when you are monitoring a repository you do not own and want the report filed in your own tracker.

## `issueRepo` (type: `string`):

Leave blank to file the issue in the repository that was analysed.

## `riskThreshold` (type: `integer`):

Health runs 0 to 100, where 100 is healthy. Anything at or below this lands in the issue.

## `dryRun` (type: `boolean`):

On by default. The Actor scores everything and writes the dataset, but does not touch your repository. Turn this off once the output looks right.

## `debugMode` (type: `boolean`):

Adds a line per package showing exactly what was found. Useful if a result looks wrong and you want to see why.

## Actor input object example

```json
{
  "runMode": "analyse",
  "repoOwner": "expressjs",
  "repoName": "express",
  "manifestPaths": [],
  "includeDevDependencies": false,
  "maxDependencies": 60,
  "skipRepoSignals": false,
  "riskThreshold": 45,
  "dryRun": true,
  "debugMode": false
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "repoOwner": "expressjs",
    "repoName": "express",
    "manifestPaths": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("ishekofficial/dependency-signal-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "repoOwner": "expressjs",
    "repoName": "express",
    "manifestPaths": [],
}

# Run the Actor and wait for it to finish
run = client.actor("ishekofficial/dependency-signal-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "repoOwner": "expressjs",
  "repoName": "express",
  "manifestPaths": []
}' |
apify call ishekofficial/dependency-signal-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ishekofficial/dependency-signal-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/ZslMKts1arfsKN2hJ/builds/RmioYQx1SQ74RiIVf/openapi.json
