Build for Light Kali Packages • APIs • Manifest • Commands • Lifecycle Current package bridge reference

A runtime-grounded reference for package authors. This page separates declared manifest data from actual runtime capabilities, documents the complete package bridge, explains command registration without source duplication, and exposes the current command registry.

01 / Quick Start

One source of truth for your package

Define command metadata once, derive manifest.commands from that definition, and let install() consume the same object. This avoids declaring the same command names twice.

Core contract: The package bridge itself calls registerCommand(name, meta, {{ source: 'package', packageKey }}) internally. Package authors call only api.registerCommand(name, meta); do not pass a third source/package options object.
PACKAGE MODULE
(() => {
  'use strict';

  const COMMANDS = Object.freeze({
    test: {
      description: 'Run a package self-test.',
      usage: 'test [TEXT...]',
      aliases: [],
      kind: 'plain',
      run: ({ args = [], api } = {}) => {
        const text = args.length ? args.join(' ') : 'test: ok';
        return [api.line(text, 'success')];
      }
    }
  });

  const manifest = Object.freeze({
    name: 'test',
    version: '1.0.0',
    description: 'Minimal Light Kali test package.',
    author: 'Your Name',
    help: 'test help',
    official: false,
    default: false,
    securityLevel: 'low',
    permissions: Object.freeze({
      storage: 'none',
      cookies: 'none',
      network: 'none',
      filesystem: 'none'
    }),
    commands: Object.freeze(Object.keys(COMMANDS)),
    dependencies: Object.freeze([]),
    entry: 'install'
  });

  const install = async api => {
    for (const [name, definition] of Object.entries(COMMANDS)) {
      if (!manifest.commands.includes(name)) {
        throw new Error(`COMMAND_NOT_DECLARED:${name}`);
      }
      const registered = api.registerCommand(name, definition);
      if (registered === false) {
        throw new Error(`PACKAGE_COMMAND_REGISTRATION_FAILED:${name}`);
      }
    }
    return [];
  };

  const uninstall = async api => {
    for (const name of manifest.commands) {
      api.unregisterCommand(name);
    }
    return [];
  };

  window.__kali_pkg_test = Object.freeze({
    manifest,
    install,
    uninstall
  });
})();
A

Manifest drives installation metadata

The Core resolves the module, reads manifest, normalizes it, freezes it, creates the package bridge, and then calls install(bridge). The normalized manifest is passed back through api.manifest.

B

Installation should stay declarative

Use manifest.commands as the package command inventory. Keep command behavior in one COMMANDS map and register from it instead of repeating command names, aliases, usage strings, and descriptions throughout the lifecycle code.

02 / Package Bridge

Complete package-facing API

The bridge is the supported package surface. Internal Core objects are larger and should not be treated as package APIs.

19bridge properties
10direct methods / callable properties
4capability namespaces
01

packageKey

Canonical package key used by the Core for the installed package.

CODE
const key = api.packageKey;
02

manifest

Normalized, deeply frozen package manifest supplied by the Core.

CODE
const version = api.manifest.version;
const commands = api.manifest.commands;
03

record

Current package registry record. Optional properties should be read defensively.

CODE
const status = api.record?.status ?? 'unknown';
04

append(entries)

Append terminal entry objects after lifecycle output blocking is no longer active.

CODE
api.append([api.line('Runtime event.', 'output')]);
During install and uninstall, package transcript output is blocked by the Core.
05

line(text, class)

Create a terminal line entry. Text is escaped before rendering.

CODE
return [api.line('Ready.', 'success')];
06

spacer()

Create a blank terminal spacer entry.

CODE
return [api.spacer(), api.line('Next section', 'accent')];
07

snapshot()

Return the current runtime snapshot exposed by the package bridge.

CODE
const s = api.snapshot();
const mode = s.mode;
const cwd = s.cwd;
const commands = s.commands;
const installed = s.installed;
08

getMode()

Read the active virtual mode. Current modes are user, root, and ghost.

CODE
const mode = api.getMode();
09

registerCommand(name, meta)

Register a package-owned command. The bridge supplies the package source and package identity automatically.

CODE
api.registerCommand('test', {
  description: 'Run the test command.',
  usage: 'test [TEXT...]',
  aliases: [],
  kind: 'plain',
  run: ({ args = [], api } = {}) => [
    api.line(args.join(' ') || 'test: ok', 'success')
  ]
});
10

unregisterCommand(name)

Remove a command during cleanup.

CODE
api.unregisterCommand('test');
11

registerPackageGuard(name, guard)

Security-guard registration is restricted to the official kalisecurity package.

CODE
api.registerPackageGuard('example', guard);
Normal third-party packages must not depend on this API.
12

unregisterPackageGuard(name)

