Skip to content

Latest commit

 

History

95 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

adlc-cli

The CLI layer of the ADLC toolchain for coding agents: skill management (install skills, generate slash commands, wire lifecycle event hooks), team directives (configure and maintain a team-ai-directives repo), workspaces (multi-repo bootstrap), agent execution (run any coding agent headlessly with a task — the invocation layer the Agentic Container delegates to), and a workflow engine (a full JS port of the github/spec-kit workflow engine — ADR-390 + amendments).

Renamed from adlc-skills-cli. The deprecated adlc-skills-cli bin still ships (the legacy add/upgrade/remove/status/agents surface), along with the shim/adlc-skills-cli npm package forwarding to it.

Works with any skills repo: adlc-team-skills, mattpocock/skills, addyosmani/agent-skills, obra/superpowers, or your own.

Quickstart

# Install skills + generate commands + wire events
npx adlc-cli skills add tikalk/adlc-team-skills -a opencode

# Install skills AND configure team-ai-directives (runs /team-setup headlessly)
npx adlc-cli team setup tikalk/adlc-team-skills -a opencode

# Works with any skills repo — events auto-skip if no .events.json
npx adlc-cli skills add mattpocock/skills -a claude-code --no-events
npx adlc-cli skills add addyosmani/agent-skills -a opencode -a cursor

# Run a coding agent headlessly with a task
npx adlc-cli agent run "Fix the failing auth test" -a opencode

# List supported agents + run profiles
npx adlc-cli agent list

# Print version
npx adlc-cli version

Commands

Skill management

Command Description
skills add <source> -a <agent> Install skills via npx skills add + generate commands + wire events
skills update [-a <agent>] Re-generate commands from installed skills; --pull re-installs from source
skills remove [-a <agent>] Remove generated commands + event configs; cleans dispatcher + .events.json
skills [-a <agent>] Show what's installed per agent + dispatcher + event status

Team directives

Command Description
team setup <source> -a <agent> Install skills + write .adlc/init-options.json + run /team-setup headlessly (--skip-skills to skip installation)
team update git pull the team-ai-directives repo + re-install skills from source + team repair --update-confidence
team repair [--update-confidence|--validate-drafts|--build-to-delete] Run /team-repair headlessly (agent-driven), or the deterministic setup-team.sh path for --update-confidence / --validate-drafts

The team tree reads its targets from .adlc/init-options.json (see below); -a defaults to the configured agent.

Workspace

Command Description
workspace setup [file] Apply a workspace file: clone git: modules, create dirs:, install skills, generate commands, run /workspace --init, and (first boot only) hand the agent the workspace goal
workspace init [--link|--ignore-only] Run /workspace --init headlessly (.adlc/ structure, discover/link child repos)
workspace status Run /workspace --status headlessly (audit branch, dirty, unpushed, SHA drift)

Workspace file resolution: explicit argument → ADLC_WORKSPACE_FILE env → .adlc/workspace.yml. Schema requires schema_version plus any of workspace.git[] (repo/path/branch/ref), workspace.dirs[], workspace.init, workspace.link, skills.sources[], commands[], goal. Deterministic steps (git, dirs) run directly; agent-led steps go through agent run. --dry-run prints the plan without executing.

Agent execution

Command Description
agent run "<task>" [flags] Run a coding agent headlessly with a task
agent list List supported agents, command formats, event support, and run profiles
run "<task>" [flags] Top-level alias for agent run (runtime contract, ADR-368)

Workflows

Command Description
workflow run <source> Execute a workflow — YAML path, installed ID, or built-in (factory = the outer loop)
workflow resume <run_id> Resume a paused/failed run; gates re-prompt (or bind a verdict_input via --input)
workflow status [run_id] List runs / show one run's step states
workflow validate <source> Validate a definition; --headless requires gates to declare verdict_input
workflow state … LLM-executor helpers: start/advance/pause/fail/show (ADR-395)

