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

argocd-api-client

v1.7.1

Published

TypeScript client for the Argo CD REST API

Readme

argocd-api-client

TypeScript client for the official Argo CD REST API. Works in Node.js 18+ and browsers via fetch.

Maintainers and contributors: see Architecture for system boundaries, request lifecycle, extension guidance, and design decisions.

Argo CD exposes Swagger docs at /swagger-ui on each Argo CD server. Argo CD authenticates API requests with JWTs; pass the JWT in the Authorization header as Bearer <jwt>.

Compatibility

The minimum guaranteed Argo CD version is v3.5.1, using the API contract pinned to that exact stable release. Older versions may work on a best-effort basis but are not covered by the compatibility guarantee. The current test suite uses mocked fetch responses and does not claim live-server version coverage.

See Argo CD compatibility for the authoritative support baseline, portable versus version-gated endpoint rules, contract verification status, and deprecation policy.

Install

npm install argocd-api-client

Quick Start

import { ArgoCdClient } from 'argocd-api-client';

const argocd = new ArgoCdClient({
  baseUrl: 'https://argocd.example.com',
  token: process.env.ARGOCD_TOKEN,
});

const apps = await argocd.applications.list({ project: ['default'] });
console.log(apps.items.map((app) => app.metadata?.name));

Login

const argocd = await ArgoCdClient.fromCredentials({
  baseUrl: 'https://argocd.example.com',
  username: 'admin',
  password: 'password',
});

The client stores the credentials internally and automatically refreshes the session on 401 responses.

Resources

// Applications
await argocd.applications.list({ project: ['default'] });
await argocd.applications.get('guestbook', { project: 'default' });
await argocd.applications.create({ metadata: { name: 'guestbook' } });
await argocd.applications.update('guestbook', { metadata: { name: 'guestbook' } });
await argocd.applications.patch('guestbook', { spec: {} });
await argocd.applications.sync('guestbook', { revision: 'main' });
await argocd.applications.revisionMetadata('guestbook', 'v2.1.0');
// → ArgoCdRevisionMetadata  { author, date, tags, message }

await argocd.applications.terminateSync('guestbook');
await argocd.applications.wait('guestbook', { health: true, timeout: '60s' });
// → ArgoCdApplication  returned once the app reaches the desired state

await argocd.applications.deleteResource('guestbook', {
  kind: 'Pod',
  resourceName: 'api-abc123',
  version: 'v1',
  namespace: 'default',
  force: true,
});
await argocd.applications.rollback('guestbook', { id: 3 });
await argocd.applications.deleteByName('guestbook');

// Application observability
const tree = await argocd.applications.resourceTree('guestbook');
const managed = await argocd.applications.managedResources('guestbook');
const desired = await argocd.applications.manifests('guestbook', { revision: 'main' });
const logs = await argocd.applications.logs('guestbook', { container: 'main', tailLines: 100 });
// logs → ArgoCdLogEntry[]  (streamed NDJSON, returned as an array)

// Consume logs incrementally without buffering the full response
for await (const entry of argocd.applications.logsStream('guestbook', {
  container: 'main',
  follow: true,
})) {
  console.log(entry.content);
}

// Convenience methods
await argocd.applications.images('guestbook');
// → string[]  unique container images across all resources

await argocd.applications.pods('guestbook');
// → ArgoCdPod[]  live pods with phase, nodeName and container specs/status

await argocd.applications.containers('guestbook');
// → ArgoCdContainer[]  all containers with podName and raw resources.requests/limits

const allocation = await argocd.applications.resourceAllocation('guestbook');
// → requests/limits normalized for CPU, memory and ephemeral storage
// → totals per app, live Pod and assigned node
// Requests follow scheduler rules for init containers, native sidecars, Pod overhead and
// Pod-level resources. This is declared allocation, not current resource usage or cluster capacity.

const insights = await argocd.applications.insights('guestbook');
// → health, sync, revision, images, allocation and actionable warnings for mutable images,
//   missing requests/limits, restarts, Warning events, drift and orphaned resources

const before = await argocd.applications.snapshot('guestbook');
const preview = await argocd.applications.plan('guestbook', { revision: 'v2' });
// plan() renders manifests and uses Argo CD server-side dry-run diff; it does not mutate resources

// Fleet operations
const bulk = await argocd.applications.syncMany(['api', 'worker'], {
  concurrency: 2,
  sync: { prune: true },
  wait: true,
  waitFor: { health: true },
});
// → one fulfilled/rejected result per application; failures do not hide sibling results

for await (const app of argocd.applications.iterate({ project: ['production'] })) {
  console.log(app.metadata?.name);
}

