Skip to main content

Command Line Interface

Last updated: 6 August 2026

The PlayServ CLI (playserv-cli) scaffolds, deploys, and manages your server-side Functions from the terminal. It generates a ready-to-edit C# project, provisions the function's API key, packages the build, and ships it to the PlayServ FaaS gateway.


Install

The CLI is a .NET global tool.

Prerequisites
dotnet tool install --global PlayServ.FaaS.Cli

Verify the install:

playserv-cli --help

Update later with dotnet tool update --global PlayServ.FaaS.Cli.


Quick start

1

Scaffold a function project

Start from a solution when you want several functions to share entities, contracts, and a single appsettings.Common.json. Use a standalone project for a single function.

playserv-cli init --solution --name Acme --game-id <gameId> --function Hello

Creates ./Acme/ with a solution file, Acme.Shared.Entities, Acme.Shared.Contracts, appsettings.Common.json (carrying PlayServ:GameId), nuget.config, and an initial Function.Hello wired to the shared projects.

init auto-provisions an API key for the function and writes it to PlayServ:ApiKey in the project's appsettings.json. Standalone functions also get PlayServ:GameId; in-solution functions inherit it from appsettings.Common.json.

2

Write a handler

Handlers derive from PlayServHandler<TRequest> and return a HandlerResult. Constructor-inject services — the SDK host wires them up. Each project has exactly one handler.

using PlayServ.Sdk;
using PlayServ.Sdk.Handlers;
using PlayServ.Sdk.Persistence;
using Function.PlayerProfile.Entities;
using Function.PlayerProfile.Requests;

namespace Function.PlayerProfile;

public class PlayerHandler(
IRepository<Player> players,
ILogger<PlayerHandler> logger) : PlayServHandler<CreatePlayerRequest>
{
protected override async Task<HandlerResult> HandleAsync(CreatePlayerRequest request)
{
var player = new Player { Name = request.Name, Level = request.Level };
players.Add(player);
await players.SaveChangesAsync();

logger.LogInformation("Created player {PlayerId}", player.Id);
return HandlerResult.Ok(player);
}
}
3

Deploy

cd Function.PlayerProfile
playserv-cli deploy --tag v1.0.0

The function goes live at <GatewayUrl>/player-profile (the function name is lower-cased and kebab-cased on the wire).


Configuration

The CLI reads its settings from the FaaS section of appsettings.json (next to the installed tool), or from environment variables.