Full JS port of the upstream github/spec-kit workflow engine (zero Python — ADR-390 + amendments). Dual-executor architecture (ADR-395): the same workflow.yml + state.json run either in-session (skills via the state helpers) or headless (the CLI engine) — a run parked at a gate by one executor resumes on the other. Step types: command, prompt, shell, gate, if, switch, while, do-while, fan-out (with max_concurrency), fan-in, slot.

.adlc/workflows/<id>/workflow.yml      installed · curated definitions
.adlc/workflows/<run_id>/workflow.yml  generated-by-slug definitions (ADR-391-amendment)
.adlc/workflows/runs/<run_id>/         run state: state.json, inputs.json, log.jsonl,
                                       frozen workflow.yml, lease.json + mission
                                       artifacts (brief.md, mission.yml, scratchpads/…)
refs/factory-runs/<run_id>             git-refs Tier-3 (ADR-393)
# Run → gate pauses (non-TTY) → resume headlessly
adlc-cli workflow run mission --input spec="Fix auth"
adlc-cli workflow resume <run_id> --input verdict=approve

# The bundled outer loop (stages = command steps + gates)
adlc-cli workflow run factory --input verdict=approve

# CI: JSONL lifecycle events (run_started/step_*/gate_paused/…/run_completed)
adlc-cli workflow run factory --format json

# LLM executor drives state via helpers (set ADLC_WORKFLOW_SESSION per session)
export ADLC_WORKFLOW_SESSION=my-session
adlc-cli workflow state start --workflow mission --input spec="Fix auth"
adlc-cli workflow state advance <run_id> --step specify --status completed
adlc-cli workflow state pause <run_id> --step review      # gate → human

Environment variables:

Variable Meaning
ADLC_WORKFLOW_SESSION Session id — makes the run lease persist across sequential CLI invocations instead of per-command
ADLC_WORKFLOW_RUN_ID Set for step processes so nested commands address their own run
ADLC_WORKFLOW_LEASE_TTL Lease TTL in seconds (default 900)
ADLC_WORKSPACE_FILE Workspace file path override for workspace setup

SIGINT/SIGTERM trigger a clean pause (resumable) rather than a corrupt partial state.

Known constraint (inherited upstream): a gate nested inside if/switch/while bodies that pauses will re-run the parent control-flow step and its nested body on resume. Keep gates at the top level, or bind a verdict_input on the gate.

Top-level

Command Description
version Print installed version
help Show full help

.adlc/init-options.json

Written by team setup (and by the /team-setup skill), read by the team and workspace trees to resolve defaults:

{
  "agent": "opencode",
  "skills_source": "tikalk/adlc-team-skills",
  "team_ai_directives": "./tikal-team-ai-directives"
}

agent and skills_source default every later -a / re-install; team_ai_directives is where team update pulls and team repair indexes.

agent run flags

Flag Description
-a <agent> Run profile: opencode | claude-code | goose | gemini (default: opencode)
--model <id> Model id passed to the agent CLI (optional — agent picks its own if absent)
--format <fmt> Output: text (default, human-readable) | json (normalized JSONL for container/CI)
--cwd <path> Working directory (default: current directory)
--timeout <s> Kill agent after N seconds (CI safety)
--require-approval <tools> Comma-separated tools that pause for human approval (e.g., Bash,Write)
- Read the task from stdin

agent run examples

# One-shot run (text output)
adlc-cli agent run "Fix the failing auth test" -a opencode

# JSON output (normalized JSONL — what the Agentic Container consumes)
adlc-cli agent run "echo hello" -a opencode --format json

# Read task from stdin
cat brief.md | adlc-cli agent run - --format json

# Run in a specific workspace with a timeout
adlc-cli agent run "refactor utils" -a opencode --cwd ./my-project --timeout 120

# Require approval for dangerous tools (HITL)
adlc-cli agent run "deploy to staging" -a opencode --require-approval Bash,Write

Normalized JSONL event vocabulary

