@package-system

Source packages

How synced filesystem sources contribute markdown packages — recognized layouts, defaults, per-file control, and the security model.

Maturity: stable (85 %)

Ecosystem import. Skills, rules, agents and instruction files in the Claude Code, Cursor, Codex, Gemini and Copilot conventions load straight from any synced source, without an install step and under the same scope as every other package.

  • Imported content is markdown only: hooks and MCP server definitions in a foreign layout are not loaded.
  • Rules are always on; glob-scoped rules are not supported.
  • Skill arguments and per-skill model preferences from other ecosystems are accepted but not applied.

How maturity is measured

A source package is a package contributed by a synced filesystem source rather than an installed directory: when a source — a mounted repository, the agent data tree, or a machine sandbox — is synced into the vector index, markdown files matching the contribution layout group into packages the agent can use. No package.json is required, no install step runs, and no code ever executes from a source — source packages are markdown contributions only: skills, instructions, rules, agents, and docs.

This is the import path for existing agent configuration. A repository that already carries a .claude/, .cursor/, or .github/ folder with skills and rules contributes them to Neuralis agents as-is — sync the source and the folder appears as a package, with the same frontmatter whitelist policy that lets skills written for other platforms load unchanged.

Sync is the prerequisite

An unsynced source contributes nothing. Discovery reads only the vector index — never the live file tree — so a source's packages exist exactly when its files are indexed. The Sources panel surfaces this directly: a source that has never synced shows "Never synced — run a sync to index this source and load its packages". Sync triggers (manual, auto, and interval:<N><s|m|h|d>) are described on memory and sync.

