This page is for LLM agents
This guide is written for Claude, GPT, Gemini, and similar agents operating hence autonomously. It is dense, reference-complete, and unambiguous by design. If you are an LLM reading this, follow the patterns exactly — they are tested and correct.

Contents

  1. Load the SPL reference into context
  2. The complete agent loop
  3. Parsing hence task next output
  4. Creating a plan from scratch
  5. Translating a spec to a plan
  6. Asserting findings
  7. Decomposing a task into subtasks
  8. Handling blocked tasks
  9. Debugging with explain / why-not
  10. Multi-agent coordination
  11. Working with hence.run remote plans
  12. JSON output for programmatic use
  13. Common mistakes to avoid
  14. Session commands
  15. Inline SPL reference

1. Load the SPL reference into context

Before doing any plan work, load the full SPL syntax reference into your context window. This is the single most important step — without it, you will write malformed plans.

hence llm spl

Run this command at the start of every session where you will be reading, writing, or validating .spl plan files. The output is plain text, formatted for LLM context windows. Pipe it into your prompt or include it in your system prompt:

# Pipe into a variable for use in a script or prompt template
SPL_REF=$(hence llm spl)

# Or pipe directly when invoking another LLM
hence llm spl | llm "Now write a plan for my project: ..."
Tip
The full SPL reference is also embedded verbatim at the bottom of this page as a <pre> block. An LLM reading this HTML page already has the reference in context — no command required.

2. The complete agent loop

This is the canonical sequence an LLM agent follows when working a plan. Execute these commands in order. Every step has a purpose — do not skip any.

# Step 0: Set identity (once per session, or set in environment)
export HENCE_AGENT=claude

# Step 1: Confirm your identity
hence agent whoami

# Step 2: Read plan metadata — understand scope, status, and spec
hence plan info plan.spl

# Step 3: See the full task board — all tasks and their states
hence plan board plan.spl

# Step 4: Find tasks assigned to you that are ready to work
hence task next plan.spl

# Step 5: Claim a specific task before starting work
hence task claim TASK plan.spl

# Step 6: Do the actual work for the task
# (run tests, write code, make decisions, gather results, etc.)

# Step 7: Record findings as logical facts while working
hence task assert '(given FACT)' plan.spl

# Step 8: Mark the task complete
hence task complete TASK plan.spl

# Step 9: Check what work just unlocked
hence task next plan.spl

# Repeat from Step 5 until hence task next returns nothing

Step-by-step explanation

Step Command Purpose
0 export HENCE_AGENT=<name> Sets your agent identity for all subsequent commands. Without this, all task/claim commands require --agent <name> on every invocation.
1 hence agent whoami Confirms the active agent name from environment. Use to verify the correct identity is set before claiming tasks.
2 hence plan info plan.spl Reads (meta plan ...) metadata: id, title, description, status, spec reference. Establishes context for the entire session.
3 hence plan board plan.spl Shows all tasks with their current state: ready, claimed, completed, blocked. Use to orient yourself before picking work.
4 hence task next plan.spl Returns tasks assigned to HENCE_AGENT that are currently ready. This is your work queue. Empty output means no work available right now.
5 hence task claim TASK plan.spl Atomically claims a task. Appends a (claims ...) block to the plan file. Other agents will see this task as in-progress.
7 hence task assert '(given FACT)' plan.spl Records a logical fact discovered during work. Facts are permanent and drive downstream readiness. Assert early and often.
8 hence task complete TASK plan.spl Marks task done. Automatically derives completed-TASK fact, which may unlock downstream tasks per readiness rules.
9 hence task next plan.spl Check again after completing — completing a task may have unlocked new work. Loop here until no more tasks.

Minimal agent loop (copy-paste ready)

export HENCE_AGENT=claude
PLAN=plan.spl

hence agent whoami
hence plan info $PLAN
hence plan board $PLAN

while true; do
  NEXT=$(hence task next $PLAN --json)
  ACTIONS=$(echo "$NEXT" | jq '.next_actions | length')
  if [ "$ACTIONS" -eq 0 ] || [ -z "$NEXT" ]; then
    echo "No tasks available. Done."
    break
  fi

  TASK=$(echo "$NEXT" | jq -r '.next_actions[0].task')
  echo "Working on: $TASK"

  hence task claim "$TASK" $PLAN

  # ... do the work for $TASK ...

  hence task complete "$TASK" $PLAN
done

3. Parsing hence task next output

Use --json for programmatic parsing. The output is a JSON object with a next_actions array.

hence task next plan.spl --json

JSON schema

