AgentFn.Cli
0.1.0-rc.3
dotnet tool install --global AgentFn.Cli --version 0.1.0-rc.3
dotnet new tool-manifest
dotnet tool install --local AgentFn.Cli --version 0.1.0-rc.3
#tool dotnet:?package=AgentFn.Cli&version=0.1.0-rc.3&prerelease
nuke :add-package AgentFn.Cli --version 0.1.0-rc.3
AgentFn CLI
For the shortest end-to-end product walkthrough, start with the minimum aha moment guide.
Install the 0.1.0-rc.3 release candidate from NuGet:
dotnet tool install --global AgentFn.Cli --version 0.1.0-rc.3
For a local source build, pack and install from the repository:
dotnet pack agentfn-cli/src/AgentFn.Cli/AgentFn.Cli.csproj
dotnet tool install --global --add-source agentfn-cli/src/AgentFn.Cli/bin/Release AgentFn.Cli --version 0.1.0-rc.3
Authentication
The CLI supports normal user identities and Credential Clients through complementary browser,
device-code, non-interactive, profile, and stateless flows.
The AgentFn host defaults to https://agentfn.io-vii.com; use --base-url, a profile, or
AGENTFN_BASE_URL to target another deployment.
Credential Client management
The CLI mirrors the authenticated console's Credential Client management operations:
agentfn-cli clients list
agentfn-cli clients users
agentfn-cli clients create orders-service \
--display-name "Orders Service" \
--allowed-skill order-review \
--allowed-scope skill:run \
--private-jwks-out ./orders-service.private.jwks.json \
--public-jwks-out ./orders-service.public.jwks.json
agentfn-cli clients update orders-service --disable
export CLIENT_MODEL_TOKEN='replace-me'
agentfn-cli clients provider-tokens set orders-service PROVIDER_ID \
--token-env CLIENT_MODEL_TOKEN
agentfn-cli clients provider-tokens delete orders-service PROVIDER_ID
agentfn-cli clients delete orders-service
On clients create, omit --jwks-file to let AgentFn generate three RSA signing keys. Prefer
--private-jwks-out FILE and optionally --public-jwks-out FILE: the CLI reserves new files before
creating the Client, refuses to overwrite existing paths, and writes each raw JWKS with mode 0600
on Unix. Successful subprocess output then contains the private file path instead of the private keys.
Without the private output option, the CLI
prints the private JWKS and matching public JWKS exactly once; AgentFn persists only the public JWKS. Pass
--jwks-file public-jwks.json to register your own public key instead. Update supports replacement
Developers, allowed Skills, scopes, JWKS, and enabled state; use clients users to discover member
User IDs. The creator is automatically the immutable Owner, so create and update have no Owner
option. Either the Owner or a Developer must explicitly add each callable Skill. OAuth scopes and
the allowed-Skill list are both enforced, including for public Skills.
clients provider-tokens set reads the plaintext only from the named environment variable and
stores a separately encrypted model Token owned by that Credential Client. Listing a Client returns
only Token metadata. An Owner or Developer may set or delete these Tokens. Tasks can still pass
one-shot business SessionSecrets, which remain separate from the Provider credential. The
Client's own Provider Token is required for model access, and AgentFn never falls back to an Owner
or Developer's personal Token.
User-level control plane
The CLI manages only resources owned by or delegated to the current User. Platform-administrator Provider, model, Runner, and User operations remain available through the platform administration UI and their dedicated JSON-RPC operations; the CLI does not expose a platform-scope switch.
agentfn-cli account show
agentfn-cli tasks stats
agentfn-cli tasks stats --skill-id reimbursement-review
account show reads the server-side User identity and personal Provider Token metadata; it is
different from auth status, which reports only the selected local CLI profile. Task statistics
match the authenticated console aggregation and are grouped by Skill version.
Manage an owned Provider, its discovery Key, personal execution Token, discovery, and manual models:
agentfn-cli providers register \
--name private-openai \
--display-name 'Private OpenAI' \
--provider-base-url https://api.openai.com/v1/
agentfn-cli providers update PROVIDER_ID --display-name 'Private OpenAI v2'
export OPENAI_DISCOVERY_KEY='replace-me'
agentfn-cli providers discovery-key set PROVIDER_ID --key-env OPENAI_DISCOVERY_KEY
agentfn-cli providers discover PROVIDER_ID
agentfn-cli providers discovery-key delete PROVIDER_ID
agentfn-cli providers tokens list
export OPENAI_EXECUTION_TOKEN='replace-me'
agentfn-cli providers tokens set PROVIDER_ID --token-env OPENAI_EXECUTION_TOKEN
agentfn-cli providers tokens delete PROVIDER_ID
agentfn-cli models create PROVIDER_ID openai/gpt-5 \
--display-name 'GPT-5' \
--alias reasoning
agentfn-cli models update PROVIDER_ID MODEL_ID --disable
providers register is the atomic onboarding command when the Provider, optional
discovery Key, synchronized personal Token, and initial manual models should commit together.
providers update and models update apply only explicitly supplied fields, preserving all other
configuration. Provider Key and Token plaintext is accepted only through the named environment variable.
Manage Skills owned by or delegated to the current User:
agentfn-cli skills managed list --query reimbursement
agentfn-cli skills users --search alice
agentfn-cli skills members get reimbursement-review
agentfn-cli skills members set reimbursement-review \
--developer-user-id USER_ID
agentfn-cli skills drafts save ./reimbursement-review
agentfn-cli skills versions list reimbursement-review --status draft
agentfn-cli skills versions publish VERSION_ID --expected-revision REVISION
agentfn-cli skills versions deprecate VERSION_ID \
--expected-revision REVISION \
--reason 'Superseded by 2.0.0'
agentfn-cli skills versions delete-draft VERSION_ID --expected-revision REVISION
The version list returns the concurrency REVISION required by publish, deprecate, and draft
deletion. skills drafts save creates or replaces only the matching draft from the folder; use
skills publish FOLDER for the existing save-and-publish shortcut. Omitting every
--developer-user-id from skills members set clears the Developer list.
1. Interactive login
Normal users use the platform's SMS/browser login through OAuth Authorization Code + PKCE. Before
opening the browser, the CLI binds a free 127.0.0.1 port and uses it in the callback URI. The
listener is closed after code exchange and profile save:
agentfn-cli auth login
agentfn-cli auth status
Use --no-browser to print the authorization URL without launching it; the CLI still waits on its
temporary loopback listener. The built-in Client accepts arbitrary ports only for HTTP callbacks
using the exact /callback/ path on localhost, 127.0.0.1, or ::1. A successful user login
saves the access token, refresh token, public Client ID, and scopes in the selected profile. Expired
access tokens are refreshed automatically.
Skill publication and management additionally require the caller to be entitled to skill:write.
Explicit --scope values replace the normal defaults, so a profile that both manages and runs Skills should log in
with the complete set:
agentfn-cli auth login \
--scope openid \
--scope profile \
--scope offline_access \
--scope skill:read \
--scope skill:write \
--scope skill:run \
--scope task:read \
--scope model:read
To obtain an Initial Access Token for RFC 7591 OAuth Client registration, include
client.register together with every AgentFn scope the new delegated client may receive. The CLI
Client is allowed to request this protocol scope, but it is intentionally absent from the normal
login defaults:
agentfn-cli auth login \
--scope openid \
--scope profile \
--scope offline_access \
--scope client.register \
--scope skill:read \
--scope skill:run \
--scope task:read \
--scope model:read
Use the resulting User access token as the Bearer Initial Access Token at /oauth2/register; see
the repository README for the RFC 7591 request and RFC 7592 rotation rules.
Credential Clients authenticate only with private_key_jwt. Interactive login prompts for the Client ID, RSA private-key PEM path, and the kid published in the Client's JWKS:
agentfn-cli auth login \
--identity client \
--scope skill:read \
--scope task:read
2. Device-code login
Use OAuth Device Authorization Flow when the CLI runs on a remote host, container, or terminal that cannot receive a browser callback. The CLI prints a short user code, optionally opens the platform verification page, and polls the token endpoint at the server-provided interval:
agentfn-cli auth login --device-code
On a host with no browser, suppress the launch attempt and open the printed URL on another device:
agentfn-cli auth login --device-code --no-browser --timeout 900
The platform registers this flow under the separate public agent-fn-cli-device Client so the
existing Authorization Code + PKCE Client and its loopback policy remain unchanged. Both flows save
the same user profile shape and refresh tokens, and both resolve to the same opaque AgentFn user
subject. With --output subprocess, the URL and user code are written to standard error while the
single final JSON envelope remains on standard output.
3. Non-interactive login
For a Credential Client, pass the assertion-key configuration explicitly. The CLI creates a fresh, two-minute RS256 assertion, validates it at the Token Endpoint, and saves only the private-key path and kid in the profile:
agentfn-cli auth login \
--identity client \
--client-id my-service \
--client-private-key /run/secrets/my-service-key.pem \
--client-key-id my-service-key-2026-08 \
--scope skill:read \
--scope skill:run \
--scope task:read \
--scope model:read
For automation that already brokers an Authorization Code callback, generate an authorization URL,
PKCE verifier, state, and selected loopback redirect URI. Complete SMS login in another browser, validate the returned state, and
exchange the returned code with the same redirect URI:
agentfn-cli auth authorize \
--output subprocess
agentfn-cli auth login \
--authorization-code "$AUTHORIZATION_CODE" \
--code-verifier "$CODE_VERIFIER" \
--redirect-uri "$REDIRECT_URI" \
--output subprocess
auth authorize --output subprocess returns redirectUri; preserve that exact value with the
PKCE verifier. auth login requires --redirect-uri when exchanging an externally obtained code
so the token request cannot silently use a different random port.
An already issued user or client Bearer token can be saved non-interactively from a protected file or pipe without placing it in shell history or process arguments:
agentfn-cli auth login --token-stdin < /run/secrets/agentfn-access-token
--token remains available for compatibility, but --token-stdin is preferred. Private-key paths and key IDs are not secret, but the referenced PEM must remain readable only by the intended service account;
prefer protected variables or a pre-provisioned configuration file in automation.
4. Configuration profiles
--config selects a JSON file and --profile selects one of its profiles. Their environment
compatibility aliases are AGENTFN_CONFIG_FILE and AGENTFN_PROFILE. The default file is the
current user's platform configuration directory under AgentFn/config.json.
{
"version": 1,
"currentProfile": "production",
"profiles": {
"production": {
"baseUrl": "https://agentfn.io-vii.com",
"authenticationType": "credential_client",
"clientId": "my-service",
"clientPrivateKeyPath": "/run/secrets/my-service-key.pem",
"clientKeyId": "my-service-key-2026-08",
"scopes": ["skill:read", "skill:run", "task:read", "model:read"]
}
}
}
On Unix, CLI writes replace the configuration file with mode 0600. The file can contain private-key paths and
user access/refresh tokens, so it must be handled as a credential file. Use agentfn-cli auth logout --profile production to clear saved authentication while retaining the profile's host
configuration.
5. Stateless commands
Read a Bearer token from redirected standard input after any business subcommand. --token-stdin is
recursive and has the highest authentication precedence without exposing the token in process arguments:
agentfn-cli skills list --token-stdin < /run/secrets/agentfn-access-token
The compatible recursive --token option remains available when standard input cannot be used.
Explicit options override compatible AGENTFN_* environment variables, which override the selected
profile. The older environment-only flow remains supported:
export AGENTFN_BASE_URL='https://agentfn.io-vii.com'
export AGENTFN_CLIENT_ID='my-service'
export AGENTFN_CLIENT_PRIVATE_KEY='/run/secrets/my-service-key.pem'
export AGENTFN_CLIENT_KEY_ID='my-service-key-2026-08'
export AGENTFN_SCOPES='skill:read skill:run task:read model:read model-provider:manage user-byok:manage runner:manage'
agentfn-cli skills list
agentfn-cli skills search 'audit suspicious reimbursement claims'
agentfn-cli providers list
export MODEL_PROVIDER_DISCOVERY_KEY='...'
agentfn-cli providers register --name local-openai --display-name 'Local OpenAI' \
--provider-base-url https://models.example/v1 \
--discovery-key-env MODEL_PROVIDER_DISCOVERY_KEY
agentfn-cli models list --provider-id 456
agentfn-cli runners register --name gpu-runner --tag gpu --tag region:cn
agentfn-cli tasks create \
--skill review-reimbursement@1.0.0 \
--model openai/gpt-5 \
--reasoning-effort high \
--extra-body '{"chat_template_kwargs":{"enable_thinking":true}}' \
--tag gpu \
--attachments ./reimbursement-materials \
--input 'Review the attached reimbursement claim' \
--wait
Task status/result and internal Runtime steps are separate reads:
agentfn-cli tasks get TASK_ID
agentfn-cli tasks steps TASK_ID --offset 0 --limit 2000
tasks list, tasks get, and tasks steps read only the current calling subject's own Tasks.
An authenticated User inspects a managed Credential Client's read-only history through the separate
Client management commands; every current Owner and Developer is authorized:
agentfn-cli clients tasks list CLIENT_ID
agentfn-cli clients tasks get CLIENT_ID TASK_ID
agentfn-cli clients tasks steps CLIENT_ID TASK_ID --offset 0 --limit 2000
agentfn-cli clients tasks stats CLIENT_ID
When tasks steps reports a next offset, pass it to the next invocation to continue the ordered trace.
Retry a Failed, Cancelled, or TimedOut Task before its fixed seven-day deadline; Succeeded and active Tasks are not eligible:
agentfn-cli tasks retry TASK_ID --wait --timeout 600
Retry keeps TASK_ID, appends the next Attempt, and makes tasks get return that Attempt's latest status/result. tasks steps includes attemptNumber. The deadline is seven days after original Task creation and is not extended by retry; retained business Secrets and Attachments are deleted when it expires.
Task creation accepts compact catalog references instead of internal database IDs. --skill uses
NAME@VERSION, where NAME is a Skill slug or unique display name. --model uses
PROVIDER/MODEL, where the Provider is a name or unique display name and the model is an upstream
name, unique alias, or unique display name. The model portion may contain additional slashes.
--reasoning-effort VALUE applies a Provider-supported reasoning level to every model call.
--extra-body JSON accepts a non-secret JSON object up to 64 KiB and adds each property directly
to every model request body. AgentFn-controlled model, messages, streaming, tools, tool choice,
response format, and reasoning-effort fields cannot be overridden. Retry reuses the original
values from the encrypted retry payload.
--idempotency-key KEY accepts an opaque 1–200 character key with no surrounding whitespace or
control characters. For the same authenticated subject, retries with the same key return the
original Task ID and never start a second Runtime, even if the later request body differs. Use a
new key when the intended operation changes.
--attachments FOLDER recursively packages the folder contents as the Task workspace while
preserving relative paths. It excludes a root .git/ and .DS_Store files and rejects symbolic
links. Use exactly one of --input and --input-file.
--tag TAG is repeatable. A Runner can acquire a Task only when its registered tags contain every
Task tag. runners register, runners set-tags, runners enable, and runners disable always
manage only the current User's Runners, even when the caller is a platform administrator. Shared
platform Runners use separate platform JSON-RPC operations or the platform administration UI.
User-owned Providers registered with providers register can execute only on a Runner owned by the same User.
When --discovery-key-env ENVIRONMENT_VARIABLE is present, registration sends the discovery Key
from that variable to the atomic RegisterModelProvider operation. The Provider, encrypted
discovery Key, personal execution Token, and every --model either commit together or are all
rolled back. Add --no-sync-personal-token to omit the personal Token; synchronization requires the
user-byok:manage scope included in normal CLI login. The CLI never accepts or prints the discovery
Key as a literal command-line value.
The default --output interactive mode renders tables and human-readable Task summaries. For
another Agent or subprocess, use --output subprocess. This mode writes exactly one single-line
JSON envelope to stdout, writes handled errors to the envelope instead of stderr, and preserves the
process exit code:
{"schemaVersion":1,"ok":true,"command":"tasks cancel","exitCode":0,"data":{"taskId":"42","cancelled":true}}
{"schemaVersion":1,"ok":false,"command":"skills list","exitCode":64,"error":{"type":"usage","code":"invalid_arguments","message":"Command line validation failed.","details":{"messages":["..."]}}}
Completion scripts and the hidden completion callback intentionally remain raw text rather than JSON. Task-scoped secrets use --secret-env SLOT=ENVIRONMENT_VARIABLE; use --strict-secret-env when the value is at least eight characters, has no surrounding whitespace, and requires exact length-preserving Runtime redaction. The CLI never prints either value. It validates slot names, duplicate slots, count and size limits, and Strict value rules before submitting the Task. Task wait commands report only status or Attempt transitions on standard error; their final human or subprocess result remains on standard output.
Publish a Skill folder
skills publish accepts a directory directly. Keep runtime Skill files at the folder root and
local publication metadata under .agentfn/:
my-skill/
├── .agentfn/
│ ├── .skillignore # optional
│ ├── manifest.json
│ └── output-schema.json
├── demo/ # optional authoring fixture
├── SKILL.md
├── agents/
├── references/
└── scripts/
Only SKILL.md is required in the runtime package; the other runtime directories are optional.
The CLI always excludes .agentfn/, a root .git/, and .DS_Store files from the ZIP it uploads.
It also rejects symbolic links so selecting one folder cannot silently package files outside it.
.agentfn/manifest.json contains publication metadata:
{
"skillId": "my-skill",
"version": "1.0.0",
"name": "My Skill",
"description": "What the Skill does.",
"visibility": "public",
"changeNotes": "Initial release."
}
skillId, version, name, and changeNotes are required. description defaults to an empty
string and visibility defaults to public; the other accepted visibility is private.
.agentfn/output-schema.json must contain the JSON Schema that constrains the Task result.
Optional .agentfn/.skillignore keeps demos and other authoring-only files beside the Skill without
publishing them. It accepts one root-relative glob per line, # comments, *, ?, and **;
directory rules exclude the complete subtree. Negation rules beginning with ! are intentionally
unsupported, and the root SKILL.md cannot be excluded. For example:
# Task fixtures are uploaded separately with --attachments.
demo/
**/*.tmp
Publish from the repository root or any directory:
agentfn-cli skills publish ./my-skill
The command packages the folder, creates the matching Draft, and immediately publishes it. If a
previous attempt left the same version as a Draft, rerunning updates that Draft with its current
revision before publishing. Published and deprecated versions are immutable; increment the
manifest's SemVer version and update changeNotes for a new release.
The checked-in skills/use-agentfn-cli folder is a complete, directly
publishable example maintained with the CLI.
Tab completion
The CLI uses the same System.CommandLine command tree for parsing, help, validation, and completion candidates. Enable completion for the current shell session with one of:
# Bash
eval "$(agentfn-cli completion bash)"
# Zsh
eval "$(agentfn-cli completion zsh)"
# Fish
agentfn-cli completion fish | source
For PowerShell:
Invoke-Expression (agentfn-cli completion powershell | Out-String)
Add the matching command to the shell profile for persistent completion. The generated shim calls back into agentfn-cli __complete; commands, options, and constrained values therefore stay synchronized with CLI help automatically.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-rc.3 | 63 | 9/1/2026 |
| 0.1.0-rc.2 | 71 | 8/31/2026 |
| 0.1.0-rc.1 | 84 | 8/28/2026 |
Third v0.1 release candidate with separate User and managed Credential Client Task-history commands and authorization boundaries.