const stopWatching = new AbortController();
for await (const app of argocd.applications.watch(
  { project: ['production'], intervalMs: 5_000 },
  stopWatching.signal,
)) {
  console.log('Application changed:', app.metadata?.name);
}

const fleet = await argocd.applications.fleetSummary({ project: ['production'] });
// → total applications plus health/sync counts and original application records

await argocd.applications.nodes('guestbook');
// → ArgoCdNode[]  Kubernetes nodes hosting the app's pods (osImage, architecture, kernelVersion…)

await argocd.applications.health('guestbook');
// → ArgoCdApplicationHealth  { status: 'Healthy' | 'Degraded' | …, message? }

await argocd.applications.diff('guestbook');
// → ArgoCdManagedResource[]  only resources whose live state differs from target

await argocd.applications.events('guestbook');
// → ArgoCdEvent[]  Kubernetes events for the application or a specific resource

// Live-resource operations and Argo CD resource customizations
await argocd.applications.getResource('guestbook', {
  group: 'apps',
  version: 'v1',
  kind: 'Deployment',
  namespace: 'default',
  resourceName: 'api',
});
await argocd.applications.resourceActions('guestbook', {
  kind: 'Deployment',
  namespace: 'default',
  resourceName: 'api',
});
await argocd.applications.runResourceAction('guestbook', {
  action: 'restart',
  kind: 'Deployment',
  namespace: 'default',
  resourceName: 'api',
});

// ApplicationSets
await argocd.applicationSets.list();
await argocd.applicationSets.get('my-set');
await argocd.applicationSets.create({ metadata: { name: 'my-set' } });
await argocd.applicationSets.update('my-set', { metadata: { name: 'my-set' } });
await argocd.applicationSets.deleteByName('my-set');

// Projects
await argocd.projects.list();
await argocd.projects.get('default');
await argocd.projects.create({ metadata: { name: 'default' } });
await argocd.projects.update('default', { metadata: { name: 'default' } });
await argocd.projects.deleteByName('default');
await argocd.projects.events('default');
// → ArgoCdEvent[]  Kubernetes events for the project

await argocd.projects.repositories('default');
// → ArgoCdRepositoryList  repositories associated with the project

// Repositories
await argocd.repositories.list();
await argocd.repositories.get('https://github.com/acme/app.git');
await argocd.repositories.create({ repo: 'https://github.com/acme/app.git' });
await argocd.repositories.refs('https://github.com/acme/app.git');
await argocd.repositories.apps('https://github.com/acme/app.git', { revision: 'main' });
// → ArgoCdRepoAppsResponse  { items: [{ type, path }] }

await argocd.repositories.deleteByRepo('https://github.com/acme/app.git');

// Clusters
await argocd.clusters.list();
await argocd.clusters.get('https://kubernetes.default.svc');
await argocd.clusters.create({ name: 'prod', server: 'https://prod.k8s.io' });
await argocd.clusters.update('https://prod.k8s.io', { name: 'prod' });
await argocd.clusters.deleteByServer('https://kubernetes.default.svc');
await argocd.clusters.invalidateCache('https://kubernetes.default.svc');
// → ArgoCdCluster  cluster with refreshed cache state

// Accounts
await argocd.accounts.list();
await argocd.accounts.get('admin');
await argocd.accounts.canI('applications', 'get', '*');
await argocd.accounts.updatePassword({ name: 'admin', currentPassword: 'old', newPassword: 'new' });
await argocd.accounts.listTokens('admin');
// → ArgoCdAccountTokenList  { items: ArgoCdAccountToken[] }

await argocd.accounts.createToken('admin', { expiresIn: '24h', id: 'ci-token' });
// → ArgoCdAccountTokenCreated  { token, id, issuedAt, expiresAt }

await argocd.accounts.deleteToken('admin', 'token-id');

// Repository credential templates
await argocd.repoCreds.list();
await argocd.repoCreds.create({ url: 'https://github.com/acme', username: 'bot', sshPrivateKey: '...' });
await argocd.repoCreds.deleteByUrl('https://github.com/acme');

// Repository certificates (TLS/SSH)
await argocd.certificates.list();
await argocd.certificates.create([{ serverName: 'github.com', certType: 'ssh', certSubType: 'ssh-rsa', certData: '...' }]);
await argocd.certificates.delete({ hostNamePattern: 'github.com', certType: 'ssh' });

// GPG keys (commit signature verification)
await argocd.gpgKeys.list();
// → ArgoCdGpgKeyList  { items: Record<keyID, ArgoCdGpgKey> }