agent run --format json emits one JSON object per line:

Type Payload Meaning
message {text} Agent text output
tool {phase: "call"|"result", name?, arguments?, result?} Tool invocation or result
permission_request {tool, request_id} HITL permission gate
error {message} Error
complete {} Agent finished
log {message?} Non-structured log line

How skill installation works

adlc-cli skills add <source> -a <agent>
  │
  ├─ 1. npx skills add <source> -a <npx_agent>     ← installs SKILL.md files
  │
  ├─ 2. Discover installed skills                   ← reads SKILL.md frontmatter
  │
  ├─ 3. Generate command files                      ← slash commands (/name)
  │     .opencode/commands/<name>.md                   inline: embeds skill body
  │                                                    wrapper: references skill
  │
  └─ 4. Wire events (if .events.json in source)     ← lifecycle hooks
        .agents/dispatcher.mjs                        generic dispatcher (shipped)
        .opencode/plugins/adlc-skills-events.ts       agent-native hook config

Skill flags

Flag Description
-a <agent> Target agent (repeatable). Run agent list to list.
-g, --global Install to user directory instead of project
--no-events Skip event config generation
--prefix <str> Namespace command filenames (e.g., adlc.team-setup.md)
--mode <mode> inline (embeds full skill body) or wrapper (references skill by name)
--skill, -s <name> Install/generate for one skill only (use '*' for all). The selection is expanded through the source's .skills-deps.json closure: borrowers auto-pull their canonical homes (e.g. --skill architect-implement also installs architect-clarify)
--copy Copy files instead of symlinking (passthrough to npx skills)
--pull (update) re-install from the locked source
-y, --yes Skip confirmation prompts

Supported agents

24 command agents across 3 command formats (plus a generic fallback), 9 agents with event hooks, 4 run profiles.

Gemini key split (current behavior): the agent registry key is gemini-cli (skills/commands/events), but the run profile is keyed gemini. So: skills add -a gemini-cli, but agent run -a gemini — and agent list shows gemini-cli without a run profile. Use the two keys as shown.

Agent Commands dir Format Events Run
opencode .opencode/commands/ markdown yes yes
claude-code .claude/commands/ markdown yes yes
goose .goose/recipes/ yaml no yes
gemini-cli .gemini/commands/ toml yes agent run -a gemini
...and 20 more

Run adlc-cli agent list for the full table.

Command generation: two modes

Inline

Embeds the full SKILL.md body in the command file — self-contained, works on any agent:

---
description: Clone, scaffold, or configure a team AI directives repository
---

<!-- generated by adlc-cli; source: tikalk/adlc-team-skills — do not edit -->

Base directory for this skill: /project/.agents/skills/team-setup

# Team Setup

[full skill body...]

$ARGUMENTS

Wrapper

Thin command that references the installed skill — requires the agent to have skill support:

---
description: Clone, scaffold, or configure a team AI directives repository
---

<!-- generated by adlc-cli; source: tikalk/adlc-team-skills — do not edit -->

Invoke the `team-setup` skill.

<skill summary>

## User Input

$ARGUMENTS

The ## User Input block is generated for both modes so the args placeholder is framed as workflow input rather than trailing text.

User-invoked skills: wrapper vs execution mode

User-invoked skills (disable-model-invocation: true in frontmatter) are meant to be triggered explicitly. The command body strategy depends on the agent:

Mode Used by Why
wrapper opencode Ignores disable-model-invocation — skill stays available, model calls skill({name})
execution claude-code, cursor, copilot, codex Respects disable-model-invocation — skill hidden, body must be inlined

Events: lifecycle hooks

For agents with native hook support (9 agents), the CLI wires event hooks that auto-trigger skills at lifecycle points.

Events are auto-enabled when:

  1. The agent supports events
  2. The source repo declares a .events.json manifest
  3. --no-events is not set

.events.json manifest

