@enactprotocol/cli 2.1.24 → 2.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/commands/index.d.ts +2 -0
  2. package/dist/commands/index.d.ts.map +1 -1
  3. package/dist/commands/index.js +4 -0
  4. package/dist/commands/index.js.map +1 -1
  5. package/dist/commands/init/templates/claude.d.ts +1 -1
  6. package/dist/commands/init/templates/claude.d.ts.map +1 -1
  7. package/dist/commands/init/templates/claude.js +268 -28
  8. package/dist/commands/init/templates/claude.js.map +1 -1
  9. package/dist/commands/init/templates/tool-agents.d.ts +1 -1
  10. package/dist/commands/init/templates/tool-agents.d.ts.map +1 -1
  11. package/dist/commands/init/templates/tool-agents.js +90 -15
  12. package/dist/commands/init/templates/tool-agents.js.map +1 -1
  13. package/dist/commands/install/index.d.ts.map +1 -1
  14. package/dist/commands/install/index.js +9 -1
  15. package/dist/commands/install/index.js.map +1 -1
  16. package/dist/commands/learn/index.d.ts.map +1 -1
  17. package/dist/commands/learn/index.js +4 -11
  18. package/dist/commands/learn/index.js.map +1 -1
  19. package/dist/commands/mcp/index.d.ts.map +1 -1
  20. package/dist/commands/mcp/index.js +204 -53
  21. package/dist/commands/mcp/index.js.map +1 -1
  22. package/dist/commands/run/index.d.ts.map +1 -1
  23. package/dist/commands/run/index.js +380 -39
  24. package/dist/commands/run/index.js.map +1 -1
  25. package/dist/commands/validate/index.d.ts +11 -0
  26. package/dist/commands/validate/index.d.ts.map +1 -0
  27. package/dist/commands/validate/index.js +299 -0
  28. package/dist/commands/validate/index.js.map +1 -0
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +6 -2
  32. package/dist/index.js.map +1 -1
  33. package/dist/types.d.ts +2 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js.map +1 -1
  36. package/dist/utils/errors.d.ts +8 -1
  37. package/dist/utils/errors.d.ts.map +1 -1
  38. package/dist/utils/errors.js +13 -2
  39. package/dist/utils/errors.js.map +1 -1
  40. package/package.json +5 -5
  41. package/src/commands/index.ts +5 -0
  42. package/src/commands/init/templates/claude.ts +268 -28
  43. package/src/commands/init/templates/tool-agents.ts +90 -15
  44. package/src/commands/install/index.ts +11 -0
  45. package/src/commands/learn/index.ts +6 -11
  46. package/src/commands/mcp/index.ts +768 -0
  47. package/src/commands/run/README.md +68 -1
  48. package/src/commands/run/index.ts +475 -35
  49. package/src/commands/validate/index.ts +344 -0
  50. package/src/index.ts +8 -1
  51. package/src/types.ts +2 -0
  52. package/src/utils/errors.ts +26 -6
  53. package/tests/commands/init.test.ts +2 -2
  54. package/tests/commands/run.test.ts +260 -0
  55. package/tests/commands/validate.test.ts +81 -0
  56. package/tests/utils/errors.test.ts +36 -0
  57. package/tsconfig.tsbuildinfo +1 -1
@@ -24,4 +24,6 @@ export { configureInspectCommand } from "./inspect";
24
24
  export { configureYankCommand } from "./yank";
25
25
  export { configureUnyankCommand } from "./unyank";
26
26
  export { configureVisibilityCommand } from "./visibility";
27
+ export { configureMcpCommand } from "./mcp";
28
+ export { configureValidateCommand } from "./validate";
27
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAGpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAGpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAG5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
@@ -28,4 +28,8 @@ export { configureYankCommand } from "./yank";
28
28
  export { configureUnyankCommand } from "./unyank";
29
29
  // Private tools (Phase - visibility management)
30
30
  export { configureVisibilityCommand } from "./visibility";
31
+ // MCP integration commands
32
+ export { configureMcpCommand } from "./mcp";
33
+ // Validation command
34
+ export { configureValidateCommand } from "./validate";
31
35
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,8BAA8B;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhD,wCAAwC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,4BAA4B;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,gDAAgD;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,8BAA8B;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhD,wCAAwC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,4BAA4B;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,gDAAgD;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,2BAA2B;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE5C,qBAAqB;AACrB,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * CLAUDE.md template for Claude integration
3
3
  */
