Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Anything after the `--` double dash (the "slop") is parsed as arguments to the c
- `completion` — Print shell completion code for the specified shell
- `cache` — Cache for transactions and contract specs
- `version` — Print version information
- `skill` — Print an AI-agent skill guide for using the Stellar CLI
- `plugin` — The subcommand for CLI plugins
- `ledger` — Fetch ledger information
- `message` — Sign and verify arbitrary messages using SEP-53
Expand Down Expand Up @@ -4860,6 +4861,14 @@ Print version information
- `--only-version-major` — Print only the major version
- `--only-commit` — Print only the commit sha

## `stellar skill`

Print an AI-agent skill guide for using the Stellar CLI

Outputs a Markdown document describing how to use the Stellar CLI idiomatically. It is meant to be read by AI coding agents (or pasted into their instructions) so they follow the CLI's conventions: using named networks, identities, and contract aliases instead of raw RPC URLs, secret keys, and hard-coded contract ids.

**Usage:** `stellar skill`

## `stellar plugin`

The subcommand for CLI plugins
Expand Down
1 change: 1 addition & 0 deletions cmd/crates/soroban-test/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod log;
mod message;
mod plugin;
mod rpc_provider;
mod skill;
mod strkey;
mod tx;
mod util;
Expand Down
16 changes: 16 additions & 0 deletions cmd/crates/soroban-test/tests/it/skill.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use soroban_test::TestEnv;