{
  "agent": "claude",
  "next_actions": [
    {
      "agent": "claude",                                          // assigned agent name
      "command": "hence task claim auth plan.spl --agent claude", // copy-pasteable claim command
      "literal": "assign-to-auth-claude",                        // the derived assignment literal
      "task": "auth"                                             // task identifier (task- prefix stripped)
    }
  ]
}

Extraction examples

# Get the first task name
hence task next plan.spl --json | jq -r '.next_actions[0].task'

# Get all task names as a list
hence task next plan.spl --json | jq -r '.next_actions[].task'

# Get the claim command for the first task
hence task next plan.spl --json | jq -r '.next_actions[0].command'

# Check if there is any work available
TASKS=$(hence task next plan.spl --json | jq '.next_actions | length')
if [ "$TASKS" -gt 0 ]; then echo "Work available"; fi
Note
The task field is the task identifier with the task- prefix stripped (e.g., a plan fact task-auth appears as "task": "auth"). Pass it directly to hence task claim and hence task complete.

4. Creating a plan from scratch

Follow this prompt pattern precisely when an LLM is asked to write a new plan:

  1. Load the SPL reference
    Run hence llm spl or read the inline reference on this page. You must have the syntax in context before writing anything.
  2. Identify all tasks and their dependencies
    List every task that must be completed. For each, determine: what must be true before this task can start? Which other tasks must be complete? What agent should do it?
  3. Write the .spl file
    Follow the structure: (meta plan ...), agents, task facts, task metadata, readiness rules, assignment rules, superiority declarations.
  4. Validate
    Run hence plan validate plan.spl and fix any errors before proceeding.
  5. Review
    Run hence plan review plan.spl which uses a headless LLM agent to check for logical issues, missing metadata, and ambiguous rules.

Complete plan template

;; ── Plan metadata ────────────────────────────────────────────
;; Required. Must appear at the top. hence plan info reads this.
(meta plan
  (id "IMPL-042")
  (title "User Authentication System")
  (version "1.0.0")
  (status "active")
  (created "2026-02-24")
  (author "agent:claude")
  (spec "SPEC-042")
  (description "Implement login, session management, and token refresh"))

;; ── Agents ───────────────────────────────────────────────────
;; Declare which agents are available to take work.
(given agent-coder-available)
(given agent-security-available)
(given agent-reviewer-available)

;; ── Task identifiers ─────────────────────────────────────────
;; Each task is a fact. Naming: task-IDENTIFIER
(given task-auth)
(given task-tests)
(given task-review)

;; ── Task properties ──────────────────────────────────────────
;; Additional facts that influence readiness and assignment.
(given no-deps-auth)
(given security-sensitive-auth)

;; ── Task metadata ─────────────────────────────────────────────
;; Required on every task: description + acceptance criteria.
(meta task-auth
  (description "Implement JWT auth with refresh tokens")
  (acceptance  "Login endpoint returns valid JWT; refresh works; all auth tests pass"))

(meta task-tests
  (description "Integration tests for auth endpoints")
  (acceptance  "Coverage above 80%; all auth flows covered; CI green"))

(meta task-review
  (description "Security review of auth implementation")
  (acceptance  "No critical vulnerabilities; reviewer signs off"))

;; ── Readiness rules ──────────────────────────────────────────
;; When can each task start? Naming: ready-IDENTIFIER
(normally r-ready-auth
  (and task-auth no-deps-auth)
  ready-auth)

(normally r-ready-tests
  (and task-tests completed-auth)
  ready-tests)

(normally r-ready-review
  (and task-review completed-tests)
  ready-review)

;; ── Assignment rules ─────────────────────────────────────────
;; Who works on what? Naming: assign-to-TASK-AGENT
(normally r-assign-auth-coder
  (and ready-auth agent-coder-available)
  assign-to-auth-coder)

(normally r-assign-auth-security
  (and ready-auth security-sensitive-auth agent-security-available)
  assign-to-auth-security)

(normally r-assign-tests-coder
  (and ready-tests agent-coder-available)
  assign-to-tests-coder)

(normally r-assign-review-security
  (and ready-review agent-security-available)
  assign-to-review-security)

;; ── Superiority ──────────────────────────────────────────────
;; When two assignment rules conflict, which wins?
(prefer r-assign-auth-security r-assign-auth-coder)

;; ── Rule metadata ─────────────────────────────────────────────
;; Explain why each non-obvious rule exists.
(meta r-assign-auth-security
  (description "Security-sensitive tasks go to security agent")
  (justification "Per security policy section 3.2"))