Indexing also captures contribution metadata at sync time: a whitelisted frontmatter set (name, title, description, requiredFeatures, credentials, the metadata vendor-extension map, and allowed-tools — metadata recorded for compatibility and never enforced, allowed-tools advisory on a skill but enforced on an agents/*.md persona, synced ones included), a usability flag for manifests, and a privacy marker for agent-private subtrees. Files that were already indexed before a metadata field existed pick it up through a payload-only refresh on the next regular sync — no re-embedding and no full reindex needed.

How current the answer is

Discovery reads the index through a shared per-project inventory, so repeated stream starts do not re-read the same rows. The inventory holds raw index entries only — never an answer that has already been filtered for a caller — and it is invalidated at the boundary every write passes through, when the start of a write could move a package candidate and again when it finishes. A write that fails or times out invalidates too: a backend that did not answer is not a backend that changed nothing. High-rate writes that cannot affect a package — the chunk rows behind semantic search, files outside every package root — cost nothing. A bounded recovery window covers writes made to the same vector store by something other than this instance; platform config tunes it.

Access is a separate question with a stricter answer: nothing about it is ever reused. Every request re-reads the source's persisted configuration and re-evaluates whether the source is enabled, whether the caller's scope reaches it, and every URI-policy rule, so a revoked permission, a disabled source or a changed role takes effect on the next request — including one already in flight when the change lands.

What is recognized

The indexer assigns contribution categories by path — the same vocabulary packages use everywhere else — and admits a markdown as a contribution by the same rule an installed package uses (see Admission below the table):

Path patternCategory
SKILL.md (any directory)skill
commands/*.md (legacy single-file command form)skill
instructions/**/*.mdinstruction
AGENTS.md, CLAUDE.md, CLAUDE.local.md, GEMINI.md, .github/copilot-instructions.mdinstruction (identity form, opt-in)
rules/**/*.md, .cursor/rules/*.mdc, .cursorrules, .windsurfrulesrule (opt-in)
agents/**/*.md, *.agent.mdagent
docs/**/*.md (READMEs and templates excluded)docs (read on demand)

These patterns match inside well-known tool directories too: .claude, .agents, .cursor, .codex, .gemini, .windsurf, .github, .opencode, .kilo, and .roo are recognized marker directories. Non-contribution content inside them (settings files, themes) is indexed for search but never becomes a contribution.

Admission. The path decides the category; the file's own declaration decides whether it is a contribution. A markdown under agents/, rules/, instructions/ or docs/ — and a *.agent.md anywhere — is a contribution only when its frontmatter carries id or name. Without one it is indexed as a plain file: searchable, never listed as an agent, rule or doc, never summonable. The forms whose filename is the identity by protocol are exempt: SKILL.md (the directory names the skill), commands/*.md, the identity basenames (AGENTS.md, CLAUDE.md, …), .cursorrules, .windsurfrules and .cursor/rules/*.mdc. This is the same rule an installed package's discovery applies, so a folder of reference notes beside a real agent definition costs nothing in any package form; a title: or description: alone never promotes a file. A file that was indexed under the wrong category before this rule existed is corrected on the next full sync, payload-only.

Four manifest filenames are recognized as package-anchor candidates: package.json (only when it carries a neuralis block — a plain application manifest anchors nothing), neuralis.package.json, gemini-extension.json, and a plugin.json sitting directly inside .claude-plugin/, .cursor-plugin/, or .codex-plugin/. .mcp.json / mcp.json and hooks.json are indexed and categorized but are not loaded as runtime contributions — connectors and hooks never come from a source.

How files group into packages

Recognized files group into package roots by precedence — the strongest matching rule wins for a given directory, and every contribution binds to the deepest detected root that encloses it:

  1. Usable manifest — a directory holding a package.json with a neuralis block (or another recognized manifest) anchors that directory as one package. A plain application package.json is not usable and binds nothing.
  2. Marker directory — a .claude/, .cursor/, .github/, or other marker dot-dir becomes one package named after the dot-dir. This is the "import your existing tool folder" rule.
  3. Category directories — a directory holding skills/, instructions/, rules/, agents/, docs/, or commands/ folders becomes a package named after that directory.
  4. Bare skill — a free-standing SKILL.md folder enclosed by no other root becomes a one-skill package.
  5. Source root (restricted) — the source root itself binds only root-level identity files, a root SKILL.md, and files under root-level category directories. Docs never bind to the implicit source-root package, and nested stray files claimed by no rule above stay unloaded — a large multi-project source never collapses into one giant package.

A folder-per-skill layout (skills/a/SKILL.md, skills/b/SKILL.md) stays one package — it does not shatter into one package per skill.

repo://
  .claude/                     → package ".claude" (rule 2)
    skills/review/SKILL.md
    rules/style.md
  packages/helper/
    package.json               → package "helper" (rule 1, neuralis block)
    skills/deploy/SKILL.md
  AGENTS.md                    → source-root package (rule 5, opt-in)

A source package appears in the agent's <packages> overview as its own block after the installed packages, behaves like any other package in the packages editor and the conversation package selector, and obeys the same two visibility gates as every contribution: package enable/disable state and the caller's role and feature grants, deny-by-default (see Features and access).

Defaults and per-file control

Categories carry deliberate defaults — syncing a repository must never silently change agent behavior:

CategoryDefault
Skills, instructions, agentsOn
Rules and identity files (AGENTS.md, CLAUDE.md, …)Opt-in — never injected until explicitly enabled per file
DocsListed, never auto-injected — read on demand like a skill body

The docs posture is server-pinned: frontmatter in a synced file cannot escalate a doc into the system prompt.

Every file in every category is individually toggleable at two scopes:

  • Agent scope — the packages editor in the agent settings. Enabling an opt-in file saves an explicit per-file enable on the agent configuration.
  • Conversation scope — the composer's package selector renders per-file rows, with opt-in files badged.

Precedence is one shared predicate: a disabled package turns everything off; an agent-level per-file off is final (a conversation cannot re-enable it); a conversation-level off wins next; and an opt-in (default-off) file activates only with an explicit enable at either scope. Delegate child runs inherit the parent conversation's file overrides.

The worked example

example-source — one of the three contract examples — is this path in full: no package.json at all, so the folder layout is the whole declaration. It ships skills/, instructions/, rules/, docs/ and a root AGENTS.md, which is exactly the set that shows both default floors side by side, and those floors are narrower than they are usually described:

  • defaultEnabled: false is applied to rule files and identity files only. Skills, instructions and agents from a source stay default-ON.
  • docs are not disabled — they are pinned to activation.invocation: "manual", so they are listed and readable but never injected.

It ships no agents/ folder; the agent category is demonstrated in example-builtin instead, where it can be exercised against a loaded package.

Skills from sources

A source skill activates exactly like a package skill — through execute action="skill" (see Skills) — with source-specific mechanics:

  • Identity. The activation id is the frontmatter id, then name, falling back to the skill's directory name. The display title follows the same chain — a skill row never renders as the literal SKILL.md.
  • Content loads at activation. Discovery carries metadata only; the SKILL.md body is read through the source's connector when the skill activates. If the indexed file no longer exists, activation fails closed with the same not-found result as a skill that never existed.
  • Bundles. scripts/, references/, and assets/ siblings enumerate into the skill's files[] list, advertised in the package overview's [files: …] suffix and the packages editor's file mini-tree — the same bundle contract as installed packages.
  • Collisions are namespaced. A built-in skill id always wins. A colliding source skill stays activatable as <id>.<sourceSlug>, and when two packages of the same source collide, as <id>.<sourceSlug>.<packageKey>.
  • Machine sandboxes. A skill synced from a machine source lives inside the machine container — its activation envelope prints the skill's directory URI, which execute takes as the working directory to run the scripts on that machine. The directory is never reachable from the platform shell.
  • No double loading. A source subtree that belongs to an already-installed package contributes nothing — the installed package's snapshot covers it.

Prompt-injected categories (rules, instructions, agents) hydrate per stream, only for the files that survived every gate, under a strict budget — a disabled or feature-gated file is never read at all.

Security model

Source packages sit behind the same deny-by-default boundary as everything else:

  • URI policy, per root and per file. The source's persisted URI policy is evaluated for every package root and every member file against the caller's real identity. A denied subtree's package is simply absent — no placeholder entry, no leaked file names. A source without a persisted policy contributes nothing.
  • Per-agent privacy. Files in an agent's private data subtree are visible only to that agent — another agent never sees them, not even their names.
  • Caller identity is required. Discovery without a verified caller role fails closed to an empty result, and results are never shared across callers with different roles or feature grants — the shared inventory holds raw index entries, and the whole access evaluation is redone per request, so one caller's view can never be served to another.
  • Markdown only. Tools, hooks, routes, lifecycle code, and team definitions never load from a source. Anything executable in a synced repository is searchable content, nothing more.
  • Standard gates apply unchanged. A requiredFeatures frontmatter declaration on a source file gates it for non-holders exactly like a package contribution — hidden entirely, never rendered as locked.

What is deliberately not loaded

  • Code surfaces of any kind — no tools, hooks, connectors, routes, or lifecycle from sources. Exception, opt-in: a local source flagged recognizesPackages: true ALSO becomes a runtime-WASM package source, at any scope — its directory is scanned and hot-reloaded like the _packages/ drop-zone, so its packages' code runs in the sandbox. The source's own scope then governs who those packages are advertised to, so a user- or agent-scoped source contributes capabilities to that user or agent alone (the package code itself is not yet isolated per owner at runtime). This is additive: the source still contributes markdown packages as described here, and a built-in dedup stops the same package from appearing on both axes. See Hot-reload & package sources.
  • Workflow templates. Nothing under a workflows/ directory is a source contribution at all — a shipped template reaches the platform only through real package discovery and its strict validator.
  • README* files and anything under template(s)/ directories — indexed for search, excluded from the contribution categories.
  • Non-contribution files inside marker directories (settings, themes, configuration).
  • Contribution-shaped files claimed by no grouping rule — they stay indexed but unloaded rather than being lumped into a junk package.
  • Agent runtime data (conversation logs, usage data) — never package content.

Authoring for agents, not just importing

The agent data tree works as a Neuralis-native equivalent of a .claude folder: contributions an agent writes into its own data source become source packages on the next sync, with per-agent private subtrees staying private. The same layout rules apply, so authored and imported content behave identically.

On this page