4
- export declare const claudeTemplate = "# CLAUDE.md\n\nThis project uses Enact tools \u2014 containerized, signed executables you can run via CLI.\n\n## Quick Reference\n```bash\nenact run <tool> --args '{\"key\": \"value\"}' # Run a tool\nenact search \"keyword\" # Find tools\nenact learn author/tool # View tool documentation\nenact install author/tool # Install tool\nenact list # List installed tools\n```\n\n## Running Tools\nTools take JSON input and return JSON output:\n```bash\n# Run and capture output\nresult=$(enact run author/utils/formatter --args '{\"code\": \"const x=1\"}')\n\n# Parse with jq\nenact run tool --args '{}' | jq '.data'\n```\n\n## Creating Tools\nCreate `SKILL.md` in a directory:\n```yaml\n---\nname: namespace/category/tool\ndescription: Clear description for search\nversion: 1.0.0\nfrom: python:3.12-slim # Docker image\nbuild: pip install requests # Install dependencies (cached)\ncommand: python /work/main.py ${input}\ninputSchema:\n type: object\n properties:\n input: { type: string, description: \"The input to process\" }\n required: [input]\n---\n# Tool Name\nUsage documentation here.\n```\n\nKey points:\n- `${param}` is auto-quoted \u2014 never add manual quotes\n- `from:` pin image versions (not `:latest`)\n- `build:` steps are cached by Dagger\n- Output JSON to stdout, errors to stderr\n- Non-zero exit = failure\n\n## Tool Development Workflow\n```bash\nenact run ./ --args '{\"input\": \"test\"}' # Test locally\nenact run ./ --args '{}' --dry-run # Preview command\nenact sign ./ && enact publish ./ # Publish\n```\n\n## Secrets\nDeclare in SKILL.md, set via CLI:\n```yaml\nenv:\n API_KEY: # Declared but not set\n```\n```bash\nenact env set API_KEY --secret --namespace author/tool\n```\n";
4
+ export declare const claudeTemplate = "# CLAUDE.md\n\nThis project uses Enact tools \u2014 containerized, cryptographically-signed executables you can run via CLI.\n\n## Quick Reference\n\n| Task | Command |\n|------|---------|\n| Run with JSON | `enact run <tool> --args '{\"key\": \"value\"}'` |\n| Run from file | `enact run <tool> --input-file inputs.json` |\n| Dry run | `enact run <tool> --args '{}' --dry-run` |\n| Debug params | `enact run <tool> --args '{}' --debug` |\n| Search tools | `enact search \"keyword\"` |\n| View docs | `enact learn author/tool` |\n| Install tool | `enact install author/tool` |\n| List installed | `enact list` |\n| Sign & publish | `enact sign ./ && enact publish ./` |\n\n## Running Tools\n\nTools take JSON input and return JSON output:\n```bash\n# Run and capture output\nresult=$(enact run author/utils/formatter --args '{\"code\": \"const x=1\"}')\n\n# Parse with jq\nenact run tool --args '{}' | jq '.data'\n```\n\n## SKILL.md Structure\n\nEach tool is defined by a `SKILL.md` file (YAML frontmatter + Markdown docs):\n\n```yaml\n---\nname: namespace/category/tool\ndescription: What the tool does\nversion: 1.0.0\nenact: \"2.0.0\"\n\nfrom: python:3.12-slim # Docker image (pin versions, not :latest)\nbuild: pip install requests # Build steps (cached by Dagger)\ncommand: python /workspace/main.py ${input}\ntimeout: 30s\n\ninputSchema:\n type: object\n properties:\n input:\n type: string\n description: \"Input to process\"\n required: [input]\n\noutputSchema:\n type: object\n properties:\n result:\n type: string\n\nenv:\n API_KEY:\n description: \"External API key\"\n secret: true # Set via: enact env set API_KEY --secret\n---\n# Tool Name\nDocumentation here.\n```\n\n## Field Reference\n\n| Field | Description |\n|-------|-------------|\n| `name` | Hierarchical ID: `org/category/tool` |\n| `description` | What the tool does |\n| `version` | Semver version |\n| `from` | Docker image |\n| `build` | Build commands (string or array, cached) |\n| `command` | Shell command with `${param}` substitution |\n| `timeout` | Max execution time (e.g., \"30s\", \"5m\") |\n| `inputSchema` | JSON Schema for inputs |\n| `outputSchema` | JSON Schema for outputs |\n| `env` | Environment variables and secrets |\n\n## Parameter Substitution\n\nEnact auto-quotes parameters. **Never manually quote:**\n\n```yaml\n# WRONG - causes double-quoting\ncommand: python /workspace/main.py \"${input}\"\n\n# RIGHT - Enact handles quoting\ncommand: python /workspace/main.py ${input}\n```\n\n**Optional vs Required Parameters:**\n\nParameters listed in the `required` array must be provided. All other properties are optional.\n\n```yaml\ninputSchema:\n type: object\n properties:\n url: # Required (in required array)\n type: string\n user_agent: # Optional (not in required array)\n type: string\n default: \"Mozilla/5.0\" # Provide default for optional params\n timeout:\n type: number\n default: 30\n required: [url] # Only url is required\n```\n\n**Best practices for optional parameters:**\n1. Always provide a `default` value in the schema when possible\n2. Optional params without defaults become empty strings in commands\n3. Use `--debug` to see how parameters are resolved: `enact run ./ --debug`\n\nHandle optional params in shell commands:\n```yaml\ncommand: \"curl ${url} -A '${user_agent:-Mozilla/5.0}' --max-time ${timeout:-30}\"\n```\n\nModifiers:\n- `${param}` \u2014 auto-quoted (handles spaces, JSON, special chars)\n- `${param:raw}` \u2014 raw, no quoting (use carefully)\n\n## Output\n\nOutput valid JSON to stdout when `outputSchema` is defined:\n\n```python\nimport json, sys\n\ntry:\n result = do_work()\n print(json.dumps({\"status\": \"success\", \"result\": result}))\nexcept Exception as e:\n print(json.dumps({\"status\": \"error\", \"message\": str(e)}))\n sys.exit(1) # non-zero = error\n```\n\n## Build Steps by Language\n\n**Python:**\n```yaml\nfrom: python:3.12-slim\nbuild: pip install requests pandas\n```\n\n**Node.js:**\n```yaml\nfrom: node:20-alpine\nbuild:\n - npm install\n - npm run build\n```\n\n**Rust:**\n```yaml\nfrom: rust:1.83-slim\nbuild: rustc /workspace/main.rs -o /workspace/tool\ncommand: /workspace/tool ${input}\n```\n\n**Go:**\n```yaml\nfrom: golang:1.22-alpine\nbuild: cd /workspace && go build -o tool main.go\ncommand: /workspace/tool ${input}\n```\n\n**System packages:**\n```yaml\nbuild: apt-get update && apt-get install -y libfoo-dev\n```\n\nBuild steps are cached \u2014 first run slow, subsequent runs instant.\n\n## Base Image Requirements\n\nNot all Docker images work as Enact base images. Requirements:\n\n**Must have:**\n- `/bin/sh` (POSIX shell) - Enact wraps commands with `sh -c`\n- Standard filesystem layout\n\n**Recommended base images:**\n| Language | Image | Notes |\n|----------|-------|-------|\n| Python | `python:3.12-slim` | Best balance of size/features |\n| Node.js | `node:20-alpine` | Smallest, may need build tools |\n| Ruby | `ruby:3.2-slim` | For Ruby tools |\n| Go | `golang:1.22-alpine` | Compile in build step |\n| Rust | `rust:1.83-slim` | Compile in build step |\n| General | `alpine:3.18` | Minimal, use apk for packages |\n| Debian | `debian:bookworm-slim` | More packages, larger |\n\n**Images that may NOT work:**\n- Distroless images (no shell)\n- Scratch images (no shell)\n- Some specialized images with custom entrypoints\n\n**Debugging image issues:**\n```bash\n# Test if an image works with Enact\nenact exec . \"echo test\" # Run simple command in tool's container\nenact run ./ --verbose # See detailed container output\n```\n\n## File Access\n\nTools run in a container with `/workspace` as the working directory. All source files are copied there.\n\n## Secrets\n\nDeclare in `SKILL.md`:\n```yaml\nenv:\n API_KEY:\n description: \"API key for service\"\n secret: true\n```\n\nSet before running:\n```bash\nenact env set API_KEY --secret --namespace author/tool\n```\n\nAccess in code:\n```python\nimport os\napi_key = os.environ.get('API_KEY')\n```\n\n## LLM Instruction Tools\n\nTools without a `command` field are interpreted by LLMs:\n\n```yaml\n---\nname: myorg/ai/reviewer\ndescription: AI-powered code review\ninputSchema:\n type: object\n properties:\n code: { type: string }\n required: [code]\noutputSchema:\n type: object\n properties:\n issues: { type: array }\n score: { type: number }\n---\n# Code Reviewer\n\nYou are a senior engineer. Review the code for bugs, style, and security.\nReturn JSON: {\"issues\": [...], \"score\": 75}\n```\n\n## Publishing Checklist\n\n- [ ] `name` follows `namespace/category/tool` pattern\n- [ ] `version` set (semver)\n- [ ] `description` is clear and searchable\n- [ ] `inputSchema` / `outputSchema` defined\n- [ ] `from` uses pinned image version\n- [ ] `timeout` set appropriately\n- [ ] Tool tested locally with `enact run ./`\n\n## Troubleshooting\n\n```bash\nenact run ./ --args '{\"x\": \"y\"}' --verbose # Verbose output\nenact run ./ --args '{}' --dry-run # Preview command without running\nenact run ./ --args '{}' --debug # Show parameter resolution details\nenact list # List installed tools\n```\n\n**Common issues:**\n\n| Issue | Solution |\n|-------|----------|\n| \"Missing required parameter\" | Check your `required` array in inputSchema |\n| Parameters not substituting | Use `--debug` to see what values are being passed |\n| Optional params failing | Add `default` values or handle empty strings |\n| Build step fails | Use `--verbose` to see build output |\n| Base image not working | Use recommended images (see Base Image Requirements) |\n| Command exit code 2 | Check if command exists in the container |\n\n**Debugging build failures:**\n```bash\nenact run ./ --args '{}' --verbose # See build output\nenact exec . \"which python\" # Check if command exists\nenact exec . \"ls /workspace\" # Check file mounts\nenact validate ./ # Validate SKILL.md structure\n```\n\n**Multi-step builds:** Use YAML array syntax for clearer error reporting:\n```yaml\nbuild:\n - apk add --no-cache ruby ruby-dev\n - gem install bundler\n - bundle install\n```\n";
5
5
  //# sourceMappingURL=claude.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/templates/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,cAAc,20DAkE1B,CAAC"}
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/templates/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,cAAc,8pQAkT1B,CAAC"}
@@ -3,18 +3,24 @@
3
3
  */
4
4
  export const claudeTemplate = `# CLAUDE.md
5
5
 
6
- This project uses Enact tools — containerized, signed executables you can run via CLI.
6
+ This project uses Enact tools — containerized, cryptographically-signed executables you can run via CLI.
7
7
 
8
8
  ## Quick Reference
9
- \`\`\`bash
10
- enact run <tool> --args '{"key": "value"}' # Run a tool
11
- enact search "keyword" # Find tools
12
- enact learn author/tool # View tool documentation
13
- enact install author/tool # Install tool
14
- enact list # List installed tools
15
- \`\`\`
9
+
10
+ | Task | Command |
11
+ |------|---------|
12
+ | Run with JSON | \`enact run <tool> --args '{"key": "value"}'\` |
13
+ | Run from file | \`enact run <tool> --input-file inputs.json\` |
14
+ | Dry run | \`enact run <tool> --args '{}' --dry-run\` |
15
+ | Debug params | \`enact run <tool> --args '{}' --debug\` |
16
+ | Search tools | \`enact search "keyword"\` |
17
+ | View docs | \`enact learn author/tool\` |
18
+ | Install tool | \`enact install author/tool\` |
19
+ | List installed | \`enact list\` |
20
+ | Sign & publish | \`enact sign ./ && enact publish ./\` |
16
21
 
17
22
  ## Running Tools
23
+
18
24
  Tools take JSON input and return JSON output:
19
25
  \`\`\`bash
20
26
  # Run and capture output
@@ -24,48 +30,282 @@ result=$(enact run author/utils/formatter --args '{"code": "const x=1"}')
24
30
  enact run tool --args '{}' | jq '.data'
25
31
  \`\`\`
26
32
 
27
- ## Creating Tools
28
- Create \`SKILL.md\` in a directory:
33
+ ## SKILL.md Structure
34
+
35
+ Each tool is defined by a \`SKILL.md\` file (YAML frontmatter + Markdown docs):
36
+
29
37
  \`\`\`yaml
30
38
  ---
31
39
  name: namespace/category/tool
32
- description: Clear description for search
40
+ description: What the tool does
33
41
  version: 1.0.0
34
- from: python:3.12-slim # Docker image
35
- build: pip install requests # Install dependencies (cached)
36
- command: python /work/main.py \${input}
42
+ enact: "2.0.0"
43
+
44
+ from: python:3.12-slim # Docker image (pin versions, not :latest)
45
+ build: pip install requests # Build steps (cached by Dagger)
46
+ command: python /workspace/main.py \${input}
47
+ timeout: 30s
48
+
37
49
  inputSchema:
38
50
  type: object
39
51
  properties:
40
- input: { type: string, description: "The input to process" }
52
+ input:
53
+ type: string
54
+ description: "Input to process"
41
55
  required: [input]
56
+
57
+ outputSchema:
58
+ type: object
59
+ properties:
60
+ result:
61
+ type: string
62
+
63
+ env:
64
+ API_KEY:
65
+ description: "External API key"
66
+ secret: true # Set via: enact env set API_KEY --secret
42
67
  ---
43
68
  # Tool Name
44
- Usage documentation here.
69
+ Documentation here.
70
+ \`\`\`
71
+
72
+ ## Field Reference
73
+
74
+ | Field | Description |
75
+ |-------|-------------|
76
+ | \`name\` | Hierarchical ID: \`org/category/tool\` |
77
+ | \`description\` | What the tool does |
78
+ | \`version\` | Semver version |
79
+ | \`from\` | Docker image |
80
+ | \`build\` | Build commands (string or array, cached) |
81
+ | \`command\` | Shell command with \`\${param}\` substitution |
82
+ | \`timeout\` | Max execution time (e.g., "30s", "5m") |
83
+ | \`inputSchema\` | JSON Schema for inputs |
84
+ | \`outputSchema\` | JSON Schema for outputs |
85
+ | \`env\` | Environment variables and secrets |
86
+
87
+ ## Parameter Substitution
88
+
89
+ Enact auto-quotes parameters. **Never manually quote:**
90
+
91
+ \`\`\`yaml
92
+ # WRONG - causes double-quoting
93
+ command: python /workspace/main.py "\${input}"
94
+
95
+ # RIGHT - Enact handles quoting
96
+ command: python /workspace/main.py \${input}
45
97
  \`\`\`
46
98
 
47
- Key points:
48
- - \`\${param}\` is auto-quoted — never add manual quotes
49
- - \`from:\` pin image versions (not \`:latest\`)
50
- - \`build:\` steps are cached by Dagger
51
- - Output JSON to stdout, errors to stderr
52
- - Non-zero exit = failure
99
+ **Optional vs Required Parameters:**
53
100
 
54
- ## Tool Development Workflow
101
+ Parameters listed in the \`required\` array must be provided. All other properties are optional.
102
+
103
+ \`\`\`yaml
104
+ inputSchema:
105
+ type: object
106
+ properties:
107
+ url: # Required (in required array)
108
+ type: string
109
+ user_agent: # Optional (not in required array)
110
+ type: string
111
+ default: "Mozilla/5.0" # Provide default for optional params
112
+ timeout:
113
+ type: number
114
+ default: 30
115
+ required: [url] # Only url is required
116
+ \`\`\`
117
+
118
+ **Best practices for optional parameters:**
119
+ 1. Always provide a \`default\` value in the schema when possible
120
+ 2. Optional params without defaults become empty strings in commands
121
+ 3. Use \`--debug\` to see how parameters are resolved: \`enact run ./ --debug\`
122
+
123
+ Handle optional params in shell commands:
124
+ \`\`\`yaml
125
+ command: "curl \${url} -A '\${user_agent:-Mozilla/5.0}' --max-time \${timeout:-30}"
126
+ \`\`\`
127
+
128
+ Modifiers:
129
+ - \`\${param}\` — auto-quoted (handles spaces, JSON, special chars)
130
+ - \`\${param:raw}\` — raw, no quoting (use carefully)
131
+
132
+ ## Output
133
+
134
+ Output valid JSON to stdout when \`outputSchema\` is defined:
135
+
136
+ \`\`\`python
137
+ import json, sys
138
+
139
+ try:
140
+ result = do_work()
141
+ print(json.dumps({"status": "success", "result": result}))
142
+ except Exception as e:
143
+ print(json.dumps({"status": "error", "message": str(e)}))
144
+ sys.exit(1) # non-zero = error
145
+ \`\`\`
146
+
147
+ ## Build Steps by Language
148
+
149
+ **Python:**
150
+ \`\`\`yaml
151
+ from: python:3.12-slim
152
+ build: pip install requests pandas
153
+ \`\`\`
154
+
155
+ **Node.js:**
156
+ \`\`\`yaml
157
+ from: node:20-alpine
158
+ build:
159
+ - npm install
160
+ - npm run build
161
+ \`\`\`
162
+
163
+ **Rust:**
164
+ \`\`\`yaml
165
+ from: rust:1.83-slim
166
+ build: rustc /workspace/main.rs -o /workspace/tool
167
+ command: /workspace/tool \${input}
168
+ \`\`\`
169
+
170
+ **Go:**
171
+ \`\`\`yaml
172
+ from: golang:1.22-alpine
173
+ build: cd /workspace && go build -o tool main.go
174
+ command: /workspace/tool \${input}
175
+ \`\`\`
176
+
177
+ **System packages:**
178
+ \`\`\`yaml
179
+ build: apt-get update && apt-get install -y libfoo-dev
180
+ \`\`\`
181
+
182
+ Build steps are cached — first run slow, subsequent runs instant.
183
+
184
+ ## Base Image Requirements
185
+
186
+ Not all Docker images work as Enact base images. Requirements:
187
+
188
+ **Must have:**
189
+ - \`/bin/sh\` (POSIX shell) - Enact wraps commands with \`sh -c\`
190
+ - Standard filesystem layout
191
+
192
+ **Recommended base images:**
193
+ | Language | Image | Notes |
194
+ |----------|-------|-------|
195
+ | Python | \`python:3.12-slim\` | Best balance of size/features |
196
+ | Node.js | \`node:20-alpine\` | Smallest, may need build tools |
197
+ | Ruby | \`ruby:3.2-slim\` | For Ruby tools |
198
+ | Go | \`golang:1.22-alpine\` | Compile in build step |
199
+ | Rust | \`rust:1.83-slim\` | Compile in build step |
200
+ | General | \`alpine:3.18\` | Minimal, use apk for packages |
201
+ | Debian | \`debian:bookworm-slim\` | More packages, larger |
202
+
203
+ **Images that may NOT work:**
204
+ - Distroless images (no shell)
205
+ - Scratch images (no shell)
206
+ - Some specialized images with custom entrypoints
207
+
208
+ **Debugging image issues:**
55
209
  \`\`\`bash
56
- enact run ./ --args '{"input": "test"}' # Test locally
57
- enact run ./ --args '{}' --dry-run # Preview command
58
- enact sign ./ && enact publish ./ # Publish
210
+ # Test if an image works with Enact
211
+ enact exec . "echo test" # Run simple command in tool's container
212
+ enact run ./ --verbose # See detailed container output
59
213
  \`\`\`
60
214
 
215
+ ## File Access
216
+
217
+ Tools run in a container with \`/workspace\` as the working directory. All source files are copied there.
218
+
61
219
  ## Secrets
62
- Declare in SKILL.md, set via CLI:
220
+
221
+ Declare in \`SKILL.md\`:
63
222
  \`\`\`yaml
64
223
  env:
65
- API_KEY: # Declared but not set
224
+ API_KEY:
225
+ description: "API key for service"
226
+ secret: true
66
227
  \`\`\`
228
+
229
+ Set before running:
67
230
  \`\`\`bash
68
231
  enact env set API_KEY --secret --namespace author/tool
69
232
  \`\`\`
233
+
234
+ Access in code:
235
+ \`\`\`python
236
+ import os
237
+ api_key = os.environ.get('API_KEY')
238
+ \`\`\`
239
+
240
+ ## LLM Instruction Tools
241
+
242
+ Tools without a \`command\` field are interpreted by LLMs:
243
+
244
+ \`\`\`yaml
245
+ ---
246
+ name: myorg/ai/reviewer
247
+ description: AI-powered code review
248
+ inputSchema:
249
+ type: object
250
+ properties:
251
+ code: { type: string }
252
+ required: [code]
253
+ outputSchema:
254
+ type: object
255
+ properties:
256
+ issues: { type: array }
257
+ score: { type: number }
258
+ ---
259
+ # Code Reviewer
260
+
261
+ You are a senior engineer. Review the code for bugs, style, and security.
262
+ Return JSON: {"issues": [...], "score": 75}
263
+ \`\`\`
264
+
265
+ ## Publishing Checklist
266
+
267
+ - [ ] \`name\` follows \`namespace/category/tool\` pattern
268
+ - [ ] \`version\` set (semver)
269
+ - [ ] \`description\` is clear and searchable
270
+ - [ ] \`inputSchema\` / \`outputSchema\` defined
271
+ - [ ] \`from\` uses pinned image version
272
+ - [ ] \`timeout\` set appropriately
273
+ - [ ] Tool tested locally with \`enact run ./\`
274
+
275
+ ## Troubleshooting
276
+
277
+ \`\`\`bash
278
+ enact run ./ --args '{"x": "y"}' --verbose # Verbose output
279
+ enact run ./ --args '{}' --dry-run # Preview command without running
280
+ enact run ./ --args '{}' --debug # Show parameter resolution details
281
+ enact list # List installed tools
282
+ \`\`\`
283
+
284
+ **Common issues:**
285
+
286
+ | Issue | Solution |
287
+ |-------|----------|
288
+ | "Missing required parameter" | Check your \`required\` array in inputSchema |
289
+ | Parameters not substituting | Use \`--debug\` to see what values are being passed |
290
+ | Optional params failing | Add \`default\` values or handle empty strings |
291
+ | Build step fails | Use \`--verbose\` to see build output |
292
+ | Base image not working | Use recommended images (see Base Image Requirements) |
293
+ | Command exit code 2 | Check if command exists in the container |
294
+
295
+ **Debugging build failures:**
296
+ \`\`\`bash
297
+ enact run ./ --args '{}' --verbose # See build output
298
+ enact exec . "which python" # Check if command exists
299
+ enact exec . "ls /workspace" # Check file mounts
300
+ enact validate ./ # Validate SKILL.md structure
301
+ \`\`\`
302
+
303
+ **Multi-step builds:** Use YAML array syntax for clearer error reporting:
304
+ \`\`\`yaml
305
+ build:
306
+ - apk add --no-cache ruby ruby-dev
307
+ - gem install bundler
308
+ - bundle install
309
+ \`\`\`
70
310
  `;
71
311
  //# sourceMappingURL=claude.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../../src/commands/init/templates/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkE7B,CAAC"}
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../../src/commands/init/templates/claude.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkT7B,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * AGENTS.md template for tool development
3
3
  */
4
- export declare const toolAgentsTemplate = "# Enact Tool Development Guide\n\nEnact tools are containerized, cryptographically-signed executables. Each tool is defined by a `SKILL.md` file (YAML frontmatter + Markdown docs).\n\n## Quick Reference\n\n| Task | Command |\n|------|---------|\n| Run with JSON | `enact run ./ --args '{\"key\": \"value\"}'` |\n| Run from file | `enact run ./ --input-file inputs.json` |\n| Dry run | `enact run ./ --args '{}' --dry-run` |\n| Sign & publish | `enact sign ./ && enact publish ./` |\n\n## SKILL.md Structure\n\n```yaml\n---\nname: {{TOOL_NAME}}\ndescription: What the tool does\nversion: 1.0.0\nenact: \"2.0.0\"\n\nfrom: python:3.12-slim # Docker image (pin versions, not :latest)\nbuild: pip install requests # Build steps (cached by Dagger)\ncommand: python /work/main.py ${input}\ntimeout: 30s\n\ninputSchema:\n type: object\n properties:\n input:\n type: string\n description: \"Input to process\"\n required: [input]\n\noutputSchema:\n type: object\n properties:\n result:\n type: string\n\nenv:\n API_KEY:\n description: \"External API key\"\n secret: true # Set via: enact env set API_KEY --secret\n---\n# Tool Name\nDocumentation here.\n```\n\n## Field Reference\n\n| Field | Description |\n|-------|-------------|\n| `name` | Hierarchical ID: `org/category/tool` |\n| `description` | What the tool does |\n| `version` | Semver version |\n| `from` | Docker image |\n| `build` | Build commands (string or array, cached) |\n| `command` | Shell command with `${param}` substitution |\n| `timeout` | Max execution time (e.g., \"30s\", \"5m\") |\n| `inputSchema` | JSON Schema for inputs |\n| `outputSchema` | JSON Schema for outputs |\n| `env` | Environment variables and secrets |\n\n## Parameter Substitution\n\nEnact auto-quotes parameters. **Never manually quote:**\n\n```yaml\n# WRONG - causes double-quoting\ncommand: python /work/main.py \"${input}\"\n\n# RIGHT - Enact handles quoting\ncommand: python /work/main.py ${input}\n```\n\n**Optional params:** Missing optional params become empty strings. Always provide defaults:\n```yaml\ninputSchema:\n properties:\n greeting: \n type: string\n default: \"Hello\" # Recommended for optional params\n```\n\nOr handle empty in shell:\n```yaml\ncommand: \"echo ${greeting:-Hello} ${name}\"\n```\n\nModifiers:\n- `${param}` \u2014 auto-quoted (handles spaces, JSON, special chars)\n- `${param:raw}` \u2014 raw, no quoting (use carefully)\n\n## Output\n\nOutput valid JSON to stdout when `outputSchema` is defined:\n\n```python\nimport json, sys\n\ntry:\n result = do_work()\n print(json.dumps({\"status\": \"success\", \"result\": result}))\nexcept Exception as e:\n print(json.dumps({\"status\": \"error\", \"message\": str(e)}))\n sys.exit(1) # non-zero = error\n```\n\n## Build Steps by Language\n\n**Python:**\n```yaml\nfrom: python:3.12-slim\nbuild: pip install requests pandas\n```\n\n**Node.js:**\n```yaml\nfrom: node:20-alpine\nbuild:\n - npm install\n - npm run build\n```\n\n**Rust:**\n```yaml\nfrom: rust:1.83-slim\nbuild: rustc /work/main.rs -o /work/tool\ncommand: /work/tool ${input}\n```\n\n**Go:**\n```yaml\nfrom: golang:1.22-alpine\nbuild: cd /work && go build -o tool main.go\ncommand: /work/tool ${input}\n```\n\n**System packages:**\n```yaml\nbuild: apt-get update && apt-get install -y libfoo-dev\n```\n\nBuild steps are cached \u2014 first run slow, subsequent runs instant.\n\n## File Access\n\nTools run in a container with `/work` as the working directory. All source files are copied there.\n\n## Secrets\n\nDeclare in `SKILL.md`:\n```yaml\nenv:\n API_KEY:\n description: \"API key for service\"\n secret: true\n```\n\nSet before running:\n```bash\nenact env set API_KEY --secret --namespace {{TOOL_NAME}}\n```\n\nAccess in code:\n```python\nimport os\napi_key = os.environ.get('API_KEY')\n```\n\n## LLM Instruction Tools\n\nTools without a `command` field are interpreted by LLMs:\n\n```yaml\n---\nname: myorg/ai/reviewer\ndescription: AI-powered code review\ninputSchema:\n type: object\n properties:\n code: { type: string }\n required: [code]\noutputSchema:\n type: object\n properties:\n issues: { type: array }\n score: { type: number }\n---\n# Code Reviewer\n\nYou are a senior engineer. Review the code for bugs, style, and security.\nReturn JSON: {\"issues\": [...], \"score\": 75}\n```\n\n## Publishing Checklist\n\n- [ ] `name` follows `namespace/category/tool` pattern\n- [ ] `version` set (semver)\n- [ ] `description` is clear and searchable\n- [ ] `inputSchema` / `outputSchema` defined\n- [ ] `from` uses pinned image version\n- [ ] `timeout` set appropriately\n- [ ] Tool tested locally with `enact run ./`\n\n## Troubleshooting\n\n```bash\nenact run ./ --args '{\"x\": \"y\"}' --verbose # Verbose output\nenact run ./ --args '{}' --dry-run # Preview command\nenact list # List installed tools\n```\n";
4
+ export declare const toolAgentsTemplate = "# Enact Tool Development Guide\n\nEnact tools are containerized, cryptographically-signed executables. Each tool is defined by a `SKILL.md` file (YAML frontmatter + Markdown docs).\n\n## Quick Reference\n\n| Task | Command |\n|------|---------|\n| Run with JSON | `enact run ./ --args '{\"key\": \"value\"}'` |\n| Run from file | `enact run ./ --input-file inputs.json` |\n| Dry run | `enact run ./ --args '{}' --dry-run` |\n| Debug params | `enact run ./ --args '{}' --debug` |\n| Sign & publish | `enact sign ./ && enact publish ./` |\n\n## SKILL.md Structure\n\n```yaml\n---\nname: {{TOOL_NAME}}\ndescription: What the tool does\nversion: 1.0.0\nenact: \"2.0.0\"\n\nfrom: python:3.12-slim # Docker image (pin versions, not :latest)\nbuild: pip install requests # Build steps (cached by Dagger)\ncommand: python /workspace/main.py ${input}\ntimeout: 30s\n\ninputSchema:\n type: object\n properties:\n input:\n type: string\n description: \"Input to process\"\n required: [input]\n\noutputSchema:\n type: object\n properties:\n result:\n type: string\n\nenv:\n API_KEY:\n description: \"External API key\"\n secret: true # Set via: enact env set API_KEY --secret\n---\n# Tool Name\nDocumentation here.\n```\n\n## Field Reference\n\n| Field | Description |\n|-------|-------------|\n| `name` | Hierarchical ID: `org/category/tool` |\n| `description` | What the tool does |\n| `version` | Semver version |\n| `from` | Docker image |\n| `build` | Build commands (string or array, cached) |\n| `command` | Shell command with `${param}` substitution |\n| `timeout` | Max execution time (e.g., \"30s\", \"5m\") |\n| `inputSchema` | JSON Schema for inputs |\n| `outputSchema` | JSON Schema for outputs |\n| `env` | Environment variables and secrets |\n\n## Parameter Substitution\n\nEnact auto-quotes parameters. **Never manually quote:**\n\n```yaml\n# WRONG - causes double-quoting\ncommand: python /workspace/main.py \"${input}\"\n\n# RIGHT - Enact handles quoting\ncommand: python /workspace/main.py ${input}\n```\n\n**Optional vs Required Parameters:**\n\nParameters listed in the `required` array must be provided. All other properties are optional.\n\n```yaml\ninputSchema:\n type: object\n properties:\n url: # Required (in required array)\n type: string\n user_agent: # Optional (not in required array)\n type: string\n default: \"Mozilla/5.0\" # Provide default for optional params\n timeout:\n type: number\n default: 30\n required: [url] # Only url is required\n```\n\n**Best practices for optional parameters:**\n1. Always provide a `default` value in the schema when possible\n2. Optional params without defaults become empty strings in commands\n3. Use `--debug` to see how parameters are resolved: `enact run ./ --debug`\n\nHandle optional params in shell commands:\n```yaml\ncommand: \"curl ${url} -A '${user_agent:-Mozilla/5.0}' --max-time ${timeout:-30}\"\n```\n\nModifiers:\n- `${param}` \u2014 auto-quoted (handles spaces, JSON, special chars)\n- `${param:raw}` \u2014 raw, no quoting (use carefully)\n\n## Output\n\nOutput valid JSON to stdout when `outputSchema` is defined:\n\n```python\nimport json, sys\n\ntry:\n result = do_work()\n print(json.dumps({\"status\": \"success\", \"result\": result}))\nexcept Exception as e:\n print(json.dumps({\"status\": \"error\", \"message\": str(e)}))\n sys.exit(1) # non-zero = error\n```\n\n## Build Steps by Language\n\n**Python:**\n```yaml\nfrom: python:3.12-slim\nbuild: pip install requests pandas\n```\n\n**Node.js:**\n```yaml\nfrom: node:20-alpine\nbuild:\n - npm install\n - npm run build\n```\n\n**Rust:**\n```yaml\nfrom: rust:1.83-slim\nbuild: rustc /workspace/main.rs -o /workspace/tool\ncommand: /workspace/tool ${input}\n```\n\n**Go:**\n```yaml\nfrom: golang:1.22-alpine\nbuild: cd /workspace && go build -o tool main.go\ncommand: /workspace/tool ${input}\n```\n\n**System packages:**\n```yaml\nbuild: apt-get update && apt-get install -y libfoo-dev\n```\n\nBuild steps are cached \u2014 first run slow, subsequent runs instant.\n\n## Base Image Requirements\n\nNot all Docker images work as Enact base images. Requirements:\n\n**Must have:**\n- `/bin/sh` (POSIX shell) - Enact wraps commands with `sh -c`\n- Standard filesystem layout\n\n**Recommended base images:**\n| Language | Image | Notes |\n|----------|-------|-------|\n| Python | `python:3.12-slim` | Best balance of size/features |\n| Node.js | `node:20-alpine` | Smallest, may need build tools |\n| Ruby | `ruby:3.2-slim` | For Ruby tools |\n| Go | `golang:1.22-alpine` | Compile in build step |\n| Rust | `rust:1.83-slim` | Compile in build step |\n| General | `alpine:3.18` | Minimal, use apk for packages |\n| Debian | `debian:bookworm-slim` | More packages, larger |\n\n**Images that may NOT work:**\n- Distroless images (no shell)\n- Scratch images (no shell)\n- Some specialized images with custom entrypoints\n\n**Debugging image issues:**\n```bash\n# Test if an image works with Enact\nenact exec . \"echo test\" # Run simple command in tool's container\nenact run ./ --verbose # See detailed container output\n```\n\n## File Access\n\nTools run in a container with `/workspace` as the working directory. All source files are copied there.\n\n## Secrets\n\nDeclare in `SKILL.md`:\n```yaml\nenv:\n API_KEY:\n description: \"API key for service\"\n secret: true\n```\n\nSet before running:\n```bash\nenact env set API_KEY --secret --namespace {{TOOL_NAME}}\n```\n\nAccess in code:\n```python\nimport os\napi_key = os.environ.get('API_KEY')\n```\n\n## LLM Instruction Tools\n\nTools without a `command` field are interpreted by LLMs:\n\n```yaml\n---\nname: myorg/ai/reviewer\ndescription: AI-powered code review\ninputSchema:\n type: object\n properties:\n code: { type: string }\n required: [code]\noutputSchema:\n type: object\n properties:\n issues: { type: array }\n score: { type: number }\n---\n# Code Reviewer\n\nYou are a senior engineer. Review the code for bugs, style, and security.\nReturn JSON: {\"issues\": [...], \"score\": 75}\n```\n\n## Publishing Checklist\n\n- [ ] `name` follows `namespace/category/tool` pattern\n- [ ] `version` set (semver)\n- [ ] `description` is clear and searchable\n- [ ] `inputSchema` / `outputSchema` defined\n- [ ] `from` uses pinned image version\n- [ ] `timeout` set appropriately\n- [ ] Tool tested locally with `enact run ./`\n\n## Troubleshooting\n\n```bash\nenact run ./ --args '{\"x\": \"y\"}' --verbose # Verbose output\nenact run ./ --args '{}' --dry-run # Preview command without running\nenact run ./ --args '{}' --debug # Show parameter resolution details\nenact list # List installed tools\n```\n\n**Common issues:**\n\n| Issue | Solution |\n|-------|----------|\n| \"Missing required parameter\" | Check your `required` array in inputSchema |\n| Parameters not substituting | Use `--debug` to see what values are being passed |\n| Optional params failing | Add `default` values or handle empty strings |\n| Build step fails | Use `--verbose` to see build output |\n| Base image not working | Use recommended images (see Base Image Requirements) |\n| Command exit code 2 | Check if command exists in the container |\n\n**Debugging build failures:**\n```bash\nenact run ./ --args '{}' --verbose # See build output\nenact exec . \"which python\" # Check if command exists\nenact exec . \"ls /workspace\" # Check file mounts\nenact validate ./ # Validate SKILL.md structure\n```\n\n**Multi-step builds:** Use YAML array syntax for clearer error reporting:\n```yaml\nbuild:\n - apk add --no-cache ruby ruby-dev\n - gem install bundler\n - bundle install\n```\n";
5
5
  //# sourceMappingURL=tool-agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-agents.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/templates/tool-agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,kBAAkB,22JAsN9B,CAAC"}