Security-guard removal is restricted to the official kalisecurity package.

CODE
api.unregisterPackageGuard('example');
13

confirm(title, detail)

Open the terminal Y/N confirmation flow and resolve to a boolean.

CODE
const approved = await api.confirm(
  'Allow operation?',
  'The user must answer Y or N.'
);
14

permissions

Read the bridge capability declaration. The current bridge is always none for all four categories.

CODE
console.log(api.permissions);
// { storage: 'none', cookies: 'none',
//   network: 'none', filesystem: 'none' }
15

storage

Namespace shape: get, set, remove, keys. Every operation currently denies access.

CODE
await api.storage.get('key'); // throws
16

cookies

Namespace shape: get, set, remove. Every operation currently denies access.

CODE
await api.cookies.get('session'); // throws
17

network

Namespace shape: fetch, request. Every operation currently denies access.

CODE
await api.network.fetch('https://example.com'); // throws
18

filesystem

Namespace shape: read, write, remove, list. Every operation currently denies access.

CODE
await api.filesystem.read('/home/kali/file.txt'); // throws
19

flow

Low-level flow surface with stub/passthrough behavior. Use confirm() for the supported Y/N flow.

CODE
api.flow.begin(value);  // returns value
api.flow.next(value);   // returns value
api.flow.cancel();      // null
api.flow.resume();      // null
03 / Manifest

Complete manifest contract

These are the fields the Core currently normalizes and exposes through api.manifest. Unknown fields are not part of the documented normalized contract.

MANIFEST
const manifest = Object.freeze({
  name: 'example',
  version: '1.0.0',
  description: 'Example Light Kali package.',
  author: 'Your Name',
  help: 'example help',
  permissions: Object.freeze({
    storage: 'none',
    cookies: 'none',
    network: 'none',
    filesystem: 'none'
  }),
  commands: Object.freeze(['example']),
  dependencies: Object.freeze([]),
  entry: 'install',
  default: false,
  official: false,
  securityLevel: 'medium'
});
FieldTypeNormalization / defaultMeaning
namestringpkgKey fallbackCanonical package identity. A non-empty manifest name can migrate the package to that canonical key.
versionstringunknownPackage version stored in the normalized manifest.
descriptionstringempty stringHuman-readable package description.
authorstringunknownAuthor or project attribution.
helpstring<name> helpMain package help reference.
permissionsobjectall categories become none when omittedDeclaration stored in the manifest. It is not a runtime capability grant today.
commandsarray[]Declared package command names. Best generated from one command-definition source.
dependenciesarray[]Declared package dependency names.
entrystringinstallDeclared package initialization entry name.
defaultbooleanfalseExplicit default-package marker.
officialbooleanfalseExplicit official-package marker.
securityLevelstringmediumSecurity-level label. The current Core stores it as text; there is no closed enum validator in the normalizer.
Manifest source of truth: The normalizer reads mod.manifest when it is an object and falls back to loader data otherwise, then creates a deep-frozen normalized object containing exactly the fields documented above.
04 / Capabilities

All permission variables and actual runtime behavior

The implementation currently accepts text for each permission field and lowercases it. Because there is no allow-list, there is no finite set of “all accepted values”; any string can survive normalization. Separately, the package bridge currently grants none of these capabilities.

Manifest keyShapeNormalizationBridge namespaceCurrent implementationDocumented examples
storagestringString(value ?? 'none').toLowerCase()api.storageDENIEDnone, read, write, readwrite, full are merely possible strings; only none is currently granted, and in practice the bridge operation still denies access.
cookiesstringLowercase stringapi.cookiesDENIEDAny string can normalize; no runtime grant enum exists today.
networkstringLowercase stringapi.networkDENIEDAny string can normalize; values such as read, request, full are not runtime grants.
filesystemstringLowercase stringapi.filesystemDENIEDAny string can normalize; values such as read, write, full are not runtime grants.
A

securityLevel

The current normalizer treats securityLevel as plain text and defaults it to medium. The loader uses a stronger default for built-in protected packages, but no finite public enum is enforced by the normalizer.

DECLARATION
securityLevel: 'low'
B

Recommended discipline

For package interoperability, use a small controlled vocabulary in your own package metadata, but do not claim that the Core currently enforces that vocabulary. Treat security policy as runtime-owned.

EXAMPLE LABELS
'low'
'medium'
'high'
'system'
Do not confuse declaration with grant. Today, api.permissions is hard-coded to none for storage, cookies, network, and filesystem; the exposed methods are denied functions. Requesting read, write, full, or another string in the manifest does not unlock the operation.
05 / Commands

Register commands without creating developer traps