FieldRequiredDescription
GatewayUrlYes (pre-filled)Address of the FaaS gateway. Ships pointing at the managed cluster (https://func.skeldar.playserv.io/run). Override here or with the FAAS_GATEWAY_URL env var to target a different gateway.
TemplatesBaseUrlNoRemote base URL for templates (<base>/<template>.zip). Empty → use bundled templates, or --src for a local folder.
DisplayLogsNoWhen true, also emit Microsoft.Extensions.Logging output alongside the CLI's styled messages. Default: false.
Gateway URL isn't stored per function

The SDK that runs inside a deployed function ships with the same default GatewayUrl, so generated appsettings.json files intentionally omit PlayServ:GatewayUrl — they carry only PlayServ:ApiKey (and PlayServ:GameId for standalone functions). Add PlayServ:GatewayUrl only when targeting a non-default gateway.


Commands

Every command accepts the global --json flag (see Output modes).

init

Scaffold a single function, or a whole solution with shared projects.

playserv-cli init --name <PascalCaseName> [--game-id <gameId>] \
[--template <simple|with-startup>] [--output <dir>] \
[--solution-path <file-or-dir>] [--src <path>] [--yes]
OptionRequiredDefaultDescription
--nameYesPascalCase function name, written into <PlayServFunctionName>.
--game-idWhen standaloneGame identifier. Ignored in-solution (read from appsettings.Common.json).
--templateNosimplesimple → minimal handler; with-startup → adds a Startup class. Standalone only.
--outputNo./Function.<Name>Target directory (must not exist or be empty).
--solution-pathNoauto-detectExplicit .sln/.slnx file or a directory containing exactly one.
--srcNoLocal folder holding template folders.
--yesNoAuto-accept the API-key rename suggestion on a name collision. Required with --json.

Standalone vs. in-solution is decided automatically: an explicit --solution-path wins; otherwise the CLI walks up from --output (up to 5 levels, or until .git) looking for a single solution file; if none is found it scaffolds a standalone project.

In every mode, init auto-provisions an API key labelled after the function (on a name collision it suggests <Fn>1, <Fn>2, … and prompts, or takes the suggestion with --yes).

deploy

Package the source as a ZIP, build it, and register a new function.

playserv-cli deploy [--tag <tag>] [--src <path>] [--namespace <ns>]
OptionDefaultDescription
--taglatestImage tag (e.g. v1.0.0, dev).
--srccurrent dirSource root (must contain a .csproj).
--namespaceTarget namespace.

The function name comes from <PlayServFunctionName> in the nearest csproj. Deploy fails if a function with that name already exists — use update, or delete first.

update

Rebuild and roll out a new version of an already-deployed function. Options are identical to deploy.

playserv-cli update [--tag <tag>] [--src <path>] [--namespace <ns>]

publish

Solution-wide deploy/update — diffs every function project in the solution against the gateway and ships them in one pass. Refuses to run outside a solution.

playserv-cli publish [--deploy] [--update] [--parallel <N>] [--tag <tag>] \
[--namespace <ns>] [--dry-run] [--yes] [--solution-path <file>] [--src <path>]
OptionDefaultDescription
--deployOnly ship functions absent from the gateway.
--updateOnly redeploy functions already on the gateway. Both omitted → ship everything.
--parallel <N>1Bounded concurrency for build/upload.
--tag <tag>latestImage tag applied to every function.
--dry-runPrint the plan and exit — no prompts, no calls.
--yesSkip the confirmation prompt. Required with --json.

Each Deploy (new) project must have a non-empty PlayServ:ApiKey in its appsettings.json, or the run fails with a hint to run init for that function.

delete

Remove a deployed function. The registry image is not deleted.

playserv-cli delete [--name <PascalCaseName>] [--src <path>]

Omit --name to resolve it from the csproj in --src or the current directory.

list

Show all deployed functions with status and invocation counts.

playserv-cli list

logs

Tail logs for a deployed function.

playserv-cli logs [--name <PascalCaseName>] [--src <path>] [--tail <lines>] [--since <ISO8601>]
OptionDefaultDescription
--namecsproj-derivedPascalCase function name.
--tail100Number of most recent entries to fetch.
--sinceISO 8601 timestamp; older entries are filtered out.

API keys

Manage API keys scoped to a game.

playserv-cli apikey-provision --game-id <gameId> [--name <keyName>]
playserv-cli apikey-list --game-id <gameId>
playserv-cli apikey-revoke --game-id <gameId> --key-id <keyId>

config-set

Set game configuration parameters (currently EOS credentials).

playserv-cli config-set --game-id <gameId> \
[--eos-client-id <id>] [--eos-client-secret <secret>] [--eos-deployment-id <id>]

Output modes

By default every command prints styled output — tables, colors, icons, and human-friendly summaries. Errors use the same style on stderr with a red headline, a detail line, and a hint.

For scripting and CI, pass the global --json flag to switch to raw JSON on stdout. In this mode errors become a single JSON object on stderr with error, detail, and hint fields.

playserv-cli list                 # styled table
playserv-cli list --json # JSON, pipe into jq

Colors auto-disable when stdout isn't a terminal. You can also override them:

VariableEffect
NO_COLOR=1Disable all ANSI colors.
FORCE_COLOR=1Force colors on even when piped.
PLAYSERV_CLI_NO_COLOR=1CLI-specific opt-out.

Exit codes: 0 on success, 1 on error (details on stderr).


Typical workflows

playserv-cli init --name Echo --game-id <gameId>
cd Function.Echo
playserv-cli deploy --tag v1.0.0 # ship it
playserv-cli list # verify
playserv-cli logs --tail 50 # tail while you invoke it
playserv-cli update --tag v1.1.0 # roll out a new version
playserv-cli delete # remove when done

Troubleshooting

  • ✗ Invalid argument. — a required option is missing or malformed. Run playserv-cli --help; each command's hint line names the flag.
  • ✗ Cannot reach the PlayServ gateway. — verify FaaS:GatewayUrl in appsettings.json (or FAAS_GATEWAY_URL) and that the gateway is running.
  • ✗ Function '<name>' already exists.deploy found a live function with that name. Use update to redeploy, or delete --name <name> first.

Next steps