Validate and review

# Validate syntax and rule consistency
hence plan validate plan.spl

# LLM-based review: checks for missing metadata, logical gaps, ambiguous rules
hence plan review plan.spl
Always validate before distributing
Never share a plan file with other agents until hence plan validate exits cleanly. A malformed plan silently produces wrong task lists.

5. Translating a spec to a plan

If you have a requirements document (Markdown, plain text, or structured spec), you can bootstrap a plan from it using:

hence plan translate spec.md --output plan.spl

This invokes a headless LLM agent that reads the spec and generates a valid SPL plan. The generated plan will have:

  • A populated (meta plan ...) block with title and description derived from the spec
  • Task identifiers and task metadata inferred from requirements
  • Dependency chains derived from ordering clues in the spec
  • Readiness and assignment rules following hence conventions

After translation, always review and validate:

# Translate
hence plan translate spec.md --output plan.spl

# Validate syntax
hence plan validate plan.spl

# LLM review — check for gaps, ambiguities, missing tasks
hence plan review plan.spl

# Inspect the task board before distributing
hence plan board plan.spl
Note
Translation is a starting point. The generated plan will often need manual refinement — particularly around agent assignment and superiority declarations. Always read the generated file before using it.

6. Asserting findings

Asserting facts is how an agent records discoveries during work. Facts are permanent, append-only, and may unlock downstream tasks. Assert findings immediately when you discover them — do not wait until the task is complete.

Basic fact assertion

# Assert a simple fact (no quotes around the atom needed with --task)
hence task assert '(given tests-passing)' plan.spl --task my-task

# Assert without --task (asserts as the plan-level agent)
hence task assert '(given database-schema-finalized)' plan.spl

Facts that unlock downstream work

Facts named to match preconditions in readiness rules will immediately unlock dependent tasks when asserted:

# If a readiness rule reads: (normally r-ready-deploy (and task-deploy completed-tests) ready-deploy)
# then asserting completed-tests (via task complete) unlocks deploy.
# But you can also assert intermediate facts:

hence task assert '(given integration-approved)' plan.spl
hence task assert '(given security-review-passed)' plan.spl
hence task assert '(given load-test-passed)' plan.spl

Asserting decisions

# Record architectural decisions as facts
hence task assert '(given decided-use-redis)' plan.spl
hence task assert '(given decided-postgres-over-mysql)' plan.spl
hence task assert '(given discovered-api-deprecated)' plan.spl
hence task assert '(given verified-auth-endpoint-works)' plan.spl

Asserting derived rules (advanced)

You can assert not just facts, but new rules — adding logic to the plan dynamically:

# Assert a new assignment rule based on a runtime discovery
hence task assert '(normally r-new (and ready-deploy agent-devops-available) assign-to-deploy-devops)' plan.spl

# Assert a blocking defeater rule
hence task assert '(except e-block-deploy (and ready-deploy security-hold) assign-to-deploy-devops)' plan.spl

Naming conventions for asserted facts

Prefix Use for Example
discovered- Runtime findings, unexpected conditions discovered-api-rate-limited
decided- Architectural or process decisions made decided-use-postgres
verified- Validation results, confirmations verified-auth-works
approved- Human or automated approvals granted approved-security-review
failed- Failures worth recording as plan facts failed-load-test
ready- Task readiness (derived, not usually asserted directly) ready-auth
completed- Task completion (derived from claims, never assert directly) completed-auth

7. Decomposing a task into subtasks

Sometimes a claimed task turns out to be too large or too complex for a single pass. When this happens, decompose it into a subplan — a separate .spl file with its own tasks, rules, and agents. Work the subplan through the normal lifecycle, then report the result back to the parent plan.

When to decompose

  • The acceptance criteria has multiple independent deliverables — e.g., "write tests, update docs, and migrate the schema."
  • The work spans multiple domains that different agents could handle in parallel.
  • You discover unexpected complexity during execution — a task that looked simple requires prerequisite work.
  • The task would take more than one agent session to complete.

Create a subplan

Write a new .spl file for the subtasks. The subplan is a self-contained plan — it has its own metadata, tasks, readiness rules, and assignments. It does not need to import or reference the parent plan.

; build-api.spl — subplan for the build-api task in parent.spl
(meta plan
  (id "build-api-sub")
  (title "Build API subplan")
  (status "active"))

(given task-api-schema)
(meta task-api-schema
  (description "Define OpenAPI schema for all endpoints")
  (acceptance "openapi.yaml passes spectral lint"))

