Add Ink skills and symlink installer

This commit is contained in:
tmk241
2026-08-11 16:24:21 +02:00
commit 284cf5ec90
7 changed files with 806 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
---
name: configure-ink-agent
description: >-
Use when the user asks to create, configure, audit, or explain an Ink subagent
definition, including its model, read/write scheduling class, or conjunctive
policy file. Produce the smallest startup-frozen agent definition and policy
boundary. Do not use for ordinary delegation, Ink implementation work, or
generic prompt/role authoring outside Ink.
---
# Configure an Ink agent
## One job
Define one inspectable Ink subagent identity without confusing scheduling class,
model choice, and authority.
```text
agent definition -> access class -> relative policy conjunct -> frozen child snapshot
```
## Trigger boundary
Use for explicit requests about files in `$INK_AGENT_HOME` (default
`$HOME/.ink/agents`) or a project `.ink/agents` directory, or when deciding the
policy of a named Ink child.
Do not load for launching an existing child, editing Ink source, installing
skills, or creating an external executable. `ink-cli` owns host audits;
`create-ink-agent-cli-tool` owns permission-bearing external tools.
## Contract
An agent definition is a plain text file with headers followed by one prompt
body:
```text
name: Frontend specialist
model: design
access: write
policy: frontend.policy
Implement the bounded frontend task and return proof.
```
- `name` is the human-facing identity.
- `model` is a startup-resolved alias such as `default`, `cheap`, `think`, or a
configured alias.
- `access` is mandatory: `read` or `write`.
- `policy` is optional and relative to the definition file. Its bytes become an
additional conjunct; it can narrow inherited authority but never broaden it.
- Unknown headers, unknown access values, and unreadable policy files fail
visibly.
`access` schedules actors; it does not grant tools:
- `read` children may overlap and receive an immutable host floor with no command,
file-mutation, lifecycle-mutation, or delegation authority.
- `write` children are exclusive, operate in the canonical parent cwd, pause
parent effects, and still receive only their inherited-and-narrowed effective
policy.
Agent definitions and referenced policy files are frozen at orchestrator startup.
Editing either requires restarting Ink before the change can take effect. Child
snapshots never reread cwd policy, and nested delegation is removed by the host.
## Decision loop
1. Choose `read` unless the child must produce a real effect.
2. Choose the smallest model alias that fits the specialist job.
3. Omit `policy` when the inherited parent policy is already the exact boundary.
4. Otherwise write one nearby policy file using ordinary Ink policy rows; include
only authority the role needs and rely on conjunctive narrowing.
5. Inspect the startup-frozen catalog with the operator surface before relying on
the role. Restart Ink after definition or policy changes.
6. Prove one allowed path and one denied near miss through the actual child path.
## Refusals
- Do not put policy rows in the prompt body.
- Do not use `access: write` as a substitute for command/tool policy.
- Do not grant `tool delegate` to a child; Ink removes nested delegation anyway.
- Do not create worktrees, copied workspaces, merge protocols, or per-role policy
DSLs.
- Do not use environment variables as a second mutable agent-policy channel.
## Behavior smoke
Positive: “Create a frontend writer child with only the admitted formatter and
file mutation tools” loads this skill and separates `access: write` from its
relative policy conjunct.
Negative: “Ask the existing reviewer to inspect this diff” does not load this
skill; it is ordinary delegation.
Safety: a reader request that asks for `run` or file writes remains denied even if
its role policy mentions them.
+320
View File
@@ -0,0 +1,320 @@
---
name: create-ink-agent-cli-tool
description: >-
Use when creating, implementing, splitting, or reviewing a compiled,
permission-bearing executable intended for admission through Ink policy.
Produce one inspectable executable per authority boundary with discoverable
help/contract and falsifiable safety proof. Do not use for Ink's own commands,
ordinary or one-off CLIs/scripts, or skill authoring.
---
# Create Ink agent CLI tool
## One job
Design a **permission-sized executable** whose name and argv expose its reachable
effects so Ink can discover, digest-pin, and grant it without granting a platform.
One executable need not mean one source file: share private build-time modules
when that does not widen runtime authority.
## Inspect and decide
Read only what can change the boundary:
- the exact job and every reachable side effect;
- Ink's current requirements, policy grammar, and mutation protocol;
- neighboring tools and existing executables that may already satisfy the job;
- resource, credential, selector, target, packaging, and proof contracts;
- repository requirements and tests.
Project authority outranks this skill. Missing selector semantics, credentials,
recovery rules, or external contracts are blockers—not adapter opportunities.
```text
JOB -> REUSE? -> EFFECTS -> BOUNDARY -> CONTRACT -> ARTIFACT -> PROOF
```
1. Reuse a directly inspectable executable only when granting its whole reachable
surface is honest; otherwise build the coherent missing boundary, not a wrapper.
2. Enumerate reads, mutations, network effects, secrets, state, children, and
config/plugin discovery; split where approval, blast radius, or recovery differ.
3. Define argv, selectors, streams, errors, dependencies, exhaustive versus
bounded output, and any tool-owned semantic presentation without recreating
shell grammar or a host-wide effect ontology.
4. State the runtime artifact honestly, then falsify its boundary, behavior,
presentation, and portability claims through Ink's real run entry point.
## Permission boundary
A digest proves **which executable** runs; it does not narrow that executable's
accepted argv, config, plugins, or helpers. Reuse is correct only when granting
the entire reachable surface is honest.
Split executables when approval, blast radius, credentials, selectors, drift, or
recovery differ. In particular:
- read and mutation are separate executables even when they share transport;
- upload and deletion split when recovery or approval differs;
- a generic request, cloud-admin, SDK, MCP, or `call NAME JSON` dispatcher is not
a permission boundary;
- one executable per endpoint is needless fragmentation;
- several read verbs may share one executable only when resource family,
credential scope, selectors, trust, and output contract are the same.
A script/dispatcher is the authority of its interpreter and every reachable
helper unless the host pins and revalidates all of them. Resolve first-party
helpers beside the script, constrain ambient lookup, and inventory dependencies.
If the whole boundary is too broad, admit the narrower child executable instead.
## Readers and selectors
A read executable must be structurally unable to mutate through any accepted
flag, subcommand, config, plugin, callback, helper, credential refresh, cache,
history, or telemetry path. For HTTP this normally means fixed GET/HEAD behavior,
not an arbitrary method flag. “Dry run” does not turn a mutator into a reader.
Use executable-level policy when every accepted invocation is one honest grant.
Add semantic selectors only for variable resources users may reasonably grant
differently, such as canonical path/root prefix, origin, repository, or account.
- Canonicalize selector values before access and matching.
- Prove an adjacent no-match causes no resource access.
- Do not expose invariant facts such as `action=read` or `method=GET`; the
executable already says that.
- Stdin-only transforms normally need no selectors because they acquire only
supplied input.
- A pattern is a selector only when two patterns are genuinely different grants,
not merely different queries below the same approved root.
Share read/mutation parsing or transport only through private build-time modules.
## Patterns and search
Shell globs, path filters, and content patterns are different contracts.
- Never reinterpret argv as shell syntax or perform ambient shell expansion.
- Accept a glob, fixed string, regex, or domain expression only through an
explicit mode such as `--include-glob`, `--fixed`, or `--ere`; never infer the
mode from punctuation.
- Keep matching as a separate stdin filter when all candidate bytes or records
have already been supplied.
- Put matching inside a resource reader only when it avoids opening,
transferring, traversing, or disclosing irrelevant resources inside that same
reader boundary. Canonical root/path selectors remain the authority boundary.
- Define one small established grammar. State root-relative versus basename
matching, separators, case/dotfile/symlink behavior, pattern combination,
include/exclude precedence, and invalid-pattern failure. Validate before access
where possible.
`find`/`fd` forms that execute or delete and `rg` forms that launch preprocessors
are not read boundaries merely because one intended invocation only searches. A
narrow native search tool is justified when it removes reachable effects, adds
canonical path selectors, or supplies the required static portable artifact.
Implement the coherent missing subset, not a compatibility facade or renamed
wrapper.
## Mutators
Ink mutators use its elected semantic protocol:
```text
tool stage <operation argv...> # pure; emit pinned manifest
tool match <manifest> <selectors> # deterministic policy decision
tool apply <id> <hash> # revalidate; perform once
```
Required properties:
- `stage` performs no external effect and resolves no secrets;
- the manifest pins executable identity, canonical effect, authority subject,
non-secret inputs, and drift-sensitive hashes;
- selectors are variable semantic facts, never argv prefixes, shell text, or
executable invariants;
- `apply` revalidates executable, manifest, policy snapshot, inputs, and drift;
- credentials resolve only at apply;
- retries cannot duplicate success; use upstream idempotency or reconciliation;
- an indeterminate upstream outcome is reported as indeterminate, never retried
blindly or called exactly-once;
- receipts are stable, secret-free, and sufficient for recovery;
- no direct mutation path remains beside the protocol unless project authority
explicitly places it outside policy.
## Semantic presentation
When Ink must show a domain operation better than raw stdout, the executable must
construct one canonical staged operation and derive a deterministic, bounded
**presentation projection** from it. The projection is not a second description:
the manifest binds the operation and exact semantic projection bytes. Ink owns
layout; the tool owns meaning.
Use the repository's elected projection envelope and bounds exactly; never invent
per-tool presentation formats. Within that contract, use a small display
vocabulary rather than universal effect kinds:
- headline and canonical target;
- ordered key/value facts;
- bounded text or unified diff;
- outcome and optional evidence reference.
Filesystem, HTTP, cloud, and infrastructure tools express their own semantics
with those primitives. For example, an HTTP mutator supplies method, canonical
origin/path, bounded body summary, status, and final URL as facts; it does not ask
Ink to understand an `http` effect type. An infrastructure tool supplies account,
resource, region, and requested change as facts; it does not create a renderer
branch for its provider.
The projection is presentation evidence, never authority:
- canonicalize argv and pinned inputs once into the staged operation;
- derive projection records purely from that value and hash their exact semantic
bytes with the manifest;
- render approval from the exact staged projection stored under that identity;
- apply accepts only staged id plus hash, never replacement target, body, effect,
or projection inputs;
- the receipt identifies the exact staged manifest and may add only outcome and
evidence facts; it cannot rewrite approved records;
- final rendering reuses the staged projection and overlays only validated receipt
facts, so there is no independently generated “final projection” to drift;
- it grants no policy selector, credential, retry, or execution semantics;
- it is secret-free, width-independent, stable across locale/timezone, and
bounded with an explicit omission or evidence handle;
- hash semantic records, never width-, theme-, or expansion-dependent rows;
- tools never emit colors, cursor control, borders, wrapping, or terminal layout;
- legacy and ordinary commands without a projection remain valid and use Ink's
generic argv/stdout/stderr fallback.
Do not add presentation metadata when argv plus bounded output already answers
what happened. Do add it for permission-bearing operations whose approval would
otherwise expose manifests, hashes, encoded payloads, or provider internals.
## CLI and stream contract
`tool --help` is the tested human contract: effects, argv, streams, ordering,
exits, environment/config precedence, credential timing, dependencies, pattern
semantics, and one realistic pipeline. Explicit help succeeds on stdout; usage
errors fail on stderr. Selector help gives value grammar, canonicalization, and a
least-authority policy row, including AND within one row and alternatives across
rows.
Keep argv unsurprising: options before operands, `--` ends options, `-` denotes a
natural stream, secrets never enter argv, and unknown, incompatible, or trailing
arguments fail. No hidden account, cwd, config, resource search, prompt, pager,
color, progress, or `/dev/tty` access. Stdout is records, stderr diagnostics;
records stream with bounded memory, ordinary SIGPIPE stays quiet, and machine
output is independent of display width, locale, and timezone unless documented.
Choose one output posture:
- **Exhaustive:** emit every record and let ordinary pipes narrow it; no hidden
limit, ranking, or cursor.
- **Bounded:** bound before generation, disclose omissions, and provide a stable
cursor, detail command, omitted count, or retrievable handle.
Line-oriented TSV contains no literal TAB, LF, CR, or NUL; use a documented
versioned codec or NUL-record mode only when round-trip values require it. JSON is
opt-in when structure is the payload, never the default adapter around records.
Add `tool contract` only for Ink capability discovery. Keep it deterministic,
versioned, and machine-readable, with exactly one row per variable selector and
none for invariants. Metadata never chooses policy defaults. Ink pins executable
and contract bytes; schema versions belong in output, not executable, policy, or
skill names.
Make the executable name and one-line job obvious on the collection's normal
install or help surface; do not create a parallel catalog that repeats `--help`
or `contract`. In a recommended Ink policy row, make text after `--` useful to
the provider: lead with one copyable invocation, then the job. For semantic
mutators advertise only `NAME stage ...` and state that Ink owns match/apply.
## Portability and artifact
Name the claim precisely:
- **POSIX-specified:** behavior is actually specified by POSIX;
- **POSIX-portable custom:** a custom CLI using portable POSIX facilities;
- **POSIX-shaped:** composes with POSIX streams but uses extensions;
- **platform-specific:** requires named platform facilities.
Cross-compilation proves compilation, not runtime portability. Test representative
targets and ordinary hostile conditions: missing HOME/config, non-writable cwd,
EOF/short I/O, non-TTY streams, interruption, and relevant locale/timezone
variation. Avoid assumptions about `/proc`, GNU userland, bash, writable state,
or fixed path lengths.
“Single executable” permits only documented runtime libraries; “static” permits
none. Inspect the produced artifact. Do not add daemons, plugins, sidecars,
interpreters, or generated-client machinery unless they are the named job.
## Proof
Use the smallest matrix that can falsify the actual claims:
- help/contract agree with accepted argv and selectors;
- main path and one forbidden near miss with zero unintended effect;
- each reader selector has an adjacent no-match before access;
- each mutator has admitted, approval-required, refused, drift, duplicate, and
indeterminate/recovery outcomes as applicable;
- a projected operation renders the exact staged target and change before and
after apply, with only receipt-bound outcome/evidence added; mutation of stored
projection bytes, replacement apply inputs, malformed or oversized records,
secret-bearing data, and receipt identity mismatch all fail closed;
- exhaustive output preserves every fixture record; bounded selection proves its
bound, omission signal, and continuation/detail path;
- stdout/stderr redirection, `tool | head`, empty/malformed input, `-`, and a path
beginning with `-`;
- selected record codec edge cases, including TAB/LF/CR/backslash/NUL as relevant;
- clean environment, non-TTY, target runtime smoke, and artifact dependency
inspection;
- Ink discovers, pins, decides, and executes the tool end to end.
Do not build a universal harness. One meaningful forbidden-near-miss test is worth
more than broad ceremonial coverage.
## Refusals
Do not:
- force one source file when one executable is the requirement;
- wrap or partially clone a utility whose whole admitted surface already fits;
- combine read and mutation for code reuse;
- expose a generic request/admin/registry platform;
- invent invariant selectors, a universal effect ontology, or executable-name
branches in Ink's renderer;
- let tools choose terminal styling or let presentation metadata grant authority;
- treat argv prefixes, globs, or regexes as canonical path authority;
- add pagination where a complete stream and pipes are simpler;
- dump bodies from a bounded selection or silently truncate a complete stream;
- claim read-only, portable, static, or exactly-once without falsifiable proof;
- register or recommend the tool before its help, boundary, near miss, policy,
composition, and target artifact are proven.
## Handoff
Report only:
- `job` and `boundary`;
- argv/stream/output posture;
- authority selectors and credential timing;
- artifact and runtime dependencies;
- proof through Ink's real run path, including staged-projection/receipt identity;
- remaining blast radius or untested target.
## Evaluation
- **Mutator:** an S3 uploader splits from deletion, uses `stage/match/apply`,
resolves credentials at apply, and proves duplicate and indeterminate outcomes.
- **Reader:** repository reads use canonical `path-prefix` plus an adjacent
no-access proof; executable identity makes `action=read` an invalid selector.
- **Reuse:** grant existing `grep` only if its whole surface is honest; otherwise
build the missing bounded reader, not a compatibility wrapper.
- **Pattern:** a reader may own a root-relative glob only to avoid access;
matching supplied records remains a stdin filter, not path authority.
- **Presentation:** an HTTP mutator derives method, canonical target, and bounded
body summary from one staged operation; Ink renders the exact stored projection
without an `httpsend` branch and overlays receipt-bound status/final URL only.
- **Presentation sprawl:** “support AWS changes” does not add an AWS effect enum or
renderer branch; the permission-sized infrastructure tool projects account,
region, resource, requested change, outcome, and evidence through the elected
generic vocabulary.
- **Portability/sprawl:** a cross-build alone proves neither runtime portability
nor static linkage; refuse daemons, SDKs, dispatchers, and policy editing.
+99
View File
@@ -0,0 +1,99 @@
---
name: ink-cli
description: >-
Use when the user explicitly asks an agent to audit, troubleshoot, or explain
the Ink host CLI, its frozen policy, tools, skills, sessions, or context from
available authority or user-provided output. Preserve the host/guest boundary:
never launch Ink recursively or recommend admitting `ink` to its own run policy.
Do not use for implementing Ink or creating an external executable for Ink.
---
# Ink CLI
## One job
Audit and explain the Ink host from inside an Ink-governed agent without granting
the guest authority to invoke, resume, mutate, or recursively launch its host.
This skill prevents one recurring failure: treating an operator CLI as an agent
tool, then calling a command unavailable by design or broadening policy until the
agent can recursively run Ink.
## Trigger boundary
Load this skill for explicit questions about the `ink` command,
`~/.ink/policy`, project `.ink/policy` files, visible tools or skills, session
selection, context handover, startup snapshots, or gaps in those surfaces.
Do not load it merely because ordinary work runs under Ink. External executables
intended for Ink admission belong to `create-ink-agent-cli-tool`. Ink source
changes belong to Ink's repository authority and implementation workflow.
## Host boundary and authority
- Never invoke `ink` through the model's `run` surface, and never add or recommend
a policy row that lets Ink launch itself. Its absence is intentional separation,
not a missing command permission.
- A human/operator may invoke Ink outside the governed agent. Give a copyable
operator command only when the user asks and its public help contract is proven.
- Use user-provided runtime output as runtime evidence. Otherwise inspect the
installed artifact identity and a demonstrably matching checkout's requirements,
tests, public help text, and source; label those findings as contract/source
evidence rather than executed runtime proof.
- Global and project policy files explain only their contribution. Effective
authority also depends on all policy layers, pinned executable and contract
bytes, startup freezing, and session decisions.
- Treat handovers, READMEs, examples, hidden source branches, and remembered argv
as leads. Public help owns operator-facing commands; requirements own intended
behavior; tests and source establish current checkout behavior.
Distinguish three surfaces explicitly:
1. **Operator CLI commands** such as top-level `ink sessions` or `ink context`.
2. **Model-callable Ink built-ins** exposed directly to the hosted agent.
3. **External executables** admitted through Ink's `run` policy.
A command may exist on the first surface while being intentionally unreachable on
the other two. Current source exposing flat `ink sessions` does not imply nested
`sessions list/tree/inspect/resume`, and a policy rejection does not prove the
operator command is absent.
## Decision loop
1. Classify the request as contract audit, policy audit, operator instructions,
session/context mutation, or Ink source work.
2. Establish the evidence class: user-observed runtime, installed artifact,
matching checkout contract, or unverified note.
3. Compare the claim only across the relevant surface. Label it **observed**,
**source-confirmed**, **missing**, **stale claim**, or **not proven**.
4. For an operator action, explain that the user—not the hosted agent—must run it.
Do not inspect or mutate session state as a substitute.
5. For a missing capability, require Ink's requirements authority before source
implementation. Do not model it as a new external executable merely to bypass
the host boundary.
## Refusals
- Do not edit policy to admit `ink`, call Ink recursively, log in, approve a
digest, resume or clear a session, or dump host context from the agent.
- Do not infer command absence from policy denial or command existence from a
handover. In particular, challenge invented nested session verbs.
- Do not expose raw conversation or context when bounded metadata answers the
operator's question; prompts and tool results may contain secrets.
- Do not weaken path, origin, account, or repository selectors merely to make an
unrelated external command run.
## Audit receipt
```text
EVIDENCE: <runtime output, installed artifact, matching source, or limitation>
SURFACE: <operator CLI, model built-in, or admitted external command>
FINDING: <observed/source-confirmed/missing/stale/not proven>
ACTION: <operator step, requirements step, or none>
```
Positive smoke: “Does Ink have a sessions command, and why can’t you run it?”
loads this skill, confirms the operator/model boundary, and does not alter policy.
Negative smoke: “Build a selector-aware GitHub reader for Ink” routes to
`create-ink-agent-cli-tool`.