The package-facing signature is intentionally small: api.registerCommand(name, meta). Internally, the bridge marks the command as package-owned and attaches the package key automatically.

Command metadataTypeOptional?Runtime behavior
descriptionstringyesHuman-readable description stored with the command.
usagestringyesUsage line shown by help output.
aliasesarrayyesEach alias is lowercased. Package aliases are registered into the alias map.
kindplain | flowyesAny value other than the exact flow string becomes plain.
runfunctionyesUsed for plain commands. If absent, the stored fallback is an empty function.
beginfunctionyesUsed for flow commands when execution starts.
nextfunctionyesFlow callback for the next user input.
cancelfunctionyesFlow cancellation callback.
resumefunctionyesFlow resume callback.

Plain command

CODE
api.registerCommand('test', {
  description: 'Run the test command.',
  usage: 'test [TEXT...]',
  aliases: ['t'],
  kind: 'plain',
  run: ({ raw, tokens, args, api, ctx } = {}) => [
    api.line(`raw: ${raw}`, 'muted'),
    api.line(`tokens: ${tokens.join(', ')}`, 'dim'),
    api.line(args.length ? args.join(' ') : 'test: ok', 'success')
  ]
});

Flow command

CODE
api.registerCommand('login-demo', {
  description: 'Run a package-managed flow example.',
  usage: 'login-demo',
  aliases: [],
  kind: 'flow',
  begin: async ({ raw, tokens, args, api, ctx } = {}) => {
    return api.confirm(
      'Continue?',
      'Answer Y or N to continue.'
    );
  },
  next: async ({ input, api } = {}) => [
    api.line(`Input: ${String(input ?? '')}`, 'muted')
  ],
  cancel: () => [
    api.line('Cancelled.', 'muted')
  ],
  resume: () => [
    api.line('Flow is waiting for input.', 'muted')
  ]
});
Execution context: When a command runs, the Core supplies raw, tokens, args, a scoped api, and ctx. Flow commands receive the same input context in begin(); subsequent flow callbacks receive their flow-specific payloads.
InputExamplePurpose
rawtest "hello world"Original command text after outer trimming.
tokens['test','hello world']Tokenized command input.
args['hello world']All tokens after the command name.
apiapi.line(...)Scoped command API.
ctxctx.operationCurrent execution context for operations and output handling.
Collision rule: A package command cannot replace a Core-owned command. Registration returns false when the name already belongs to the Core. Use a unique command name and handle a failed registration explicitly.
06 / Install

Installation follows the manifest, not duplicated metadata

Developers publish the package module. The Core resolves the source, verifies the module shape, normalizes its manifest, builds the package bridge, and calls install(bridge).

External package rule: External installation is accepted only through HTTPS. The package manager rejects other explicit remote schemes.
USER COMMAND
apt install https://example.com/path/to/test.js
Install modeInputTransportCore behavior
internalInternal package name/pathscriptLoads a local package script, resolves the exported module, normalizes manifest, then installs it.
external-httpsHTTPS URL or www. input normalized to HTTPSfetchFetches JavaScript source, rejects empty/HTML responses, evaluates the module, then installs it.
Developer owns

Manifest, command definitions, package state, install/uninstall cleanup, and package-local behavior.

Core owns

Source resolution, manifest normalization, package identity migration, security checks, registry persistence, lifecycle status, and external-source confirmation.

Never assume

A manifest permission string creates browser, cookie, network, or filesystem access. The current bridge does not grant those operations.

07 / Lifecycle

Install, runtime, uninstall

Lifecycle hooks are for package setup and teardown. The Core owns lifecycle reporting and suppresses package transcript output while lifecycle hooks are running.

01

install(api)

Register commands, initialize package-local state, validate your own invariants, and return [] on success.

02

uninstall(api)

Unregister package-owned commands, clear package-local state, and return []. The Core cleans package records and modules.

1

Resolve

The package source is normalized into an internal or external-HTTPS installation mode.

2

Load

The Core loads the module and requires a callable install function.

3

Normalize

The manifest is normalized and deep-frozen before the package bridge is constructed.

4

Initialize

install(bridge) runs while lifecycle output is blocked.

5

Runtime

The package is recorded as enabled and its package commands become available.

6

Remove

uninstall(bridge) runs first; the Core then removes package commands and package state.

Do not emit lifecycle progress yourself. Messages such as “Installing…”, “Installed…”, or “Uninstalling…” should be left to the Core. Package output during these phases is intentionally blocked.
08 / Output

Terminal entries and current class vocabulary

Use api.line() and api.spacer() for ordinary package output. The renderer also understands structured entry types internally, but package authors should stay on the documented bridge helpers.