(given task-api-handlers)
(meta task-api-handlers
  (description "Implement route handlers")
  (acceptance "All routes return correct status codes"))

(given task-api-tests)
(meta task-api-tests
  (description "Integration tests for API")
  (acceptance "pytest suite green, coverage above 80%"))

; Dependencies: handlers need schema, tests need handlers
(normally r-ready-api-schema task-api-schema ready-api-schema)
(normally r-ready-api-handlers (and task-api-handlers completed-api-schema) ready-api-handlers)
(normally r-ready-api-tests (and task-api-tests completed-api-handlers) ready-api-tests)

; Assignments
(given agent-alice-available)
(given agent-bob-available)
(normally r-assign-api-schema (and ready-api-schema agent-alice-available) assign-to-api-schema-alice)
(normally r-assign-api-handlers (and ready-api-handlers agent-alice-available) assign-to-api-handlers-alice)
(normally r-assign-api-tests (and ready-api-tests agent-bob-available) assign-to-api-tests-bob)

Work the subplan

Execute the subplan using the standard agent loop — hence task next, claim, work, complete — just as you would any other plan:

# Work the subplan
hence task next build-api.spl
hence task claim api-schema build-api.spl
# ... do the work ...
hence task complete api-schema build-api.spl

# Check progress
hence plan board build-api.spl

Report back to the parent plan

When the subplan is complete, assert the result into the parent plan and complete the original task:

# All subtasks in build-api.spl are done.
# Assert completion back into the parent plan:
hence task complete build-api parent.spl

If the subplan produced findings relevant to other tasks in the parent, assert those too:

hence task assert '(given discovered-api-needs-rate-limiting)' parent.spl
hence task assert '(given decided-use-jwt-for-auth)' parent.spl
Why a separate file

Keeping subtasks in a separate plan file avoids bloating the parent plan with transient implementation detail. The parent plan tracks what needs to happen; the subplan tracks how. When the subplan completes, only the outcome flows back — not the internal steps. This also lets different agents or teams own subplans independently.

Automatic decomposition with hence plan decompose

Instead of writing a subplan by hand, you can use hence plan decompose to have an LLM generate subtasks automatically. The command uses abductive reasoning to tell the LLM exactly what facts need to be proved for the task to complete, then validates the generated subplan against the parent plan.

Three modes

Exactly one of --agent, --prompt-only, or --stdin is required:

ModeWhat it doesWhen to use
--agent NAME Spawns an agent process, passes the prompt, validates the output, retries on failure (up to 3 attempts) Human at terminal, or external orchestrator
--prompt-only Emits the assembled prompt to stdout and exits. No agent, no validation. When you are the LLM — get the prompt, generate SPL yourself
--stdin Reads SPL from stdin, runs full validation, outputs/merges the result Feed back your generated SPL for validation and merge

Agent mode (spawn an agent)

# Generate subtasks and print to stdout for review
hence plan decompose auth plan.spl --agent claude

# Merge subtasks directly into the parent plan
hence plan decompose auth plan.spl --agent claude --merge

Agent-reentrant mode (prompt-only + stdin)

When you are an LLM agent, you cannot spawn a nested instance of yourself. The --prompt-only and --stdin flags let you reuse your own inference capability while retaining all of hence's abductive analysis and formal validation:

# Step 1: Get the decomposition prompt (hence does orchestration)
PROMPT=$(hence plan decompose auth plan.spl --prompt-only)

# Step 2: You (the LLM agent) process $PROMPT and generate SPL...

# Step 3: Feed back for validation + merge (hence does orchestration)
echo "$SPL" | hence plan decompose auth plan.spl --stdin --merge

With --stdin --json, validation failures return structured error details per check (parse, sanity, terminal, input, namespace, no-conflict) so you can self-correct:

# If validation fails (exit code 2), JSON output includes per-check details
echo "$SPL" | hence plan decompose auth plan.spl --stdin --json
# → {"error": "interface_check_failed", "checks": {"terminal_check": {"status": "fail", ...}}}

There is no internal retry loop with --stdin — each invocation is a single validation pass. If validation fails, read the error, regenerate, and call --stdin again.

The decompose command handles:

  • Abductive analysis — runs require completed-{TASK} to discover what the task needs
  • Context assembly — sends the full plan, task metadata, dependencies, and defeater information to the LLM
  • Interface validation — checks that subtask outputs connect to parent plan inputs, namespaces don't conflict, and the bridging rule correctly produces completed-{TASK}
  • Retry on failure — with --agent, retries with error context (up to 3 attempts); with --stdin, you handle retries yourself

JSON output for automated agents