{
  "events": {
    "session_start": [
      { "skill": "team-boot", "description": "Bootstrap session with team context", "timeout": 60 }
    ],
    "user_prompt_submit": [
      { "skill": "team-discover", "description": "Fetch relevant context", "timeout": 30 }
    ]
  }
}

Repos without .events.json get commands only — events are skipped silently.

The dispatcher: two execution paths

A generic dispatcher (.agents/dispatcher.mjs) is shipped to the project. When a native hook fires, it calls the dispatcher:

Path When How
Script Skill has scripts: in frontmatter Runs the script → stdout
Body No scripts: block Outputs the skill's markdown body → stdout

Both paths feed the stdout → context injection pipeline.

8 canonical events

Event Fires when Body path? Script path?
session_start Agent session begins yes yes
session_compact Harness compacts history yes yes
user_prompt_submit User sends prompt yes yes
pre_tool_use Before tool call no yes
post_tool_use After tool call no yes
file_edited A file was edited (e.g. decision drafts) no yes
session_end Session ends no yes
stop Agent stops no yes

file_edited per-agent delivery

Agent Native hook Delivery
opencode file.edited (generic event subscription) script stdout stashed → injected into the last user message on the next messages.transform pass (before the session-start dedup guard)
claude-code PostToolUse (+ matcher e.g. Edit|Write) hookSpecificOutput.additionalContext — direct context injection
codex PostToolUse envelope suppressed (tool-hook output sink unverified — safe no-op)
cursor postToolUse envelope suppressed (tool-hook output sink unverified — safe no-op)
others — null mapping until a native surface is documented

Skill scripts see ADLC_EVENT in their environment and the event payload on stdin.

Per-agent native hook configuration

Agent Config file Format Timeout unit
opencode .opencode/plugins/adlc-skills-events.ts TS plugin seconds
claude-code .claude/settings.json (merged) JSON nested seconds
cursor .cursor/hooks.json (merged) JSON nested seconds
github-copilot .github/hooks/adlc-skills.json JSON seconds
codex .codex/config.toml (merged) TOML seconds
gemini-cli .gemini/settings.json (merged) JSON nested milliseconds
qwen-code .qwen/settings.json (merged) JSON nested milliseconds
devin .devin/hooks.v1.json (merged) JSON root-nested seconds
tabnine-cli .tabnine/agent/settings.json (merged) JSON nested milliseconds

Safety patterns (ported from spec-kit)

  • Idempotent merge: re-install never duplicates hook entries
  • Surgical teardown: remove strips only our entries, preserves user hooks
  • JSONC preservation: malformed JSON aborts, never resets user content
  • Safe-destination validation: rejects symlink redirects outside project root
  • Shell-safe argv: execFileSync with argv arrays, no shell injection
  • stdin payload forwarding: user_prompt_submit receives the user's prompt

Self-describing files

Every generated file includes a <!-- generated by adlc-cli --> header. Event hook entries carry a _adlc_skills_cli: true marker (JSON) or adlc_skills_marker = true (TOML). This enables:

  • remove to safely delete only our files
  • upgrade to overwrite our files while skipping user-modified ones

No manifest database or state file needed.

Install

# One-off (no install needed)
npx adlc-cli skills add tikalk/adlc-team-skills -a opencode

# Install as global binary
npm install -g adlc-cli
adlc-cli skills add tikalk/adlc-team-skills -a opencode

Development

# Run tests (300+ tests via node --test)
npm test

# Run the CLI locally
node bin/adlc-cli.mjs help
node bin/adlc-cli.mjs agent list
node bin/adlc-cli.mjs skills -a opencode

# Run a task locally
node bin/adlc-cli.mjs agent run "say hello" -a opencode --format text

Zero runtime dependencies. Requires Node.js >= 18.

License

MIT

About

Dual-mode CLI for coding agents: skill management + agent execution + team lifecycle (setup, update, repair). Install skills, generate slash commands, wire lifecycle events, run any agent headlessly.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages