Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.
Hooks let you run shell scripts before and after individual requests. Use @before for setup (seeding data, starting services) and @after for cleanup (removing test data, stopping services).
Security
Hooks execute shell scripts on your system. You must pass the --allow-shell flag to enable them. Without this flag, @before and @after hooks are skipped.
hitspec run tests/ --allow-shell
Basic Usage
### Test with setup and teardown# @name testWithHooks# @before ./scripts/setup.sh# @after ./scripts/cleanup.shGET {{baseUrl}}/api/test>>>expect status 200<<<
@before Hooks
@before hooks run before the HTTP request is sent. Use them to prepare test data, start services, or set up preconditions.
### Test user creation# @name testCreateUser# @before ./scripts/seed-db.sh# @before ./scripts/clear-cache.shPOST {{baseUrl}}/api/usersContent-Type: application/json{ "name": "Test User"}>>>expect status 201<<<
Multiple @before hooks execute in the order they are declared.
@after Hooks
@after hooks run after the request completes and assertions are evaluated. They always run, even if the request or assertions fail. This makes them reliable for cleanup.
### Test that requires cleanup# @name testWithCleanup# @after ./scripts/remove-test-data.sh# @after ./scripts/reset-state.shDELETE {{baseUrl}}/api/test-resources/123>>>expect status 204<<<
Multiple @after hooks also execute in declaration order.
@after hooks always run, even when the request fails or assertions do not pass. This guarantees cleanup happens regardless of test outcome.
Variable Resolution
Variables are resolved in hook paths and commands:
sh -c (on Windows, sh from Git for Windows when it is installed, otherwise cmd /C)
Working directory
Location of the .http file
Multiple hooks
Executed in declaration order
@before failure
Request is not sent; @after hooks still run
@after timing
Always runs, even on request failure
Variable support
{{variables}} are resolved before execution
Example: Database Seed and Cleanup
### Verify user list after seeding# @name verifyUsers# @before ./scripts/seed-users.sh# @after ./scripts/truncate-users.shGET {{baseUrl}}/api/users>>>expect status 200expect body type arrayexpect body length > 0<<<
### Wait for service and test# @name serviceTest# @before ./scripts/start-service.sh# @after ./scripts/stop-service.shGET http://localhost:8080/api/health>>>expect status 200expect body.status == "ok"<<<
For simple command execution after a request (without needing a separate script file), consider using shell command blocks with the >>>shell syntax instead.
Last modified on October 19, 2026
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"hitspec","description":"hitspec is a file-based HTTP API testing tool. Write API tests as plain-text .http files, run them with 26 assertion operators, capture and chain requests, stress-test, mock, and verify database state — no SDK, no GUI, no JavaScript.","colors":{"primary":"#88C0D0","light":"#8FBCBB","dark":"#5E81AC"},"logo":{"light":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/light.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=b041ab9cc5b38b53110611b1c3e3435d","dark":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/dark.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=d9a717f6f6d804685a15907aa0d1f27e"},"favicon":"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/favicon.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=1f9aa7e4e0e34f5f9afb23c4165d8673","navbar":{"links":[{"href":"https://github.com/abdul-hamid-achik/hitspec","label":"GitHub"},{"href":"https://github.com/abdul-hamid-achik/hitspec/blob/main/CHANGELOG.md","label":"Changelog"}],"primary":{"type":"button","label":"Install","href":"/installation"}},"footer":{"socials":{"github":"https://github.com/abdul-hamid-achik/hitspec"}},"search":{"prompt":"Search the docs, syntax, and CLI…"},"seo":{"metatags":{"og:site_name":"hitspec","og:type":"website","og:locale":"en_US","twitter:card":"summary_large_image","theme-color":"#88C0D0","canonical":"https://hitspec.dev","robots":"index, follow","revisit-after":"7 days","language":"en"},"indexing":"navigable"},"metadata":{"timestamp":true},"styling":{"latex":false},"navigation":{"global":{"tabs":[{"tab":"Documentation","href":"/introduction"},{"tab":"Guides","href":"/guides"},{"tab":"Reference","href":"/reference"},{"tab":"Examples","href":"/examples"}],"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/abdul-hamid-achik/hitspec"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"fuego-45a05047","hasAudioNarration":false,"actualSubdomain":"fuego-45a05047","customDomains":["hitspec.dev"],"gitSource":{"type":"github","owner":"abdul-hamid-achik","repo":"hitspec","deployBranch":"main","contentDirectory":"apps/docs","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6ad6611a7c2363fd57cca63a","clientVersion":"0.0.4143","searchFilterCounts":[{"language":"default","tag":"Features","count":17},{"language":"default","tag":"CLI Reference","count":13},{"language":"default","tag":"Guides","count":9},{"language":"default","tag":"Examples","count":8},{"language":"default","tag":"Core Concepts","count":7},{"language":"default","tag":"Getting Started","count":6},{"language":"default","tag":"Integrations","count":6},{"language":"default","tag":"Assertions Reference","count":2},{"language":"default","tag":"Configuration","count":2},{"language":"default","tag":"Authentication","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"landing.css","content":".hs-hero{position:relative;overflow:hidden;padding:6rem 1.5rem 4rem;background:radial-gradient(1200px 600px at 50% -10%, rgba(136, 192, 208, 0.18), transparent 60%),\n radial-gradient(800px 500px at 85% 10%, rgba(94, 129, 172, 0.16), transparent 55%),\n radial-gradient(700px 500px at 10% 20%, rgba(143, 188, 187, 0.14), transparent 55%)}@media (prefers-color-scheme: dark){.hs-hero{background:radial-gradient(1200px 600px at 50% -10%, rgba(136, 192, 208, 0.16), transparent 60%),\n radial-gradient(800px 500px at 85% 10%, rgba(94, 129, 172, 0.22), transparent 55%),\n radial-gradient(700px 500px at 10% 20%, rgba(143, 188, 187, 0.10), transparent 55%)}}.hs-hero::before{content:\"\";position:absolute;inset:0;background-image:linear-gradient(to right, rgba(136, 192, 208, 0.06) 1px, transparent 1px),\n linear-gradient(to bottom, rgba(136, 192, 208, 0.06) 1px, transparent 1px);background-size:48px 48px;mask-image:radial-gradient(ellipse 80% 60% at 50% 30%, black 40%, transparent 80%);-webkit-mask-image:radial-gradient(ellipse 80% 60% at 50% 30%, black 40%, transparent 80%);pointer-events:none}.hs-hero-inner{position:relative;max-width:72rem;margin:0 auto}.hs-badge{display:inline-flex;align-items:center;gap:0.5rem;padding:0.3rem 0.9rem;border-radius:999px;font-size:0.8rem;font-weight:500;letter-spacing:0.01em;color:#2e3440;background:rgba(136, 192, 208, 0.16);border:1px solid rgba(136, 192, 208, 0.35);backdrop-filter:blur(6px)}@media (prefers-color-scheme: dark){.hs-badge{color:#e5e9f0;background:rgba(136, 192, 208, 0.10);border:1px solid rgba(136, 192, 208, 0.25)}}.hs-badge-dot{width:0.5rem;height:0.5rem;border-radius:999px;background:#88c0d0;box-shadow:0 0 0 0 rgba(136, 192, 208, 0.7);animation:hs-pulse 2s infinite}@keyframes hs-pulse{0%{box-shadow:0 0 0 0 rgba(136, 192, 208, 0.6)}70%{box-shadow:0 0 0 8px rgba(136, 192, 208, 0)}100%{box-shadow:0 0 0 0 rgba(136, 192, 208, 0)}}.hs-headline{font-size:clamp(2.5rem, 6vw, 4.75rem);line-height:1.05;font-weight:700;letter-spacing:-0.02em;margin:1.25rem 0 0}.hs-gradient-text{background:linear-gradient(110deg, #5e81ac 0%, #88c0d0 45%, #8fbcbb 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}.hs-subhead{font-size:clamp(1.05rem, 2.2vw, 1.35rem);line-height:1.6;max-width:42rem;margin:1.5rem 0 0;color:#4c566a}@media (prefers-color-scheme: dark){.hs-subhead{color:#aeb6c6}}.hs-cta-row{display:flex;flex-wrap:wrap;gap:0.75rem;margin-top:2rem;align-items:center}.hs-btn{display:inline-flex;align-items:center;gap:0.5rem;padding:0.7rem 1.4rem;border-radius:0.75rem;font-weight:600;font-size:0.95rem;text-decoration:none;transition:transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease}.hs-btn-primary{color:#1b1f2a;background:linear-gradient(135deg, #88c0d0 0%, #8fbcbb 100%);box-shadow:0 10px 30px -10px rgba(136, 192, 208, 0.65)}.hs-btn-primary:hover{transform:translateY(-2px);box-shadow:0 16px 38px -12px rgba(136, 192, 208, 0.8)}@media (prefers-color-scheme: dark){.hs-btn-primary{color:#0d1117;background:linear-gradient(135deg, #88c0d0 0%, #a3d3df 100%)}}.hs-btn-ghost{color:#2e3440;background:rgba(46, 52, 64, 0.04);border:1px solid rgba(46, 52, 64, 0.18)}.hs-btn-ghost:hover{transform:translateY(-2px);background:rgba(46, 52, 64, 0.08)}@media (prefers-color-scheme: dark){.hs-btn-ghost{color:#e5e9f0;background:rgba(229, 233, 240, 0.04);border:1px solid rgba(229, 233, 240, 0.18)}.hs-btn-ghost:hover{background:rgba(229, 233, 240, 0.08)}}.hs-install-chip{display:inline-flex;align-items:center;gap:0.6rem;margin-top:1.5rem;padding:0.6rem 1rem;border-radius:0.6rem;font-family:ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;font-size:0.9rem;color:#2e3440;background:rgba(46, 52, 64, 0.05);border:1px solid rgba(46, 52, 64, 0.12)}@media (prefers-color-scheme: dark){.hs-install-chip{color:#d8dee9;background:rgba(216, 222, 233, 0.05);border:1px solid rgba(216, 222, 233, 0.12)}}.hs-install-chip code{background:transparent;border:none;padding:0;font-size:inherit}.hs-window{margin-top:2.5rem;border-radius:0.9rem;overflow:hidden;border:1px solid rgba(46, 52, 64, 0.14);background:#f6f8fa;box-shadow:0 24px 60px -28px rgba(46, 52, 64, 0.45)}@media (prefers-color-scheme: dark){.hs-window{border-color:rgba(216, 222, 233, 0.12);background:#161a23;box-shadow:0 24px 60px -28px rgba(0, 0, 0, 0.7)}}.hs-window-bar{display:flex;align-items:center;gap:0.45rem;padding:0.65rem 0.9rem;border-bottom:1px solid rgba(46, 52, 64, 0.10);background:rgba(46, 52, 64, 0.03)}@media (prefers-color-scheme: dark){.hs-window-bar{border-bottom-color:rgba(216, 222, 233, 0.10);background:rgba(216, 222, 233, 0.03)}}.hs-dot{width:0.75rem;height:0.75rem;border-radius:999px}.hs-dot-r{background:#ff5f57}.hs-dot-y{background:#febc2e}.hs-dot-g{background:#28c840}.hs-window-title{margin-left:0.5rem;font-size:0.78rem;color:#6b7280;font-family:ui-monospace, SFMono-Regular, Menlo, monospace}@media (prefers-color-scheme: dark){.hs-window-title{color:#8b93a7}}.hs-window pre{margin:0;padding:1.1rem 1.25rem;overflow-x:auto;font-family:ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace;font-size:0.86rem;line-height:1.7;background:transparent!important}.hs-stats{display:grid;grid-template-columns:repeat(2, 1fr);gap:1rem;max-width:72rem;margin:0 auto;padding:0 1.5rem 3rem}@media (min-width: 768px){.hs-stats{grid-template-columns:repeat(4, 1fr)}}.hs-stat{text-align:center;padding:1.25rem 0.5rem;border-radius:0.85rem;border:1px solid rgba(46, 52, 64, 0.10);background:rgba(136, 192, 208, 0.05)}@media (prefers-color-scheme: dark){.hs-stat{border-color:rgba(216, 222, 233, 0.10);background:rgba(136, 192, 208, 0.05)}}.hs-stat-num{font-size:1.9rem;font-weight:700;line-height:1}.hs-stat-label{margin-top:0.4rem;font-size:0.82rem;color:#6b7280}@media (prefers-color-scheme: dark){.hs-stat-label{color:#8b93a7}}.hs-section{max-width:72rem;margin:0 auto;padding:3rem 1.5rem}.hs-eyebrow{text-transform:uppercase;letter-spacing:0.12em;font-size:0.78rem;font-weight:600;color:#5e81ac}.hs-h2{font-size:clamp(1.75rem, 3.5vw, 2.5rem);font-weight:700;letter-spacing:-0.015em;margin:0.5rem 0 0.5rem}.hs-lead{max-width:40rem;color:#4c566a;font-size:1.05rem;line-height:1.6}@media (prefers-color-scheme: dark){.hs-lead{color:#aeb6c6}}.hs-grid{display:grid;gap:1rem;grid-template-columns:1fr}@media (min-width: 640px){.hs-grid{grid-template-columns:repeat(2, 1fr)}}@media (min-width: 1024px){.hs-grid{grid-template-columns:repeat(3, 1fr)}}.hs-feature{display:block;padding:1.4rem;border-radius:0.9rem;border:1px solid rgba(46, 52, 64, 0.10);background:rgba(255, 255, 255, 0.6);text-decoration:none;transition:transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;backdrop-filter:blur(4px)}.hs-feature:hover{transform:translateY(-3px);border-color:rgba(136, 192, 208, 0.55);box-shadow:0 18px 40px -22px rgba(94, 129, 172, 0.45)}@media (prefers-color-scheme: dark){.hs-feature{border-color:rgba(216, 222, 233, 0.10);background:rgba(229, 233, 240, 0.03)}.hs-feature:hover{border-color:rgba(136, 192, 208, 0.55)}}.hs-feature-ico{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:0.7rem;font-size:1.1rem;background:linear-gradient(135deg, rgba(136, 192, 208, 0.25), rgba(94, 129, 172, 0.18));margin-bottom:0.85rem}.hs-feature-title{font-weight:600;font-size:1.02rem;color:#2e3440;margin:0}@media (prefers-color-scheme: dark){.hs-feature-title{color:#e5e9f0}}.hs-feature-desc{margin-top:0.4rem;font-size:0.9rem;line-height:1.55;color:#6b7280}@media (prefers-color-scheme: dark){.hs-feature-desc{color:#9ba3b3}}.hs-compare{width:100%;border-collapse:separate;border-spacing:0;font-size:0.92rem}.hs-compare th,.hs-compare td{padding:0.7rem 0.9rem;text-align:left;border-bottom:1px solid rgba(46, 52, 64, 0.08)}@media (prefers-color-scheme: dark){.hs-compare th,.hs-compare td{border-bottom-color:rgba(216, 222, 233, 0.08)}}.hs-compare th{font-weight:600;color:#2e3440;background:rgba(136, 192, 208, 0.06)}@media (prefers-color-scheme: dark){.hs-compare th{color:#e5e9f0}}.hs-compare tr:last-child td{border-bottom:none}.hs-yes{color:#28a745;font-weight:600}.hs-no{color:#9ba3b3}.hs-band{position:relative;overflow:hidden;padding:3.5rem 1.5rem;border-radius:1.25rem;max-width:72rem;margin:2rem auto;background:linear-gradient(135deg, rgba(94, 129, 172, 0.10), rgba(136, 192, 208, 0.08)),\n rgba(255, 255, 255, 0.5);border:1px solid rgba(136, 192, 208, 0.25)}@media (prefers-color-scheme: dark){.hs-band{background:linear-gradient(135deg, rgba(94, 129, 172, 0.16), rgba(136, 192, 208, 0.06)),\n rgba(229, 233, 240, 0.03);border-color:rgba(136, 192, 208, 0.20)}}.hs-final{position:relative;overflow:hidden;text-align:center;padding:5rem 1.5rem;max-width:72rem;margin:2rem auto 4rem;border-radius:1.5rem;background:radial-gradient(600px 300px at 50% 0%, rgba(136, 192, 208, 0.30), transparent 70%),\n linear-gradient(135deg, #5e81ac 0%, #88c0d0 100%);color:#fff}@media (prefers-color-scheme: dark){.hs-final{background:radial-gradient(600px 300px at 50% 0%, rgba(136, 192, 208, 0.35), transparent 70%),\n linear-gradient(135deg, #4c5e87 0%, #7fb3c4 100%);color:#0d1117}}.hs-final h2{font-size:clamp(1.8rem, 4vw, 2.75rem);font-weight:700;letter-spacing:-0.015em;margin:0}.hs-final p{margin:1rem auto 0;max-width:36rem;font-size:1.08rem;opacity:0.95}.hs-final .hs-btn-primary{background:#fff;color:#1b1f2a;box-shadow:0 12px 34px -12px rgba(0, 0, 0, 0.45)}.hs-final .hs-btn-primary:hover{background:#f6f8fa}.hs-faq{max-width:48rem;margin:0 auto;padding:1rem 1.5rem 3rem}body:has(.hs-hero) #page-title{display:none}"}],"page":{"pagePath":"features/hooks","slug":"/features/hooks","pageMetadata":{"title":"Hooks","description":"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.","href":"/features/hooks"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,p:`p`,pre:`pre`,span:`span`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Table,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Hooks let you run shell scripts before and after individual requests. Use `,_jsx(_components.code,{children:`@before`}),` for setup (seeding data, starting services) and `,_jsx(_components.code,{children:`@after`}),` for cleanup (removing test data, stopping services).`]}),`\n`,_jsx(Heading,{level:`2`,id:`security`,children:`Security`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Hooks execute shell scripts on your system. You must pass the `,_jsx(_components.code,{children:`--allow-shell`}),` flag to enable them. Without this flag, `,_jsx(_components.code,{children:`@before`}),` and `,_jsx(_components.code,{children:`@after`}),` hooks are skipped.`]})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`hitspec`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` tests/`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --allow-shell`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`basic-usage`,children:`Basic Usage`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`10`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Test with setup and teardown`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` testWithHooks`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/setup.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/cleanup.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/test`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`@before-hooks`,children:`@before Hooks`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`@before`}),` hooks run before the HTTP request is sent. Use them to prepare test data, start services, or set up preconditions.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`15`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Test user creation`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` testCreateUser`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/seed-db.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/clear-cache.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`POST`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/users`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`Content-Type`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` application/json`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"name\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Test User\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`201`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Multiple `,_jsx(_components.code,{children:`@before`}),` hooks execute in the order they are declared.`]}),`\n`,_jsx(Heading,{level:`2`,id:`@after-hooks`,children:`@after Hooks`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`@after`}),` hooks run after the request completes and assertions are evaluated. They always run, even if the request or assertions fail. This makes them reliable for cleanup.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`10`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Test that requires cleanup`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` testWithCleanup`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/remove-test-data.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/reset-state.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`DELETE`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/test-resources/123`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 204`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Multiple `,_jsx(_components.code,{children:`@after`}),` hooks also execute in declaration order.`]}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.code,{children:`@after`}),` hooks always run, even when the request fails or assertions do not pass. This guarantees cleanup happens regardless of test outcome.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`variable-resolution`,children:`Variable Resolution`}),`\n`,_jsx(_components.p,{children:`Variables are resolved in hook paths and commands:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`10`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`10`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Dynamic hook paths`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` envSpecificTest`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/setup-{{env}}.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/cleanup-{{env}}.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/health`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`execution-details`,children:`Execution Details`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Behavior`}),_jsx(_components.th,{children:`Detail`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Execution engine`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`sh -c`}),` (on Windows, `,_jsx(_components.code,{children:`sh`}),` from Git for Windows when it is installed, otherwise `,_jsx(_components.code,{children:`cmd /C`}),`)`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Working directory`}),_jsxs(_components.td,{children:[`Location of the `,_jsx(_components.code,{children:`.http`}),` file`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Multiple hooks`}),_jsx(_components.td,{children:`Executed in declaration order`})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`@before`}),` failure`]}),_jsxs(_components.td,{children:[`Request is not sent; `,_jsx(_components.code,{children:`@after`}),` hooks still run`]})]}),_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`@after`}),` timing`]}),_jsx(_components.td,{children:`Always runs, even on request failure`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Variable support`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`{{variables}}`}),` are resolved before execution`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`example-database-seed-and-cleanup`,children:`Example: Database Seed and Cleanup`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`12`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`12`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Verify user list after seeding`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` verifyUsers`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/seed-users.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/truncate-users.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {{baseUrl}}/api/users`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect body type array`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect body length > 0`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`scripts/seed-users.sh`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`#!/bin/bash`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`psql`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` $DATABASE_URL`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"INSERT INTO users (name, email) VALUES ('Test', 'test@example.com');\"`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`scripts/truncate-users.sh`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`#!/bin/bash`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`psql`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` $DATABASE_URL`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -c`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"TRUNCATE TABLE users CASCADE;\"`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`example-service-health-check`,children:`Example: Service Health Check`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`11`,language:`http`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`http`,children:_jsxs(_components.code,{language:`http`,numberOfLines:`11`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`### Wait for service and test`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`@name`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` serviceTest`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @before ./scripts/start-service.sh`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`# @after ./scripts/stop-service.sh`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`GET`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` http://localhost:8080/api/health`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`>>>`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect status 200`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`expect body.status == \"ok\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`\u003c\u003c\u003c`})}),`\n`]})})}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`For simple command execution after a request (without needing a separate script file), consider using `,_jsx(_components.a,{href:`/features/shell-commands`,children:`shell command blocks`}),` with the `,_jsx(_components.code,{children:`>>>shell`}),` syntax instead.`]})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Hooks","description":"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.","href":"/features/hooks"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Security","slug":"security","depth":2,"children":[]},{"title":"Basic Usage","slug":"basic-usage","depth":2,"children":[]},{"title":"@before Hooks","slug":"@before-hooks","depth":2,"children":[]},{"title":"@after Hooks","slug":"@after-hooks","depth":2,"children":[]},{"title":"Variable Resolution","slug":"variable-resolution","depth":2,"children":[]},{"title":"Execution Details","slug":"execution-details","depth":2,"children":[]},{"title":"Example: Database Seed and Cleanup","slug":"example-database-seed-and-cleanup","depth":2,"children":[]},{"title":"Example: Service Health Check","slug":"example-service-health-check","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"fuego-45a05047","siteName":"hitspec","title":"Hooks - hitspec","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-19T13:52:01.792Z","gitLastModified":"2026-10-19T13:51:44.000Z","originalFileLocation":"features/hooks.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\">\u003cmeta data-mint-head name=\"application-name\" content=\"hitspec\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"index, follow\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Hooks - hitspec\">\u003cmeta data-mint-head property=\"og:description\" content=\"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"hitspec\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://hitspec.dev/features/hooks\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://fuego-45a05047.mintlify.site/_mintlify/api/og/v2?division=Features\u0026amp;title=Hooks\u0026amp;description=Run+setup+and+teardown+scripts+before+and+after+HTTP+requests+using+%40before+and+%40after+annotations.\u0026amp;theme=93275042a6aa6480dea6ccca\u0026amp;signature=f5d2d0f3de9d09e1c487d302216ca39ea26e804f3355443ca260b846ea8b30e4\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Hooks - hitspec\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://fuego-45a05047.mintlify.site/_mintlify/api/og/v2?division=Features\u0026amp;title=Hooks\u0026amp;description=Run+setup+and+teardown+scripts+before+and+after+HTTP+requests+using+%40before+and+%40after+annotations.\u0026amp;theme=93275042a6aa6480dea6ccca\u0026amp;signature=f5d2d0f3de9d09e1c487d302216ca39ea26e804f3355443ca260b846ea8b30e4\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/fuego-45a05047/7VaIAxtBvFB9MH3u/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"hitspec\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#88C0D0\">\u003cmeta data-mint-head name=\"og:locale\" content=\"en_US\">\u003cmeta data-mint-head name=\"theme-color\" content=\"#88C0D0\">\u003cmeta data-mint-head name=\"revisit-after\" content=\"7 days\">\u003cmeta data-mint-head name=\"language\" content=\"en\">\u003clink data-mint-head rel=\"canonical\" href=\"https://hitspec.dev/features/hooks\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/features/hooks.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://hitspec.dev/#organization\",\"name\":\"hitspec\",\"url\":\"https://hitspec.dev\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/fuego-45a05047/A4gbvCUx3th6_k6y/logo/light.svg?fit=max\u0026auto=format\u0026n=A4gbvCUx3th6_k6y\u0026q=85\u0026s=b041ab9cc5b38b53110611b1c3e3435d\"}},{\"@type\":\"WebSite\",\"@id\":\"https://hitspec.dev#website\",\"name\":\"hitspec\",\"url\":\"https://hitspec.dev\",\"publisher\":{\"@id\":\"https://hitspec.dev/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://hitspec.dev/features/hooks#webpage\",\"url\":\"https://hitspec.dev/features/hooks\",\"name\":\"Hooks\",\"description\":\"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\",\"dateModified\":\"2026-10-19T13:51:44.000Z\",\"isPartOf\":{\"@id\":\"https://hitspec.dev#website\"},\"breadcrumb\":{\"@id\":\"https://hitspec.dev/features/hooks#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://hitspec.dev/features/hooks#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Features\",\"item\":\"https://hitspec.dev/features/authentication\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Hooks\",\"item\":\"https://hitspec.dev/features/hooks\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://hitspec.dev/features/hooks#article\",\"headline\":\"Hooks\",\"name\":\"Hooks\",\"description\":\"Run setup and teardown scripts before and after HTTP requests using @before and @after annotations.\",\"url\":\"https://hitspec.dev/features/hooks\",\"mainEntityOfPage\":{\"@id\":\"https://hitspec.dev/features/hooks#webpage\"},\"dateModified\":\"2026-10-19T13:51:44.000Z\",\"publisher\":{\"@id\":\"https://hitspec.dev/#organization\"},\"isPartOf\":{\"@id\":\"https://hitspec.dev#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"hitspec\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"hitspec\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/features/hooks.md","siteName":"hitspec","nav":{"global":{"tabs":[{"tab":"Documentation","href":"/introduction"},{"tab":"Guides","href":"/guides"},{"tab":"Reference","href":"/reference"},{"tab":"Examples","href":"/examples"}],"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/abdul-hamid-achik/hitspec"}]},"groups":[{"group":"Getting Started","pages":[{"title":"hitspec — Plain text API tests. No magic.","mode":"custom","href":"/introduction"},{"title":"Install hitspec — Homebrew, Go, and binary","href":"/installation"},{"title":"Write and run your first API test in under a minute","href":"/quickstart"},{"title":"hitspec studio — a keyboard-first terminal API client","href":"/studio"},{"title":"hitspec Studio desktop — a native GUI for .http files","href":"/desktop"},{"title":"Editor Setup","href":"/editor-setup"}]},{"group":"Core Concepts","pages":[{"title":"The .http file format for API tests","href":"/concepts/file-format"},{"title":"Variables","href":"/concepts/variables"},{"title":"Variable Interpolation","href":"/concepts/variable-interpolation"},{"title":"Assertions","href":"/concepts/assertions"},{"title":"Captures","href":"/concepts/captures"},{"title":"Dependencies","href":"/concepts/dependencies"},{"title":"Environments","href":"/concepts/environments"}]},{"group":"Features","pages":[{"title":"Authentication for API tests (@auth)","href":"/features/authentication"},{"title":"Multipart and GraphQL","href":"/features/multipart-graphql"},{"title":"TLS, cookies and HTTP options","href":"/features/tls-and-cookies"},{"title":"Snapshot testing for API responses","href":"/features/snapshot-testing"},{"title":"Load and stress test APIs with hitspec","href":"/features/stress-testing"},{"title":"Database assertions after HTTP requests","href":"/features/database-assertions"},{"title":"Shell Commands","description":"Run shell commands after HTTP requests for post-processing, notifications, and custom validation.","href":"/features/shell-commands"},{"title":"Hooks","href":"/features/hooks"},{"title":"Server-Sent Events (SSE)","description":"Test Server-Sent Events endpoints with hitspec.","href":"/features/sse"},{"title":"API Coverage","href":"/features/api-coverage"},{"title":"Mock server from .http files","href":"/features/mock-server"},{"title":"Contract Testing","href":"/features/contract-testing"},{"title":"Recording Proxy","href":"/features/recording-proxy"},{"title":"Watch Mode","href":"/features/watch-mode"},{"title":"Parallel Execution","href":"/features/parallel-execution"},{"title":"Notifications","href":"/features/notifications"},{"title":"Metrics Export","href":"/features/metrics-export"}]},{"group":"Guides","pages":[{"title":"hitspec studio","icon":"terminal","href":"/guides/api-client-manager"},{"title":"CI/CD Pipeline Integration","href":"/guides/ci-cd-pipeline"},{"title":"Regression Testing with hitspec diff","href":"/guides/regression-testing"},{"title":"Database Testing Guide","href":"/guides/database-testing"},{"title":"Load Testing Guide","href":"/guides/load-testing"},{"title":"Contract Testing Guide","href":"/guides/contract-testing"},{"title":"Migrate from Postman to hitspec .http tests","href":"/guides/migrating-from-postman"},{"title":"Upgrading","icon":"arrow-up","href":"/guides/upgrading"},{"title":"Troubleshooting","icon":"wrench","href":"/guides/troubleshooting"}]},{"group":"Examples","pages":[{"title":"Basic CRUD","href":"/examples/basic-crud"},{"title":"Auth Flow","href":"/examples/auth-flow"},{"title":"GraphQL","href":"/examples/graphql"},{"title":"CI/CD Integration","href":"/examples/ci-cd"},{"title":"Stress Testing","href":"/examples/stress-testing"},{"title":"Database Assertions","href":"/examples/database-assertions"},{"title":"Contract Testing","href":"/examples/contract-testing"},{"title":"Mock Server","href":"/examples/mock-server"}]},{"group":"CLI Reference","pages":[{"title":"hitspec run","href":"/reference/run"},{"title":"hitspec validate \u0026 list","href":"/reference/validate-list"},{"title":"hitspec init","href":"/reference/init"},{"title":"hitspec import \u0026 export","href":"/reference/import-export"},{"title":"hitspec mock \u0026 record","href":"/reference/mock-record"},{"title":"hitspec contract \u0026 diff","href":"/reference/contract-diff"},{"title":"hitspec docs, studio \u0026 serve","href":"/reference/docs-serve"},{"title":"Fetch responses","href":"/reference/fetch"},{"title":"MCP client and server","href":"/reference/mcp"},{"title":"REST API","icon":"code","href":"/reference/rest-api"},{"title":"hitspec completion","href":"/reference/completion"},{"title":"hitspec version","href":"/reference/version"},{"title":"Exit Codes","href":"/reference/exit-codes"}]},{"group":"Configuration","pages":[{"title":"Configuration Reference","href":"/reference/configuration"},{"title":"Environment Variables","href":"/reference/environment-variables"}]},{"group":"Assertions Reference","pages":[{"title":"Assertion Operators","href":"/reference/assertion-operators"},{"title":"Assertion Subjects","href":"/reference/assertion-subjects"}]},{"group":"Built-in Functions","pages":[{"title":"Built-in Functions","href":"/reference/builtin-functions"}]},{"group":"Authentication","pages":[{"title":"Authentication Types","href":"/reference/auth-types"}]},{"group":"Output Formats","pages":[{"title":"Output Formats","href":"/reference/output-formats"}]},{"group":"Integrations","pages":[{"title":"GitHub Actions","href":"/integrations/github-actions"},{"title":"Output Formats","href":"/integrations/output-formats"},{"title":"Prometheus","href":"/integrations/prometheus"},{"title":"DataDog","href":"/integrations/datadog"},{"title":"Slack \u0026 Teams Notifications","href":"/integrations/slack-teams"},{"title":"Agent artifact workflow","href":"/integrations/agent-artifacts"}]}]},"basePath":"","title":"Hooks - hitspec","buildId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","deploymentId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","dynamics":[],"chunks":[]}