Use --json in all modes for machine-parseable output:

# Prompt as structured JSON (components, parent state, max subtasks)
hence plan decompose auth plan.spl --prompt-only --json

# Validation result as JSON (subtask list, checks, SPL)
echo "$SPL" | hence plan decompose auth plan.spl --stdin --json

# Agent mode JSON (same as stdin success output)
hence plan decompose auth plan.spl --agent claude --merge --json

See the CLI Reference for the full output schema and exit codes.

When to use decompose vs. manual subplans

Use hence plan decompose when you need a quick expansion of a task and trust the LLM to propose reasonable subtasks — it's fast and the interface validation ensures correctness. Use manual subplans when the decomposition requires domain expertise or when you want full control over subtask structure.

8. Handling blocked tasks

A task is blocked when its readiness conditions cannot be satisfied given current facts. Here is the systematic procedure for diagnosing and resolving blocked tasks.

Diagnosis flow

# Step 1: Find what preconditions are missing for a task
hence query why-not ready-TASK plan.spl

# Step 2: Find what facts would make it ready
hence query require ready-TASK plan.spl

# Step 3: If you can determine the missing fact is satisfied, assert it
hence task assert '(given missing-fact)' plan.spl

# Step 4: If the task cannot proceed due to an external dependency, block it explicitly
hence task block TASK "waiting for vendor API credentials" plan.spl

# Step 5: Re-check the board to confirm state
hence plan board plan.spl

Example: unblocking a task

# Task 'deploy' is not appearing in 'hence task next'
hence query why-not ready-deploy plan.spl
# Output: missing: completed-tests, approved-security-review

# Tests are done, we just forgot to complete the task
hence task complete tests plan.spl

# Security review was approved via Slack
hence task assert '(given approved-security-review)' plan.spl

# Now check again
hence task next plan.spl
# Output: deploy is now available

Explicit blocking

When a task cannot proceed and you cannot resolve the blocker yourself, use hence task block to leave a clear explanation for other agents or humans reviewing the plan:

hence task block deploy "prod credentials not provisioned — contact ops team" plan.spl
hence task block migrate "schema migration requires DBA sign-off" plan.spl
Do not silently abandon tasks
If you claim a task and cannot complete it, either block it with a reason or unclaim it. Leaving a task claimed but unfinished blocks all downstream work.

9. Debugging with explain / why-not

The hence query family of commands exposes the defeasible logic reasoner directly. Use these when a task state is unexpected or when you need to understand why the plan produced a particular conclusion.

Core query commands

# Explain why a fact IS concluded (shows the proof tree)
hence query explain ready-auth plan.spl

# Explain why a fact is NOT concluded (shows missing preconditions)
hence query why-not completed-auth plan.spl

# Hypothetical: what would become true if I added these facts?
hence query what-if plan.spl '(given tests-passing)' '(given review-approved)'

# Show the definition of a rule or fact
hence query describe plan.spl task-auth
hence query describe plan.spl r-assign-auth-coder

# What facts would make a given literal provable?
hence query require ready-deploy plan.spl

Proof notation

Query output uses standard defeasible logic proof notation. You will see these symbols:

Symbol Meaning Interpretation
+D Definitely provable Follows from strict rules only. Cannot be defeated.
+d Defeasibly provable Follows from defeasible rules. Currently holds but could be overridden.
-D Definitely not provable Cannot be derived; no strict rule supports it.
-d Defeasibly not provable Does not hold defeasibly; either defeated or no supporting rule.

Reading explain output

# Example: why is ready-auth concluded?
hence query explain ready-auth plan.spl

# Example output:
=== Explanation for: ready-auth ===

Contributing Sources (1):
  - unknown:anonymous

Derivation Tree:
  - ready-auth [via r-ready-auth, from unknown:anonymous]
    - task-auth [via f2, from unknown:anonymous]
    - no-deps-auth [via f5, from unknown:anonymous]

The derivation tree shows which rule fired (r-ready-auth) and which facts it depended on. Each node shows the literal, the rule that derived it (via RULE), and the agent source (from AGENT).

Using what-if for plan design

# Before asserting facts, check what they would unlock
hence query what-if plan.spl '(given tests-passing)' '(given security-approved)'

# Output shows all newly derivable conclusions, e.g.:
# +d ready-deploy
# +d assign-to-deploy-devops

10. Multi-agent coordination patterns

hence is designed for multiple LLM agents operating concurrently on the same plan. These patterns ensure correctness and avoid conflicts.