await argocd.gpgKeys.create({ keyData: '-----BEGIN PGP PUBLIC KEY BLOCK-----...' });
// → ArgoCdGpgKeyCreateResponse  { created: Record<keyID, ArgoCdGpgKey>, skipped: string[] }

await argocd.gpgKeys.create({ keyData: '...' }, { upsert: true });
await argocd.gpgKeys.deleteByKeyId('A1B2C3D4');

// Server settings (read-only)
await argocd.settings.get();
// → ArgoCdSettings  { url, appLabelKey, statusBadgeEnabled, ... }

// Server version
await argocd.version.get();
// → ArgoCdVersion  { Version, BuildDate, GitCommit, GitTag, GoVersion, Platform, ... }

// Cached compatibility query with typed flags
const capabilities = await argocd.capabilities();
if (capabilities.features.applicationWatchStream) {
  // The version policy expects the native Application watch endpoint to exist.
}

// Ignore the cached result and query the server again
await argocd.capabilities({ refresh: true });

// Session
await argocd.userInfo();
// → ArgoCdUserInfo  { loggedIn, username, iss, groups }

await argocd.deleteSession();
// Invalidates the current token on the server (logout)

Abort Requests

Every request method accepts an optional AbortSignal as its final argument.

const controller = new AbortController();

const apps = await argocd.applications.list(
  { project: ['default'] },
  controller.signal,
);

controller.abort();

Events

Use .on('request', callback) to observe every HTTP request made by the client — useful for logging, metrics, and error tracking.

argocd.on('request', (event) => {
  console.log(`[${event.method}] ${event.url} → ${event.statusCode} (${event.durationMs}ms)`);
  if (event.error) console.error('Request failed:', event.error.message);
});

The RequestEvent object includes:

| Field | Type | Description | | --- | --- | --- | | url | string | Full URL requested | | method | 'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE' | HTTP method | | startedAt | Date | When the request started | | finishedAt | Date | When the request finished | | durationMs | number | Duration in milliseconds | | statusCode | number \| undefined | HTTP status code (absent on network errors) | | error | Error \| undefined | Set on any failed request |

Multiple listeners are supported and called in registration order. .on() returns this for chaining:

argocd
  .on('request', (e) => metrics.record(e.durationMs))
  .on('request', (e) => { if (e.error) sentry.capture(e.error); });

Token auto-refresh on 401 is transparent: only one event is emitted per logical operation, reflecting the final outcome.

Express Integration

Install Express and (optionally) its types:

npm install express
npm install -D @types/express

Create a shared client instance and expose Argo CD resources through your own API:

// src/argocd.ts
import { ArgoCdClient } from 'argocd-api-client';

export const argocd = new ArgoCdClient({
  baseUrl: process.env.ARGOCD_BASE_URL!,
  token: process.env.ARGOCD_TOKEN,
});
// src/routes/apps.ts
import { Router } from 'express';
import { argocd } from '../argocd';

const router = Router();

// GET /apps?project=default
router.get('/', async (req, res, next) => {
  try {
    const project = req.query.project
      ? [String(req.query.project)]
      : undefined;

    const apps = await argocd.applications.list(
      { project },
      req.signal, // forward the request's AbortSignal
    );

    res.json(apps.items?.map((app) => ({
      name: app.metadata?.name,
      namespace: app.metadata?.namespace,
      health: app.status?.health?.status,
      sync: app.status?.sync?.status,
    })));
  } catch (err) {
    next(err);
  }
});

// POST /apps/:name/sync
router.post('/:name/sync', async (req, res, next) => {
  try {
    const result = await argocd.applications.sync(req.params.name, {
      revision: req.body.revision ?? 'HEAD',
    });
    res.json(result);
  } catch (err) {
    next(err);
  }
});

export default router;
// src/index.ts
import express from 'express';
import appsRouter from './routes/apps';

const app = express();
app.use(express.json());
app.use('/apps', appsRouter);

app.listen(3000, () => console.log('Listening on :3000'));

Environment variables

ARGOCD_BASE_URL=https://argocd.example.com
ARGOCD_TOKEN=<jwt>

If you don't have a static token, use fromCredentials to authenticate and get a ready-to-use client in one call:

import { ArgoCdClient } from 'argocd-api-client';

export const argocd = await ArgoCdClient.fromCredentials({
  baseUrl: process.env.ARGOCD_BASE_URL!,
  username: process.env.ARGOCD_USER!,
  password: process.env.ARGOCD_PASS!,
});

Token refresh

Clients created with fromCredentials store the credentials internally and handle token expiry automatically:

// Automatic — a 401 response triggers a session refresh and retries the request once
await argocd.applications.list();

// Manual — force a refresh before the token expires
await argocd.refreshSession();

