JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 50
  • Score
    100M100P100Q65600F
  • License MIT

Content Manager — fetch instruction, prompt, and block content from local folder or git repo

Package Exports

  • nx-content

Readme

nx-content

Content Manager — resolve instruction, prompt, and block content from a local folder or a Git repo. Built for Node.js 18+, TypeScript strict mode, ESM + CJS.

Use it to:

  • Resolve content keys (e.g. skills/my-skill.instructions) to file content
  • Support local and Git backends with configurable precedence (dev = local wins, prod = git wins)
  • Inline block includes with << path >> in files
  • Cache resolved content in memory (TTL configurable)
  • Drop in where a content registry is expected (e.g. ai-gateway)

Install

npm install nx-content

Requirements: Node.js >= 18.


Quick start

import { ContentResolver, init, getDefaultResolver } from 'nx-content';

// 1. Initialize (creates content root + readme)
const manager = await init({ localRoot: './.content' });

// 2. Resolver (recommended API)
const resolver = new ContentResolver({ localRoot: './.content' });
const { text } = await resolver.resolveInstructions('skills/my-skill.instructions');

// 3. Singleton from env (e.g. CONTENT_REGISTRY_LOCAL_ROOT)
const defaultResolver = getDefaultResolver();
const prompt = (await defaultResolver.resolvePrompt('prompts/default')).text;

Content keys

  • A key is a path relative to the content root, without file extension.
  • Resolution tries .md then .json when the key has no extension (or when the extension is not .md/.json).

Examples:

Key Resolved file
skills/my-skill.instructions skills/my-skill.instructions.md (or .json)
prompts/summarize prompts/summarize.md
blocks/greeting blocks/greeting.md
readme.md readme.md (exact)

Key detection: A string is treated as a key only if, after trim, it is non-empty and contains no whitespace. Otherwise it is treated as literal text and returned as-is.


Block includes

Inside any content file you can include another file with double angle brackets:

<< blocks/greeting >>

The manager replaces << path >> with that file’s full content. Paths use / or \; they are relative to the content root. Nested includes are supported (max depth 10; circular includes throw).


API

Method Description
resolveInstructions(key) Resolve instruction key → ResolvedContent. If not a key, returns { text: key }.
resolvePrompt(key) Same for prompt key.
hasInstructionKey(key) true if the key exists (no full read).
resolveInstructionsBlock(blockName, agentId, taskTypeId?, configOverride?) Resolve a block with fallback: task → agent → generic. If configOverride is non-empty, returns it.
normalizeSkillId(skillId) Normalize to canonical key (e.g. skills/<id>.instructions).
isKey(value) Whether the string is a content key (no whitespace, non-empty).
getContentRoot() Absolute content root path.
getContentRegistry() / getContentManager() Underlying ContentManager when enabled.
isEnabled() Whether the manager is configured.

ContentManager

Method Description
resolve(key) Resolve key to ResolvedContent (cache + block includes).
exists(key) Whether the key exists.
normalizeSkillId(skillId) Canonical key for skill.
resolveInstructionsBlock(blockName, agentId, taskTypeId?, configOverride?) Block resolution with fallback.
ping() Backend reachable (e.g. root exists).
listAll() All relative paths under the root.
invalidateKey(key) / invalidateAll() Clear cache.
getContentRoot() Absolute local root.
isEnabled() Whether a backend is configured.

Functions

Function Description
init(config?) Create content root dir, write readme, return ContentManager. Idempotent.
isKey(value) Key detection (no whitespace, non-empty).
isKeyLike(value) Heuristic: content looks like a key (safety net).
runDiagnostics(manager) Returns DiagnosticsResult: enabled, localRoot, backendReachable, availableKeys, error.
getDefaultResolver() Singleton ContentResolver from env.

Types

  • ContentManagerConfiglocalRoot, gitRepoUrl, gitToken, gitBranch, gitClonePath, mode, cacheTtlMs
  • ResolvedContent{ text: string; metadata?: ContentMetadata }
  • ContentMetadatakey, path, backend, version, rawContent
  • ContentBackend — interface: read, exists, listAll, ping, location
  • DiagnosticsResultenabled, localRoot, backendReachable, availableKeys, error
  • GitBackendConfigrepoUrl, token?, branch?, clonePath?

Errors (all extend ContentManagerError, have .code)

Class Code When
ContentNotFoundError CONTENT_NOT_FOUND Key not found in any backend.
ContentManagerNotAvailableError CONTENT_MANAGER_NOT_AVAILABLE No backend configured.
ContentBackendError CONTENT_BACKEND_ERROR I/O or git failure.
ContentInvalidError CONTENT_INVALID Stored content is key-like or empty (never return key as content).

Configuration

Options (ContentManagerConfig)

Option Env fallback Default Description
localRoot CONTENT_REGISTRY_LOCAL_ROOT <cwd>/.content Content root (resolved to absolute).
gitRepoUrl GITHUB_REPO_URL Git repo URL (SSH or HTTPS). Omit to disable git.
gitToken GITHUB_TOKEN GitHub PAT for HTTPS.
gitBranch CONTENT_REGISTRY_GIT_BRANCH main Branch to use.
gitClonePath CONTENT_REGISTRY_GIT_LOCAL_CLONE_PATH os.tmpdir()/nx-content-git Local clone path.
mode CONTENT_REGISTRY_MODE dev dev = local wins, prod = git wins.
cacheTtlMs CONTENT_REGISTRY_CACHE_TTL_MS 1 year Cache TTL in ms.

Environment variables

Same names as above; used when the corresponding option is not passed. All paths from config/env are resolved to absolute at init.


.content/
  skills/
    my-skill.instructions.md
  prompts/
    default.md
  blocks/
    greeting.md
    disclaimer.md

Testing

# Unit + integration (local)
npm test

# Integration only
npm run test:integration

# Watch
npm run test:watch

Git backend integration tests run only when GITHUB_TOKEN (and optionally GITHUB_REPO_URL) are set; otherwise they are skipped.


Build

npm run build

Produces:

  • dist/esm/ — ESM
  • dist/cjs/ — CommonJS ("type": "commonjs")
  • dist/types/ — Declaration files

License

MIT