CODE
return [
  api.line('Ready.', 'success'),
  api.line('Warning: example warning.', 'danger'),
  api.line('Current path: /home/kali', 'dim'),
  api.spacer(),
  api.line('More information', 'accent')
];
ClassUse in current runtimeTypical package meaning
outputYesDefault terminal output.
mutedYesSecondary or explanatory text.
accentYesHighlighted status or heading.
dangerYesError, blocked action, or attention state.
successYesSuccessful result.
dimYesLow-emphasis metadata.
purpleUsed by current runtime outputProject/information highlight.
cyan-lightUsed by current runtime outputInformational highlight.
pinkUsed by current runtime outputBoot/runtime highlight.
Class names are presentation tokens. Do not assume arbitrary class names automatically have a predefined visual treatment. Use the currently evidenced tokens above unless you control the rendering stylesheet yourself.
09 / Command Registry

Complete built-in command inventory

The current command source registers 166 named command entries. The table below is generated from the current command-source inventory so the documentation has a concrete registry instead of a partial hand-written list.

166registered names
plaindefault registration kind
dynamicmetadata lookup in Light Kali
#CommandSource guidance
Runtime help is authoritative. The unified help [command] path resolves a command and can expose its name, usage, description, capability, aliases, and examples where the command definition supplies them. Use that output when debugging the live system.
RUNTIME
help
help <command>
10 / Errors & Security

Installation failure codes and security states

The package manager classifies common failures so developers can diagnose the stage instead of guessing.

PACKAGE_ENTRY_INVALID
The resolved module does not expose a callable install function.
PACKAGE_SYNTAX_ERROR
Package JavaScript could not be evaluated because of a syntax/evaluation problem classified as a syntax error.
PACKAGE_SOURCE_HTML
The external endpoint returned HTML rather than package JavaScript.
PACKAGE_SOURCE_UNAVAILABLE
The package source could not be loaded. Check HTTPS, endpoint reachability, and source resolution.
PACKAGE_SECURITY_BLOCKED
The current security layer or package guard rejected the package.
PACKAGE_COMMAND_REGISTRATION_FAILED
A command could not be registered. A common cause is a collision with a Core-owned command.
PACKAGE_MANIFEST_INVALID
Package identity or manifest normalization failed.
PACKAGE_HTTPS_LOAD_FAILED
An HTTPS load failed and was classified by the package failure mapper as an HTTPS-specific failure.
PACKAGE_INSTALL_FAILED
A package failure did not match a more specific failure classification.
DEFAULT_SOURCE_REJECTED
A protected/default package was supplied with a source that does not satisfy the default-package installation rules.
DEFAULT_PACKAGE_REMOTE_REJECTED
A default/protected package attempted to install from a remote source.
SECURITY_GUARD_UNAVAILABLE
A non-security package attempted installation while the package-security guard provider was unavailable.
USER_DECLINED_SECURITY_WARNING
The user rejected a security confirmation; the package is not installed.
Registry stateMeaning
enabledPackage is recorded as installed and enabled.
trusted-localInternal package source has been marked trusted while installation proceeds.
corruptedSecurity processing blocked the package.
security-declinedUser declined a security warning/confirmation.
Security boundary: External packages can be fetched, inspected by the security layer, and require explicit confirmation before execution. Do not describe an external package as trusted merely because its manifest declares a low securityLevel.
11 / Special Integration

FreeUserProxy.js

FreeUserProxy is a special browser-side integration exposed outside the normal package bridge. Keep this integration optional and fail cleanly when it is unavailable.

A

Optional adapter

Resolve the exported plugin object defensively rather than assuming the plugin is always loaded.

B

Safer architecture

Prefer infrastructure you control. Never route passwords, cookies, session tokens, API keys, or other secrets through public proxies you do not control.

CODE
function getFreeUserProxy() {
  return window.__FreeUserProxy
    ?? globalThis.__FreeUserProxy
    ?? null;
}

function isFreeUserProxyAvailable() {
  const fup = getFreeUserProxy();
  return Boolean(
    fup &&
    typeof fup.getWorkingProxies === 'function'
  );
}
MethodReturnPurpose
getRandomUserAgent()stringSelect a User-Agent value from the plugin list.
getAllProxies()arrayRead configured proxy templates.
getWorkingProxies()arrayRead proxies that passed the current scan.
getRandomWorkingProxy()object | nullPick a working proxy conveniently.
isAvailable()booleanCheck plugin initialization/availability.
Operational rule: Proxy reachability is temporary. A browser-side proxy may fail due to CORS, endpoint downtime, network reachability, rate limits, or policy changes. Always implement a fallback or a clean failure path.

Build on the Bridge.
Let the Core own the System.

Keep one command definition source, derive the manifest inventory from it, use the documented bridge, and never confuse manifest declarations with runtime capability grants.