Clients created with new ArgoCdClient({ token }) do not store credentials; calling refreshSession() on them throws an error.

Local session state can be managed without a server request:

argocd.setToken(nextToken); // keeps stored refresh credentials
argocd.hasCredentials(); // true for clients created with fromCredentials
argocd.clearSession(); // clears both local token and credentials

deleteSession() invalidates the server session but retains local state for backward compatibility. Call clearSession() afterward when the client must forget its credentials.

Express + createSession

This pattern exposes a POST /auth/login endpoint that exchanges credentials for an Argo CD JWT, then uses that token on every subsequent request via a middleware-created client.

// src/routes/auth.ts
import { Router } from 'express';
import { ArgoCdClient } from 'argocd-api-client';

const router = Router();

// POST /auth/login  { "username": "admin", "password": "..." }
router.post('/login', async (req, res, next) => {
  try {
    const { username, password } = req.body as {
      username: string;
      password: string;
    };

    if (!username || !password) {
      res.status(400).json({ error: 'username and password are required' });
      return;
    }

    const client = new ArgoCdClient({ baseUrl: process.env.ARGOCD_BASE_URL! });
    const { token } = await client.createSession({ username, password });

    res.json({ token });
  } catch (err) {
    next(err);
  }
});

export default router;
// src/middleware/argocd.ts
import { RequestHandler } from 'express';
import { ArgoCdClient } from 'argocd-api-client';

declare global {
  namespace Express {
    interface Request {
      argocd: ArgoCdClient;
    }
  }
}

export const argocdMiddleware: RequestHandler = (req, res, next) => {
  const auth = req.headers.authorization;

  if (!auth?.startsWith('Bearer ')) {
    res.status(401).json({ error: 'Missing or invalid Authorization header' });
    return;
  }

  req.argocd = new ArgoCdClient({
    baseUrl: process.env.ARGOCD_BASE_URL!,
    token: auth.slice(7),
  });

  next();
};
// src/routes/apps.ts
import { Router } from 'express';
import { argocdMiddleware } from '../middleware/argocd';

const router = Router();
router.use(argocdMiddleware);

// GET /apps
router.get('/', async (req, res, next) => {
  try {
    const apps = await req.argocd.applications.list({}, req.signal);
    res.json(apps.items?.map((app) => ({
      name: app.metadata?.name,
      health: app.status?.health?.status,
      sync: app.status?.sync?.status,
    })));
  } catch (err) {
    next(err);
  }
});

export default router;
// src/index.ts
import express from 'express';
import authRouter from './routes/auth';
import appsRouter from './routes/apps';

const app = express();
app.use(express.json());
app.use('/auth', authRouter);
app.use('/apps', appsRouter); // protected by argocdMiddleware

app.listen(3000, () => console.log('Listening on :3000'));

Flow:

# 1. Obtain a token
curl -X POST http://localhost:3000/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"secret"}'
# → { "token": "<jwt>" }

# 2. Use the token in subsequent requests
curl http://localhost:3000/apps \
  -H 'Authorization: Bearer <jwt>'

Benchmarks

npm run bench

The benchmark suite uses mocked fetch responses, so it never calls a real Argo CD server. It covers client construction, resource access, GET/POST/DELETE request paths, query params, error handling, AbortSignal, and memory pressure.

API Coverage

| Service | Client property | Methods | | --- | --- | --- | | SessionService | — | createSession · deleteSession · userInfo | | ApplicationService | applications | list · iterate · watch · fleetSummary · get · create · update · patch · sync · syncMany · terminateSync · terminateOperation · wait · rollback · deleteByName · getResource · patchResource · deleteResource · resourceActions · runResourceAction · resourceLinks · refresh · manifests · serverSideDiff · plan · snapshot · revisionMetadata · chartDetails · resourceTree · managedResources · logs · images · pods · containers · resourceAllocation · insights · nodes · health · diff · events | | ApplicationSetService | applicationSets | list · get · create · update · deleteByName | | ProjectService | projects | list · get · create · update · deleteByName · events · repositories | | RepositoryService | repositories | list · get · create · refs · apps · deleteByRepo | | RepoCredsService | repoCreds | list · create · deleteByUrl | | ClusterService | clusters | list · get · create · update · deleteByServer · invalidateCache | | AccountService | accounts | list · get · canI · updatePassword · listTokens · createToken · deleteToken | | CertificateService | certificates | list · create · delete | | GPGKeyService | gpgKeys | list · create · deleteByKeyId | | SettingsService | settings | get | | VersionService | version | get |

See ROADMAP.md for planned additions. Types keep Argo CD/Kubernetes payloads extensible with Record<string, unknown> for areas where server versions vary.