Concurrency guarantees

  • Reads are always safe: Multiple agents can run hence task next, hence plan board, and all hence query commands concurrently without conflict.
  • Claims are append-only: hence task claim appends a (claims ...) block to the plan file. Appends do not conflict with concurrent reads or other appends.
  • No locking required: The defeasible reasoner evaluates all claims in the file at query time. Concurrent claims are resolved by rule priority, not file locking.

Checking current assignments

# See all tasks and who currently holds them
hence task assign plan.spl --json

# Example output:
[
  { "task": "auth",   "agent": "security",  "status": "claimed" },
  { "task": "tests",  "agent": "coder",     "status": "claimed" },
  { "task": "review", "agent": null,        "status": "ready"   }
]

Coordination pattern: producer/consumer

When one agent produces output consumed by another, use facts to signal readiness:

# Agent A (coder) completes auth implementation
hence task complete auth plan.spl
# This derives completed-auth, which makes task-tests ready per r-ready-tests

# Agent B (tester) is polling and picks up the work
hence task next plan.spl
# Output: tests (now ready because completed-auth was derived)
hence task claim tests plan.spl

Coordination pattern: parallel independent tasks

# Both tasks are ready simultaneously — different agents claim them
# Agent A:
hence task claim frontend plan.spl

# Agent B (concurrently):
hence task claim backend plan.spl

# No conflict — different tasks, different agents

Coordination pattern: fan-in (all must complete before next)

;; In the plan, use (and completed-X completed-Y) in the readiness rule:
(normally r-ready-integration
  (and task-integration completed-frontend completed-backend)
  ready-integration)

;; Integration only becomes ready after BOTH frontend and backend complete.
;; Agents work in parallel; integration is automatically unlocked when both done.

After completing a task, always check next

# Completing a task may unlock new work immediately
hence task complete auth plan.spl
hence task next plan.spl   # <-- do this every time, not just at the start

11. Working with hence.run remote plans

Remote plans hosted on hence.run use a URL in place of a local file path. The interface is identical to local plans.

# Use a hence.run URL in place of a local file path
hence task next https://hence.run/p/TOKEN
hence task claim setup https://hence.run/p/TOKEN
hence task complete setup https://hence.run/p/TOKEN
hence task assert '(given tests-passing)' https://hence.run/p/TOKEN
hence plan board https://hence.run/p/TOKEN --json
hence query explain ready-auth https://hence.run/p/TOKEN

Every command that accepts a local path also accepts a https://hence.run/p/TOKEN URL. No additional configuration is required beyond authentication (if the plan is private).

Sharing a local plan remotely

# Publish a local plan to hence.run
hence remote new plan.spl

# Output: https://hence.run/p/abc123def456
# Share this URL with other agents

12. JSON output for programmatic use

Every read command supports --json. Use this flag whenever processing output in scripts, piping to jq, or ingesting results into another LLM call.

Command JSON output content
hence plan board plan.spl --json Object keyed by status bucket (backlog, ready, in_progress, blocked, done), each containing an array of task objects
hence plan status plan.spl --json Summary counts: ready, claimed, completed, blocked
hence plan info plan.spl --json Plan metadata from (meta plan ...)
hence task next plan.spl --json Object with {agent, next_actions} where next_actions is an array of {agent, command, literal, task} objects
hence task assign plan.spl --json Array of all current assignments with status
hence query explain ready-auth plan.spl --json Structured proof tree as JSON

Examples

# Get plan title
hence plan info plan.spl --json | jq -r '.title'

# List all ready tasks
hence plan board plan.spl --json | jq '.ready[]'

# Get all ready task names
hence plan board plan.spl --json | jq -r '.ready[] | .task'

# Count ready tasks
hence plan board plan.spl --json | jq '.ready | length'

# List done tasks
hence plan board plan.spl --json | jq '.done[]'

# Get the agent for the first available task
hence task next plan.spl --json | jq -r '.next_actions[0].agent'

# Extract the claim command for the first task
hence task next plan.spl --json | jq -r '.next_actions[0].command'

13. Common mistakes to avoid

These mistakes produce silent errors
The hence CLI will not always warn you. These mistakes cause wrong task lists, missing assignments, or plan validation failures.

Fact and rule errors