1
+ {"version":3,"file":"tool-agents.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/templates/tool-agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,kBAAkB,wsPAiS9B,CAAC"}
@@ -12,6 +12,7 @@ Enact tools are containerized, cryptographically-signed executables. Each tool i
12
12
  | Run with JSON | \`enact run ./ --args '{"key": "value"}'\` |
13
13
  | Run from file | \`enact run ./ --input-file inputs.json\` |
14
14
  | Dry run | \`enact run ./ --args '{}' --dry-run\` |
15
+ | Debug params | \`enact run ./ --args '{}' --debug\` |
15
16
  | Sign & publish | \`enact sign ./ && enact publish ./\` |
16
17
 
17
18
  ## SKILL.md Structure
@@ -25,7 +26,7 @@ enact: "2.0.0"
25
26
 
26
27
  from: python:3.12-slim # Docker image (pin versions, not :latest)
27
28
  build: pip install requests # Build steps (cached by Dagger)
28
- command: python /work/main.py \${input}
29
+ command: python /workspace/main.py \${input}
29
30
  timeout: 30s
30
31
 
31
32
  inputSchema:
@@ -72,24 +73,39 @@ Enact auto-quotes parameters. **Never manually quote:**
72
73
 
73
74
  \`\`\`yaml
74
75
  # WRONG - causes double-quoting
75
- command: python /work/main.py "\${input}"
76
+ command: python /workspace/main.py "\${input}"
76
77
 
77
78
  # RIGHT - Enact handles quoting
78
- command: python /work/main.py \${input}
79
+ command: python /workspace/main.py \${input}
79
80
  \`\`\`
80
81
 
81
- **Optional params:** Missing optional params become empty strings. Always provide defaults:
82
+ **Optional vs Required Parameters:**
83
+
84
+ Parameters listed in the \`required\` array must be provided. All other properties are optional.
85
+
82
86
  \`\`\`yaml
83
87
  inputSchema:
88
+ type: object
84
89
  properties:
85
- greeting:
90
+ url: # Required (in required array)
86
91
  type: string
87
- default: "Hello" # Recommended for optional params
92
+ user_agent: # Optional (not in required array)
93
+ type: string
94
+ default: "Mozilla/5.0" # Provide default for optional params
95
+ timeout:
96
+ type: number
97
+ default: 30
98
+ required: [url] # Only url is required
88
99
  \`\`\`
89
100
 
90
- Or handle empty in shell:
101
+ **Best practices for optional parameters:**
102
+ 1. Always provide a \`default\` value in the schema when possible
103
+ 2. Optional params without defaults become empty strings in commands
104
+ 3. Use \`--debug\` to see how parameters are resolved: \`enact run ./ --debug\`
105
+
106
+ Handle optional params in shell commands:
91
107
  \`\`\`yaml
92
- command: "echo \${greeting:-Hello} \${name}"
108
+ command: "curl \${url} -A '\${user_agent:-Mozilla/5.0}' --max-time \${timeout:-30}"
93
109
  \`\`\`
94
110
 
95
111
  Modifiers:
@@ -130,15 +146,15 @@ build:
130
146
  **Rust:**
131
147
  \`\`\`yaml
132
148
  from: rust:1.83-slim
133
- build: rustc /work/main.rs -o /work/tool
134
- command: /work/tool \${input}
149
+ build: rustc /workspace/main.rs -o /workspace/tool
150
+ command: /workspace/tool \${input}
135
151
  \`\`\`
136
152
 
137
153
  **Go:**
138
154
  \`\`\`yaml
139
155
  from: golang:1.22-alpine
140
- build: cd /work && go build -o tool main.go
141
- command: /work/tool \${input}
156
+ build: cd /workspace && go build -o tool main.go
157
+ command: /workspace/tool \${input}
142
158
  \`\`\`
143
159
 
144
160
  **System packages:**
@@ -148,9 +164,40 @@ build: apt-get update && apt-get install -y libfoo-dev
148
164
 
149
165
  Build steps are cached — first run slow, subsequent runs instant.
150
166
 
167
+ ## Base Image Requirements
168
+
169
+ Not all Docker images work as Enact base images. Requirements:
170
+
171
+ **Must have:**
172
+ - \`/bin/sh\` (POSIX shell) - Enact wraps commands with \`sh -c\`
173
+ - Standard filesystem layout
174
+
175
+ **Recommended base images:**
176
+ | Language | Image | Notes |
177
+ |----------|-------|-------|
178
+ | Python | \`python:3.12-slim\` | Best balance of size/features |
179
+ | Node.js | \`node:20-alpine\` | Smallest, may need build tools |
180
+ | Ruby | \`ruby:3.2-slim\` | For Ruby tools |
181
+ | Go | \`golang:1.22-alpine\` | Compile in build step |
182
+ | Rust | \`rust:1.83-slim\` | Compile in build step |
183
+ | General | \`alpine:3.18\` | Minimal, use apk for packages |
184
+ | Debian | \`debian:bookworm-slim\` | More packages, larger |
185
+
186
+ **Images that may NOT work:**
187
+ - Distroless images (no shell)
188
+ - Scratch images (no shell)
189
+ - Some specialized images with custom entrypoints
190
+
191
+ **Debugging image issues:**
192
+ \`\`\`bash
193
+ # Test if an image works with Enact
194
+ enact exec . "echo test" # Run simple command in tool's container
195
+ enact run ./ --verbose # See detailed container output
196
+ \`\`\`
197
+
151
198
  ## File Access
152
199
 
153
- Tools run in a container with \`/work\` as the working directory. All source files are copied there.
200
+ Tools run in a container with \`/workspace\` as the working directory. All source files are copied there.
154
201
 
155
202
  ## Secrets
156
203
 
@@ -212,8 +259,36 @@ Return JSON: {"issues": [...], "score": 75}
212
259
 
213
260
  \`\`\`bash
214
261
  enact run ./ --args '{"x": "y"}' --verbose # Verbose output
215
- enact run ./ --args '{}' --dry-run # Preview command
216
- enact list # List installed tools
262
+ enact run ./ --args '{}' --dry-run # Preview command without running
263
+ enact run ./ --args '{}' --debug # Show parameter resolution details
264
+ enact list # List installed tools
265
+ \`\`\`
266
+
267
+ **Common issues:**
268
+
269
+ | Issue | Solution |
270
+ |-------|----------|
271
+ | "Missing required parameter" | Check your \`required\` array in inputSchema |
272
+ | Parameters not substituting | Use \`--debug\` to see what values are being passed |
273
+ | Optional params failing | Add \`default\` values or handle empty strings |
274
+ | Build step fails | Use \`--verbose\` to see build output |
275
+ | Base image not working | Use recommended images (see Base Image Requirements) |
276
+ | Command exit code 2 | Check if command exists in the container |
277
+
278
+ **Debugging build failures:**
279
+ \`\`\`bash
280
+ enact run ./ --args '{}' --verbose # See build output
281
+ enact exec . "which python" # Check if command exists
282
+ enact exec . "ls /workspace" # Check file mounts
283
+ enact validate ./ # Validate SKILL.md structure
284
+ \`\`\`
285
+
286
+ **Multi-step builds:** Use YAML array syntax for clearer error reporting:
287
+ \`\`\`yaml
288
+ build:
289
+ - apk add --no-cache ruby ruby-dev
290
+ - gem install bundler
291
+ - bundle install
217
292
  \`\`\`
218
293
  `;
219
294
  //# sourceMappingURL=tool-agents.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-agents.js","sourceRoot":"","sources":["../../../../src/commands/init/templates/tool-agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsNjC,CAAC"}
1
+ {"version":3,"file":"tool-agents.js","sourceRoot":"","sources":["../../../../src/commands/init/templates/tool-agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiSjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/install/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4BH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAonBzC;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyB9D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/install/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6BH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8nBzC;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyB9D"}