jwynia/agent-bootstrap
Bootstrap agentic development environment from agent.toml manifest
npx skills add https://github.com/jwynia/agent-skills --skill agent-bootstrap
You bootstrap the agentic development environment by reading agent.toml and configuring the current tool (Claude Code, OpenCode, etc.) accordingly.
/agent-bootstrap # Validate environment and configure tool
/agent-bootstrap --verify # Run all verification checks
/agent-bootstrap --check # Dry run: report what would be configured
Self-bootstrap without external dependencies. The manifest (agent.toml) + this skill = complete environment setup. No curl|bash, no package managers, no external tools.
Use this skill when:
What this skill does:
agent.toml from repository root--verify)Symptoms:
agent.toml in repository rootKey Questions:
agent.toml?Interventions:
agent.toml based on detected project typeSymptoms:
agent.toml exists at repository root/agent-bootstrapKey Questions:
Interventions:
agent.toml using TOML parserrequired_env variablerequired_commands commandSymptoms:
Key Questions:
Interventions:
.claude/settings.json with enabled plugins.mcp.json from MCP server definitionsSymptoms:
/agent-bootstrap --verifyKey Questions:
Interventions:
[[verification.checks]] with trigger = "stop" or trigger = "explicit"# Read agent.toml from repository root
Parse the TOML file and extract:
[manifest] - version check (1.1 for remote skill support)[environment] - validation requirements[[skills]] - skill definitions (local and remote)[[plugins.*]] - plugin configuration[[mcp.servers]] - MCP server definitions[[hooks.*]] - hook definitions[[verification.checks]] - verification checksFor each skill with a source field (rather than path), install from remote:
Source Format Detection:
| Pattern | Type | Installation |
|---------|------|--------------|
| owner/repo@skill | GitHub | npx skills add owner/repo@skill -g -y |
| owner/repo@skill + version | GitHub pinned | npx skills add owner/repo@skill#version -g -y |
| skills.sh/name | Registry | npx skills add name -g -y |
| https://.../raw/.../skill | Raw URL | Fetch SKILL.md directly to ~/.claude/skills/ |
| https://....git@skill | Git URL | npx skills add <url> -g -y |
Installation Process:
ls ~/.claude/skills/skill-name/SKILL.mdReport Format:
Installing remote skills...
[1/34] gitea-workflow
Source: jwynia/agent-skills@gitea-workflow
✓ Installed
[2/34] code-review
Source: jwynia/agent-skills@code-review
✓ Already installed
[3/34] custom-skill
Source: https://gitea.example.com/.../raw/.../custom-skill
✗ Failed: Connection refused
Remote skills: 32/34 installed, 1 already present, 1 failed
Raw URL Installation (for Gitea/GitLab):
When source starts with https:// and contains /raw/:
# Create skill directory
mkdir -p ~/.claude/skills/skill-name
# Fetch SKILL.md directly
curl -sSL "https://gitea.example.com/.../raw/.../skill-name/SKILL.md" \
-o ~/.claude/skills/skill-name/SKILL.md
# Verify file was created
test -f ~/.claude/skills/skill-name/SKILL.md
Skills with version field:
When a skill has both source and version:
[[skills]]
name = "code-review"
source = "jwynia/agent-skills@code-review"
version = "v1.2.0"
Append version as git ref: npx skills add jwynia/agent-skills@code-review#v1.2.0 -g -y
For each requirement, check and report:
Environment Variables:
✓ GITHUB_TOKEN is set
✗ TAVILY_API_KEY is not set
→ Set this variable for web search functionality
Commands:
✓ git (found at /usr/bin/git)
✓ cargo (found at /home/user/.cargo/bin/cargo)
✗ node not found in PATH
→ Install Node.js: https://nodejs.org/
Runtimes:
✓ rust 1.78.0 >= 1.75.0
✗ python 3.9.7 does not satisfy >=3.10
→ Upgrade Python to 3.10 or later
Detect Current Tool:
.claude/ → Claude Code.opencode/ → OpenCode.cline/ → Cline.cursor/ → CursorFor Claude Code:
.claude/settings.json: {
"enabledPlugins": {
"plugin-name@marketplace": true
}
}
.mcp.json: {
"server-name": {
"type": "http",
"url": "https://...",
"headers": {
"Authorization": "Bearer ${ENV_VAR}"
}
}
}
Hooks defined in agent.toml:
- post_tool_use: rustfmt on *.rs files
- stop: verification script
To enable hooks, add to your Claude Code settings.
Bootstrap complete for delft-core
Environment:
✓ All required commands found (git, cargo, rustfmt, npx)
✓ All runtime versions satisfied (rust 1.78.0, node 20.11.0)
⚠ 1 optional env var not set (TAVILY_API_KEY)
Remote Skills:
✓ 34 remote skills installed
⚠ 1 skill failed to install (see above)
Configuration:
✓ Enabled plugin: rust-analyzer-lsp
✓ Generated .mcp.json with 1 server
⚠ Hooks require manual configuration
Skills: 40 skills available (6 local, 34 remote)
Next steps:
- Set TAVILY_API_KEY for enhanced web search
- Review hooks configuration in agent.toml
- Retry failed remote skill installs: npx skills add <source> -g -y
Run each verification check:
Running verification checks...
[1/4] fmt
Command: cd src && cargo fmt --check
✓ PASSED (0.8s)
[2/4] build
Command: cd src && cargo build
✓ PASSED (12.3s)
[3/4] clippy
Command: cd src && cargo clippy --workspace -- -D warnings
✗ FAILED (8.2s)
error: unused variable `x`
--> src/crates/delft-cli/src/main.rs:42:9
[4/4] tests
Command: cd src && cargo test
⏭ SKIPPED (trigger = explicit, use --verify to run)
Verification: 2/3 passed, 1 failed
Check if variable is set (not its value):
# Bash approach
if [ -z "${VAR_NAME+x}" ]; then
echo "VAR_NAME is not set"
fi
For Claude Code, use the Bash tool to check:
printenv | grep -q "^VAR_NAME=" && echo "set" || echo "not set"
command -v git >/dev/null 2>&1 && echo "found" || echo "not found"
# Rust
rustc --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
# Node
node --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+'
# Python
python3 --version | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?'
Use the Read tool to read agent.toml from repository root.
Use the Edit tool to update .claude/settings.json with plugin configuration.
Use the Write tool to create .mcp.json with MCP server configuration.
Pattern: Assuming environment is correct without validation.
Problem: Leads to confusing errors later.
Fix: Always validate. Report clearly what's missing.
Pattern: Writing environment variable values to files.
Problem: Secrets in version control.
Fix: Only write ${VAR_NAME} references, never values.
Pattern: Auto-running bootstrap without user consent.
Problem: Security risk; unexpected changes.
Fix: Always require explicit /agent-bootstrap invocation.
Pattern: Configuring everything even when not needed.
Problem: Confusing state; hard to debug.
Fix: Only configure what's declared in manifest.
User: /agent-bootstrap
Your approach:
agent.toml from repository rootUser: /agent-bootstrap --verify
Your approach:
agent.tomltrigger = "stop" or trigger = "explicit"User: /agent-bootstrap --check
Your approach:
agent.tomlUser: /agent-bootstrap (no agent.toml exists)
Your approach:
agent.toml| Source Skill | Source State | Leads to State |
|--------------|--------------|----------------|
| (none) | - | AB0 or AB1 |
| This State | Leads to Skill | Target State |
|------------|----------------|--------------|
| AB2 (configured) | gitea-workflow | (ready to work) |
| AB3 (verified) | (any) | (environment confirmed) |
| Skill | Relationship |
|-------|--------------|
| find-skills | Discover skills listed in manifest |
| context-network | May be bootstrapped after environment setup |
See docs/agent-toml-spec.md for the complete schema specification.
Key sections:
[manifest] - version (1.1 for remote skill support)[environment] - required_env, required_commands, runtimes[[skills]] - skill definitions (local with path, remote with source)[[plugins.{tool}]] - plugin configuration[[mcp.servers]] - MCP server definitions[[hooks.{tool}]] - hook configuration[[verification.checks]] - verification checks# Local skill
[[skills]]
name = "delft-authoring"
path = ".claude/skills/delft-authoring"
# Remote skill (GitHub)
[[skills]]
name = "code-review"
source = "jwynia/agent-skills@code-review"
# Remote skill with version pin
[[skills]]
name = "gitea-workflow"
source = "jwynia/agent-skills@gitea-workflow"
version = "v1.0.0"
Take jwynia/agent-bootstrap from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npx.
Without those the skill loads but fails at the first command.