Wrong Right Why
(given completed-auth) hence task complete auth plan.spl completed-TASK is derived from claims, never asserted as a given. Asserting it directly creates a conflicting fact.
assign-to-coder assign-to-auth-coder Assignment atoms always include the task identifier: assign-to-TASK-AGENT. Missing the task makes it unroutable.
(always body head) for a policy (normally body head) Use always only for inviolable rules. Policies that might be overridden must use normally so superiority can defeat them.
Claiming a task without checking hence task next Always run hence task next first Claiming a task that is not yet ready (missing prerequisites) records a claim that will not match a ready state — wasted work.
Asserting ready-TASK directly Assert the facts that make the readiness rule fire ready-TASK should be derived by a readiness rule. Asserting it directly bypasses the logic and may produce inconsistent states.

Metadata errors

Missing Consequence
(meta plan ...) block hence plan info returns empty or errors. Plans without metadata are not self-documenting and may fail review.
(meta task-X (description "...") (acceptance "...")) Task has no acceptance criteria. hence plan review will flag it. Agents cannot confirm when the task is complete.
(meta r-X ...) on non-obvious rules Other agents cannot understand why the rule exists. Makes debugging harder and plan review will flag unexplained rules.

Process errors

Wrong pattern Correct pattern
Skip hence plan validate when writing a plan Always validate before distributing or claiming tasks
Check hence task next only at session start Check after every hence task complete — completing unlocks new work
Block a task without a reason string Always include a human-readable reason: hence task block TASK "reason" plan.spl
Use HENCE_AGENT with spaces or uppercase Agent names are kebab-case, no spaces: export HENCE_AGENT=my-agent

14. Session commands

Session commands show what the reasoner has loaded and concluded from a plan file. Use these for introspection and debugging.

# Show all facts and conclusions derived from the plan in the current session
hence session my-session-name

# List all recent sessions (plans interacted with, timestamps)
hence sessions

What session output shows

  • Loaded facts: all (given ...) atoms and asserted claims in the file
  • Derived conclusions: all atoms provable via rules given the loaded facts
  • Active claims: which agents have claimed or completed which tasks
  • Defeat information: which rules were defeated and by which superior rules
# Pipe session output into jq for filtering
hence session my-session-name --json | jq '.conclusions'
hence session my-session-name --json | jq '.claims'

15. Inline SPL reference

The complete output of hence llm spl is embedded below. An LLM reading this page already has the full SPL syntax reference in context. No command required.

# SPL Reference

Spindle Lisp is a LISP-based DSL for defeasible logic. Use `.spl` extension.

## How to Write a Plan

A complete annotated plan. Every plan follows this structure:

```lisp
;; Plan metadata — always start here (queryable via `hence info`)
(meta plan
  (id "IMPL-014")
  (title "User Authentication")
  (version "1.0.0")
  (status "active")
  (created "2026-02-14")
  (author "agent:architect")
  (spec "SPEC-014")
  (description "Implement login, session management, and token refresh"))

;; Agents
(given agent-coder-available)
(given agent-security-available)

;; Tasks and their properties
(given task-auth)
(given task-tests)
(given no-deps-auth)
(given security-sensitive-auth)

;; Task metadata — annotate every task with description + acceptance
(meta task-auth
  (description "Implement JWT auth with refresh tokens")
  (acceptance "Login endpoint returns valid JWT; refresh works; tests pass"))
(meta task-tests
  (description "Integration tests for auth endpoints")
  (acceptance "Coverage > 80%; all auth flows tested"))

;; Readiness rules — when can a task start?
(normally r-ready-auth
  (and task-auth no-deps-auth)
  ready-auth)
(normally r-ready-tests
  (and task-tests completed-auth)
  ready-tests)

;; Assignment rules — who works on what? (format: assign-to-TASK-AGENT)
(normally r-assign-coder
  (and ready-auth agent-coder-available)
  assign-to-auth-coder)
(normally r-assign-security
  (and ready-auth security-sensitive-auth agent-security-available)
  assign-to-auth-security)

;; Superiority — resolve conflicts (first label wins)
(prefer r-assign-security r-assign-coder)

;; Rule metadata — annotate rules with description + justification
(meta r-assign-security
  (description "Security-sensitive tasks go to security agent")
  (justification "Per security policy section 3.2"))
```

**Tip:** Set `HENCE_AGENT` to avoid repeating `--agent`:
```bash
export HENCE_AGENT=coder
hence task next plan.spl          # find my tasks
hence task claim auth plan.spl   # claim
hence task complete auth plan.spl # done
```

## Annotating with Metadata

Annotate everything — metadata makes plans queryable and self-documenting.

**Plan metadata** — required at the top of every plan:
```lisp
(meta plan (id "X") (title "Y") (status "active") (description "Z"))
```
Standard properties: `id`, `title`, `version`, `status`, `created`, `updated`, `author`, `spec`, `description`.

