Project Instructions and Skills
At each turn boundary Heph reads $XDG_CONFIG_HOME/heph/context.md (or
~/.config/heph/context.md), root .cursor/rules, HEPH.md, CLAUDE.md, and
AGENTS.md, in that order. Each contributes at most 64 KiB and the rendered
block at most 256 KiB. Directory-form Cursor rules are reported but not loaded.
Read or decoding errors block submission with diagnostics.
Recognized project paths changed in this conversation's accepted state overlay
the developer checkout; an accepted deletion does not fall back to checkout.
Pending and rejected edits never become instructions. Every turn stores its
exact text and source manifest and keeps them frozen through retries and review.
Acceptance activates only accepted text next turn here, without restart;
/commit publishes later. Forks and other refs retain their own accepted state.
External source changes are picked up next turn with a notice.
/instructions lists logical paths, origins, absent paths, unsupported formats,
errors, effective bytes, truncation, digests, and snapshot IDs. It separates the
active or last frozen snapshot from the next-turn preview and does not print
contents.
Create or Refine Guidance
An idle interactive launch without an initial prompt offers a reviewed
AGENTS.md when no recognized project path exists. Empty files, symlinks,
unreadable guidance, and directory-form Cursor rules suppress the offer. User
context and skills alone do not. The centered permission-style dialog uses y
to generate (g is an alias), n or Esc to dismiss this launch, and d to
disable future offers for this repository, shared across Git worktrees. Drafts
and armed skills stay untouched; dismiss the dialog before typing ordinary work.
/init --offer clears persistent suppression without a model call. Exec and
pipe mode never show it.
/init defaults to AGENTS.md when no root Markdown guidance exists, refines a
single existing target, and asks which target when several exist. Use
/init --file AGENTS.md, HEPH.md, or CLAUDE.md to name one explicitly.
Creating beside other guidance requires confirmation; Cursor rules themselves
are not editable targets. Arbitrary paths and extra options fail locally.
/init --help prints the contract.
When generation starts, an unnamed conversation immediately gets the local name
init-agents, init-heph, or init-claude for the selected target. Conflicts
get numeric suffixes such as init-agents-2. Existing names are kept, and no
title-model request is needed. Selecting or cancelling a target alone does not
name the conversation.
Finish current work, queued prompts, and pending review first. Init uses the configured coding model for a normal reviewed turn without changing sticky plan/design mode or consuming armed skills. It can read repository evidence, ask consequential policy questions, and create or exact-edit only the selected file. It cannot run commands, fetch the network, activate skills, change config, or delegate writes. Discovered commands are not labeled tested. Host-run gates still use normal permissions.
Preserve human policy and inspect the model's evidence in the review brief. No
useful change can mean no diff. Checkout-only uncommitted guidance must be
committed before refinement; differing checkout/ref versions require explicit
confirmation that the accepted ref version is intended. Accepted output is
active next turn only in this conversation and remains private until /commit.
The injected task stays excluded from ordinary prompt-based naming.
Discovery
Heph recursively discovers SKILL.md under project .agents/skills/,
.heph/skills/, .claude/skills/, and .cursor/skills/; user
~/.agents/skills/, ~/.claude/skills/, ~/.cursor/skills/, and
~/.codex/skills/; and heph/skills/, crush/skills/, and opencode/skills/
under $XDG_CONFIG_HOME (default ~/.config). These are the directories Claude
Code, Cursor, and OpenCode read, so skills installed for them work in Heph too.
Project skills take precedence over user skills with the same name, and earlier
directories in the lists above over later ones. A skill found more than once is
loaded once: a directory reached twice through a symbolic link is read once, and
a SKILL.md identical to the one already kept is skipped silently. Only a
different skill with the same name is reported as shadowed.
Discovery follows the Agent Skills specification. The name is 1-64 lowercase
letters, digits, or single hyphens and matches its directory; the description
is 1-1024 characters. The optional fields are read too:
-
licenseandcompatibility(each 1-500 characters) are shown in/skills.compatibilityis for you; it is not sent to the model. -
metadata, a map of strings, is kept and not used. -
allowed-toolsis shown asrequests tools: ...; not granted. Heph never turns it into approvals: everything a skill leads the model to do goes through the permission engine like any other call.
A skill with a malformed field, required or optional, is not loaded; /skills
lists it under "Ignored skills" with the reason. Fields the specification does
not define are tolerated, since skill directories shared with other agents carry
their own.
The catalog and activation
Only each enabled skill's name and description stays in the system prompt, and
only on a turn whose tools include skill: a plan turn on a
tool set without it is not told about skills it could not load. The Level 0
skill tool loads a skill's body when the model decides it applies. /skills
lists what Heph discovered, grouped as project or user skills, where each came
from, which are active or disabled, and why malformed or shadowed files were
ignored.
Use /skill NAME to require a skill for your next prompt. Heph inserts its
structured instructions before that prompt; the prompt remains what the TUI
shows and recalls. The activation is stored in conversation history, survives a
restart, and is inherited by a fork. Start /new when you want a context
without an earlier activation. For instructions that must apply to every task,
use AGENTS.md or HEPH.md instead of making a nonstandard always-active
skill.
An activation names the skill directory and lists up to 100 bundled resources
without loading them. The model can load a root-confined resource through the
same skill tool. Scripts still require an ordinary, permission-checked shell
or exec call.
Arming, queueing, and delivery
Tab after /skill completes the name, cycling the enabled skills that begin
with what you typed and are neither active nor already waiting. /skill refuses
a skill that is already armed or waiting with a prompt.
A skill you arm waits for the next prompt you write. If a turn is running when
you send that prompt, the prompt is queued and takes the armed skills with it; a
skill you arm after that waits for the prompt after. Each queued prompt keeps
its own skills; a later message never takes over an earlier message's skills.
Ctrl-U or Up returns only the newest queued prompt's skills to the next
prompt you write.
Nothing you arm is silently lost. After each turn Heph reads the conversation
back: a skill the turn's prompt carried that is not in it, because the turn
failed before storing the prompt or could not start at all, is armed again, with
a line saying so. An interrupted turn whose prompt was stored has delivered its
skills, and nothing is re-armed. Switching to another conversation drops what
was waiting, with a notice naming it, since whether it was already active was
decided against the conversation you left. /clear keeps it: it was never in
the context. /skills ends with what is armed for the next prompt and what the
queued prompts carry.
The skills sidebar
In a terminal at least 100 columns wide, a 30-column sidebar right of the conversation lists every skill you can use, and marks the ones the conversation holds or that wait for a prompt:
| Row | Meaning |
|---|---|
* name | Active; the model is following it |
* name (changed) | Active, but its file has changed since (below) |
* name (disabled) | Active, and disabled since; it stays in the conversation |
* name (missing) | Active, and no longer discovered |
+ name (queued) | Goes with the queued prompt |
+ name (next) | Armed for the next prompt you write |
- name | Available: enabled, not active; /skill name arms it |
A skill the running turn's prompt carries is shown as active, since the model is
reading it. Active and waiting skills come first, then the available ones in
name order; when they do not all fit, a line says how many more there are. The
skill roster's last line counts the active and the available skills. Below it,
the bottom of the sidebar shows the running heph version. If heph -V from
PATH reports a different installed version, the row turns yellow and adds
(outdated), with an installed version row beneath it so you can see how far
behind the running build is. Restart heph to use the installed build. The check
runs at startup and once a minute without blocking input. Failed checks leave
the last known result unchanged. By default the sidebar shows whenever there is
a skill or spend to show; it shares space with today's provider/model costs
(Models); [ui] sidebar = "on" or "off"
(UI) forces it, /sidebar on|off|auto sets it for the
session, and Ctrl-S or a bare /sidebar toggles it. Where the sidebar is not
drawn, the input's title counts the skills waiting: message (+2 skills).
When a skill changes
What the conversation holds is the exact text the model was given. Heph compares it with the skill as it is discovered now, on the instructions and the resource list; the directory line is not compared, so moving the checkout does not count as a change.
-
An active skill that is unchanged is not injected twice:
/skillrefuses it and theskilltool answers that it is already active. -
An active skill that has changed on disk shows in
/skillsas[active] (changed on disk)./skill NAMEarms the new version, and theskilltool returns it with a line saying it replaces the earlier one. The newer copy is the one that counts from then on; both stay in the conversation. -
An active skill that is no longer discovered, because it was deleted, moved away, or its project directories were turned off, shows as
[active] (not found on disk). It stays in the conversation, since history is not rewritten, and cannot be armed again.
Reloading
Heph discovers skills when it starts. /skills --reload discovers them again
and rereads [skills] from both config files, so an edited, added, or deleted
skill, or a change to disabled, takes effect without a restart. The reply
names what changed, or says nothing did. Only [skills] is reread; every other
setting, and the context files, still need a restart.
A turn running during the reload keeps the skills it started with; the next turn
uses the new ones. When the reload changes the catalog in the system prompt, the
reply says so: the next request writes the cached prompt prefix again, which
costs more once. A config file that no longer loads, including a project file
that sets [skills] project, fails the reload with its error and leaves
everything as it was.
Disabling skills and trusting projects
[skills] disabled keeps named skills from the model: they are left out of the
catalog and the skill tool, and both /skill and the tool refuse them, naming
the config file that disabled them. [skills] project = false in your user file
refuses every project's skills. A project skill is otherwise trusted as the
project's AGENTS.md is: it can change what the model is told, and nothing
else. See Skills.
Outside a session
heph skills prints the /skills report for the project, and with --ref REF
marks what is active on that conversation. heph skills show NAME prints one
skill in full: every frontmatter field, where it came from, its resources, and
the activation payload the model would receive. heph exec --skill NAME arms a
skill for a non-interactive turn (heph exec).
heph skills check is for skill authors and CI: it validates every discovered
skill, or the SKILL.md files and directories you name, prints each problem,
and exits 1 if any skill is invalid. It is heph's counterpart of the
specification's skills-ref validate, and differs from it in two ways:
-
A frontmatter field the specification does not define is a warning, and the exit status stays 0.
skills-refrejects it, but skill directories shared with other agents carry their own fields, and heph loads such skills. -
Names must be ASCII: lowercase
a-z, digits, and single hyphens.skills-refalso accepts other lowercase letters; heph does not load a skill so named, and says why.
None of these needs a model configured, and only --ref opens the database.