#[test]
fn skill_prints_agent_guide() {
let sandbox = TestEnv::default();
sandbox
.new_assert_cmd("skill")
.assert()
.success()
.stdout(predicates::str::contains("network use"))
.stdout(predicates::str::contains("--alias"))
.stdout(predicates::str::contains("--id"))
.stdout(predicates::str::contains("contract build"))
.stdout(predicates::str::contains("--send=no"))
.stdout(predicates::str::contains("container use"));
}
6 changes: 6 additions & 0 deletions cmd/soroban-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod ledger;
pub mod message;
pub mod network;
pub mod plugin;
pub mod skill;
pub mod snapshot;
pub mod token;
pub mod tx;
Expand Down Expand Up @@ -121,6 +122,7 @@ impl Root {
Cmd::Container(container) => container.run(&self.global_args).await?,
Cmd::Snapshot(snapshot) => snapshot.run(&self.global_args).await?,
Cmd::Version(version) => version.run(),
Cmd::Skill(skill) => skill.run(),
Cmd::Keys(id) => id.run(&self.global_args).await?,
Cmd::Token(token) => token.run(&self.global_args).await?,
Cmd::Tx(tx) => tx.run(&self.global_args).await?,
Expand Down Expand Up @@ -214,6 +216,10 @@ pub enum Cmd {
/// Print version information
Version(version::Cmd),

/// Print an AI-agent skill guide for using the Stellar CLI

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line clobbers the longer doc comment on the Cmd I believe.

#[command(long_about = skill::LONG_ABOUT)]
Skill(skill::Cmd),

/// The subcommand for CLI plugins
#[command(subcommand)]
Plugin(plugin::Cmd),
Expand Down
126 changes: 126 additions & 0 deletions cmd/soroban-cli/src/commands/skill/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Stellar CLI skill

A guide for AI agents driving the `stellar` CLI. Follow these conventions so commands stay short, reproducible, and free of hard-coded secrets and ids.

## Overview

The Stellar CLI (`stellar`) manages keys and accounts, builds and deploys smart contracts, deploys asset contracts, streams events, and encodes/decodes XDR.

- Every command has help: `stellar <command> --help`.
- List a contract's functions and their arguments on the fly:

stellar contract invoke --id <contract> -- --help

Anything after `--` is parsed against the contract's own schema.

## Networks: prefer `stellar network use`

Set a default network once instead of repeating `--network`, `--rpc-url`, and `--network-passphrase` on every command:

stellar network use testnet

After this, other commands use that network by default and you can omit the network flags entirely.

- List configured networks: `stellar network ls`
- Add a custom network: `stellar network add <name> --rpc-url <url> --network-passphrase <passphrase>`
- Clear the default: `stellar network unset`

Only pass `--network <name>` explicitly when a single command needs to target a different network than the default.

## Identities: prefer `stellar keys use`, never raw secret keys

Create named identities and select a default with `stellar keys use`, just like networks. Do not paste raw `S...` secret seeds on the command line.

stellar keys generate alice --fund # generates and funds on testnet
stellar keys use alice # sign and pay as alice by default

After `stellar keys use`, other commands sign and pay with that identity, so you can omit the source flag entirely.

- List identities: `stellar keys ls`
- Show an address: `stellar keys address alice`
- Clear the default: `stellar keys unset`

Only pass `--source <name>` when a single command needs to override the default identity.

## Contracts: use aliases, don't stash contract ids in env vars

When deploying, assign an alias with `--alias` so the CLI persists the contract id for you:

stellar contract deploy \
--wasm target/wasm32v1-none/release/hello.wasm \
--alias hello

Then reference the contract by its alias with `--id` — the CLI resolves the alias to the real contract id automatically:

stellar contract invoke --id hello -- hello --to world

Do **not** capture the deployed contract id into a shell variable or `.env` file and thread it through later commands. Aliases are stored per-network, survive across sessions, and keep commands readable.

- Manage aliases: `stellar contract alias ls`, `stellar contract alias add`, `stellar contract alias rm`
Comment thread
fnando marked this conversation as resolved.
- Asset contracts accept `--alias` too: `stellar contract asset deploy --asset <asset> --alias <name>`

## Building and deploying from source

Scaffold, build, and deploy a contract project:

stellar contract init my-project # scaffold a Cargo workspace
stellar contract build # compile to target/wasm32v1-none/release/<name>.wasm

Inside a contract project you can deploy without pointing at a `.wasm` — the CLI builds it for you:

stellar contract deploy --alias counter -- --admin alice

Constructor arguments go after the `--`, passed as `--arg-name value`; they are forwarded to the contract's `__constructor`.

- Deploy a prebuilt file: `stellar contract deploy --wasm <path> --alias <name>`
- Upload Wasm without instantiating a contract (e.g. for factories or upgrades): `stellar contract upload` (the older `install` is a deprecated alias).

## Discovering a contract's interface

Besides `stellar contract invoke --id <c> -- --help`, you can inspect a deployed contract's functions and types without invoking it:

stellar contract info interface --id <contract>

`--id` accepts a contract id or an alias and works across contract commands (it's the short form of `--contract-id`) — prefer it everywhere.
Comment thread
fnando marked this conversation as resolved.

## Reading data and parsing output

- For view/query calls, use `--send=no` to simulate without submitting a transaction or paying fees:

stellar contract invoke --id counter --send=no -- get_count

- A function's return value is printed to **stdout** as JSON; logs and diagnostics go to **stderr**. When capturing output for parsing, add `-q`/`--quiet` to silence logs and keep stdout clean.

## Data lifecycle and TTL (archival)

Contract storage is rented and each entry has a time-to-live (TTL). Behavior on expiry depends on the storage type: contract code, instance, and persistent entries are **archived** when their TTL runs out and must be restored before use, whereas **temporary** entries are deleted permanently and cannot be restored.

- `stellar contract read` — inspect a contract's storage entries
- `stellar contract extend` — bump an entry's TTL before it expires
- `stellar contract restore` — restore an archived persistent or instance entry (temporary data can't be restored)

## Running a local network

For fast, offline iteration, run a self-contained network (node + RPC + faucet) in a container:

stellar container start local

- Container engine: defaults to Docker (or any Docker-compatible CLI such as Podman). On Apple silicon (macOS 26+) you can use Apple's `container` CLI. Set the default once with `stellar container use <engine>` (engines: `docker`, `apple-container`); override a single command with `--engine`, or set `STELLAR_CONTAINER_ENGINE`.
- On testnet, fund an account through friendbot: `stellar keys fund alice`.

## Inspecting configuration

Use these to see the current state instead of guessing:

- `stellar env` — effective environment variables and config in use
- `stellar network ls` — configured networks and the default
- `stellar keys ls` — configured identities
- `stellar contract alias ls` — stored contract aliases, grouped by network

## Putting it together

stellar network use testnet
stellar keys generate alice --fund
stellar keys use alice
stellar contract deploy --wasm hello.wasm --alias hello
stellar contract invoke --id hello -- hello --to world
22 changes: 22 additions & 0 deletions cmd/soroban-cli/src/commands/skill/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use clap::Parser;

pub const LONG_ABOUT: &str = "\
Print an AI-agent skill guide for using the Stellar CLI

Outputs a Markdown document describing how to use the Stellar CLI idiomatically.
It is meant to be read by AI coding agents (or pasted into their instructions)
so they follow the CLI's conventions: using named networks, identities, and
contract aliases instead of raw RPC URLs, secret keys, and hard-coded contract
ids.
";

#[derive(Parser, Debug, Clone)]
#[group(skip)]
pub struct Cmd {}

impl Cmd {
#[allow(clippy::unused_self)]
pub fn run(&self) {
print!("{}", include_str!("SKILL.md"));
}
}
Loading