Skip to content
Merged
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
64 changes: 64 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ async-stream = "0.3"
urlencoding = "2"
mime_guess = "2"
rmp-serde = "1"
schemars = { version = "1", features = ["indexmap2"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["indexmap"] }
shell-words = "1.1.0"
Expand Down
16 changes: 16 additions & 0 deletions docs/cli/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,22 @@
"hidden_aliases": [],
"examples": []
},
"schema": {
"full_cmd": [
"schema"
],
"usage": "schema",
"subcommands": {},
"args": [],
"flags": [],
"mounts": [],
"hide": true,
"help": "Generate JSON Schema for pitchfork.toml configuration",
"name": "schema",
"aliases": [],
"hidden_aliases": [],
"examples": []
},
"start": {
"full_cmd": [
"start"
Expand Down
207 changes: 128 additions & 79 deletions docs/public/schema.json
Original file line number Diff line number Diff line change
@@ -1,119 +1,168 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://pitchfork.dev/schema.json",
"title": "Pitchfork Configuration",
"description": "Configuration schema for pitchfork.toml daemon supervisor configuration files",
"type": "object",
"properties": {
"daemons": {
"type": "object",
"description": "Map of daemon names to their configurations",
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/daemon"
"$ref": "#/$defs/PitchforkTomlDaemon"
}
}
},
"additionalProperties": false,
"required": [
"daemons"
],
"$defs": {
"daemon": {
"CronRetrigger": {
"description": "Retrigger behavior for cron-scheduled daemons",
"oneOf": [
{
"description": "Retrigger only if the previous run has finished (success or error)",
"type": "string",
"const": "finish"
},
{
"description": "Always retrigger, stopping the previous run if still active",
"type": "string",
"const": "always"
},
{
"description": "Retrigger only if the previous run succeeded",
"type": "string",
"const": "success"
},
{
"description": "Retrigger only if the previous run failed",
"type": "string",
"const": "fail"
}
]
},
"PitchforkTomlAuto": {
"description": "Automatic behavior triggered by shell hooks",
"oneOf": [
{
"description": "Automatically start when entering the directory",
"type": "string",
"const": "start"
},
{
"description": "Automatically stop when leaving the directory",
"type": "string",
"const": "stop"
}
]
},
"PitchforkTomlCron": {
"description": "Cron scheduling configuration",
"type": "object",
"description": "Configuration for a single daemon",
"required": ["run"],
"properties": {
"run": {
"type": "string",
"description": "The command to run. Prepend with 'exec' to avoid shell process overhead.",
"examples": ["exec node server.js", "python -m http.server 8000"]
"retrigger": {
"description": "Behavior when cron triggers while previous run is still active",
"$ref": "#/$defs/CronRetrigger",
"default": "finish"
},
"schedule": {
"description": "Cron expression (e.g., '0 * * * *' for hourly, '*/5 * * * *' for every 5 minutes)",
"type": "string",
"examples": [
"0 * * * *"
]
}
},
"required": [
"schedule"
]
},
"PitchforkTomlDaemon": {
"description": "Configuration for a single daemon",
"type": "object",
"properties": {
"auto": {
"type": "array",
"description": "Automatic start/stop behavior based on shell hooks",
"type": "array",
"items": {
"$ref": "#/$defs/auto"
},
"uniqueItems": true,
"default": []
"$ref": "#/$defs/PitchforkTomlAuto"
}
},
"boot_start": {
"description": "Whether to start this daemon automatically on system boot",
"type": [
"boolean",
"null"
]
},
"cron": {
"$ref": "#/$defs/cron",
"description": "Cron scheduling configuration for periodic execution"
"description": "Cron scheduling configuration for periodic execution",
"anyOf": [
{
"$ref": "#/$defs/PitchforkTomlCron"
},
{
"type": "null"
}
]
},
"retry": {
"type": "integer",
"description": "Number of times to retry if the daemon fails (0 = no retries)",
"minimum": 0,
"default": 0
"depends": {
"description": "List of daemon names that must be started before this one",
"type": "array",
"items": {
"type": "string"
}
},
"ready_delay": {
"type": "integer",
"description": "Delay in milliseconds before considering the daemon ready",
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0
},
"ready_output": {
"type": "string",
"description": "Regex pattern to match in stdout/stderr to determine readiness",
"examples": ["Server listening", "Ready to accept connections"]
},
"ready_http": {
"type": "string",
"description": "HTTP URL to poll for readiness (expects 2xx response)",
"format": "uri",
"examples": ["http://localhost:3000/health"]
"type": [
"string",
"null"
]
},
"ready_output": {
"description": "Regex pattern to match in stdout/stderr to determine readiness",
"type": [
"string",
"null"
]
},
"ready_port": {
"type": "integer",
"description": "TCP port to check for readiness (connection success = ready)",
"minimum": 1,
"maximum": 65535
"type": [
"integer",
"null"
],
"format": "uint16",
"maximum": 65535,
"minimum": 1
},
"boot_start": {
"type": "boolean",
"description": "Whether to start this daemon automatically on system boot"
"retry": {
"description": "Number of times to retry if the daemon fails (0 = no retries)",
"type": "integer",
"format": "uint32",
"default": 0,
"minimum": 0
},
"depends": {
"type": "array",
"description": "List of daemon names that must be started before this one",
"items": {
"type": "string"
},
"uniqueItems": true,
"default": []
}
},
"additionalProperties": false
},
"auto": {
"type": "string",
"description": "Automatic behavior triggered by shell hooks",
"enum": ["start", "stop"]
},
"cron": {
"type": "object",
"description": "Cron scheduling configuration",
"required": ["schedule"],
"properties": {
"schedule": {
"run": {
"description": "The command to run. Prepend with 'exec' to avoid shell process overhead.",
"type": "string",
"description": "Cron expression (e.g., '0 * * * *' for hourly, '*/5 * * * *' for every 5 minutes)",
"examples": ["0 * * * *", "*/5 * * * *", "0 0 * * *"]
},
"retrigger": {
"$ref": "#/$defs/retrigger",
"description": "Behavior when cron triggers while previous run is still active",
"default": "finish"
"examples": [
"exec node server.js"
]
}
},
"additionalProperties": false
},
"retrigger": {
"type": "string",
"description": "Retrigger behavior for cron-scheduled daemons",
"enum": ["finish", "always", "success", "fail"],
"enumDescriptions": [
"Retrigger only if the previous run has finished (success or error)",
"Always retrigger, stopping the previous run if still active",
"Retrigger only if the previous run succeeded",
"Retrigger only if the previous run failed"
"required": [
"run"
]
}
}
Expand Down
1 change: 1 addition & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ run = [
"rm -rf docs/cli && mkdir -p docs/cli",
"usage g markdown -mf pitchfork.usage.kdl --out-dir docs/cli --url-prefix /cli",
"usage g json -f pitchfork.usage.kdl > docs/cli/commands.json",
"pitchfork schema > docs/public/schema.json",
"git add pitchfork.usage.kdl docs",
]

Expand Down
1 change: 1 addition & 0 deletions pitchfork.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ cmd run help="Runs a one-off daemon" {
arg <ID> help="Name of the daemon to run"
arg "[-- RUN]…" help="Command and arguments to run (after --)" required=#false var=#true
}
cmd schema hide=#true help="Generate JSON Schema for pitchfork.toml configuration"
cmd start help="Starts a daemon from a pitchfork.toml file" {
alias s
long_help "Starts a daemon from a pitchfork.toml file\n\nDaemons are defined in pitchfork.toml with a `[daemons.<name>]` section.\nThe command waits for the daemon to be ready before returning.\n\nExamples:\n pitchfork start api Start a single daemon\n pitchfork start api worker Start multiple daemons\n pitchfork start --all Start all daemons in pitchfork.toml\n pitchfork start api -f Restart daemon if already running\n pitchfork start api --delay 5 Wait 5 seconds for daemon to be ready\n pitchfork start api --output 'Listening on'\n Wait for output pattern before ready\n pitchfork start api --http http://localhost:8080/health\n Wait for HTTP endpoint to return 2xx\n pitchfork start api --port 8080\n Wait for TCP port to be listening"
Expand Down
Loading