**Task metadata** — describe what and when it's done:
```lisp
(meta task-auth
  (description "Implement JWT auth with refresh tokens")
  (acceptance "Login returns valid JWT; refresh works; tests pass"))
```

**Rule metadata** — explain why a rule exists:
```lisp
(meta r-assign-security
  (description "Security tasks need security agent")
  (justification "Per security policy section 3.2"))
```

**Arbitrary metadata** on any labeled element:
```lisp
(meta r1 (confidence 0.9) (source "handbook"))
```

## Syntax Quick Reference

```
statement    ::= fact | rule | prefer | meta | import | provide | claims
fact         ::= (given atom arg*)
rule         ::= (always [label] body head)          ; strict
               | (normally [label] body head)        ; defeasible
               | (except [label] body head)          ; defeater
prefer       ::= (prefer label label+)
meta         ::= (meta label property+)
claims       ::= (claims source [:at T] [:note S] statement+)
literal      ::= atom | (atom arg*) | (not literal) | modal | temporal
modal        ::= (must literal) | (may literal) | (forbidden literal)
temporal     ::= (during literal start end)
body/head    ::= literal | (and literal+)
variable     ::= ?name | _
```

**Facts:** `(given atom)` or `(given predicate arg1 arg2)`
**Negation:** `(not literal)` — e.g. `(not flies)`, `(not (loves john mary))`
**Conjunction:** `(and literal literal+)` — e.g. `(and bird healthy)`
**Variables:** `?name` — e.g. `(normally (parent ?x ?y) (ancestor ?x ?y))`; wildcard: `_`
**Strict rule:** `(always body head)` or `(always label body head)` — cannot be defeated
**Defeasible rule:** `(normally body head)` or `(normally label body head)` — can be defeated
**Defeater:** `(except body head)` or `(except label body head)` — blocks but doesn't conclude
**Superiority:** `(prefer winner loser+)` — e.g. `(prefer r2 r1)`
**Metadata:** `(meta label (key "value")+)`
**Claims:** `(claims agent:name :at "ISO-8601" :note "text" statements...)` — source attribution
**Import:** `(import "file.spl")` or `(import "file.spl" as alias)`
**Provide:** `(provide name+)` or `(provide all)` or `(provide conclusions)`
**Modal:** `(must lit)`, `(may lit)`, `(forbidden lit)`
**Temporal:** `(during lit start end)` with `(moment year [month day ...])`, `inf`, `-inf`

## Naming Conventions (kebab-case)

| Prefix       | Purpose                       | Example                    |
|--------------|-------------------------------|----------------------------|
| `task-`      | Task identifiers              | `task-auth`                |
| `ready-`     | Task readiness                | `ready-auth`               |
| `completed-` | Task completion               | `completed-auth`           |
| `blocked-`   | Blocked tasks                 | `blocked-auth`             |
| `unblocked-` | Unblocked tasks               | `unblocked-auth`           |
| `assign-to-` | Task assignment               | `assign-to-auth-coder`     |
| `agent-`     | Agent identifiers             | `agent-coder-available`    |
| `discovered-`| Findings during execution     | `discovered-api-deprecated`|
| `decided-`   | Decisions made                | `decided-use-redis`        |
| `verified-`  | Validations                   | `verified-auth-works`      |

Note: DFL format uses `assignTo_TASK_AGENT` (underscores). Both conventions work with `hence task next`.

Quick reference card

A condensed reference for agents that already know the system.

Identity and orientation

export HENCE_AGENT=<name>
hence agent whoami
hence plan info plan.spl
hence plan board plan.spl

Work loop

hence task next plan.spl [--json]
hence task claim TASK plan.spl
hence task assert '(given FACT)' plan.spl
hence task complete TASK plan.spl

Debugging

hence query explain LITERAL plan.spl
hence query why-not LITERAL plan.spl
hence query what-if plan.spl '(given A)' '(given B)'
hence query require LITERAL plan.spl
hence query describe plan.spl LABEL

Plan authoring

hence plan validate plan.spl
hence plan review plan.spl
hence plan translate spec.md --output plan.spl

Blocking

hence task block TASK "reason" plan.spl
hence query why-not ready-TASK plan.spl

Remote plans

hence task next https://hence.run/p/TOKEN
hence task claim TASK https://hence.run/p/TOKEN
hence task complete TASK https://hence.run/p/TOKEN

JSON everywhere

hence plan board plan.spl --json
hence plan info plan.spl --json
hence plan status plan.spl --json
hence task next plan.spl --json
hence task assign plan.spl --json
hence query explain LITERAL plan.spl --json