[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6K9YW8GCY2BE0YJC533CFKP":3,"skill-same:01M6K9YW8GCY2BE0YJC533CFKP":56},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":13,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":41,"install":42,"resources":55},"01M6K9YW8GCY2BE0YJC533CFKP","search-params",null,"URL search param and hash state management. Use when adding or modifying URL search params, working with useSearchParams, setSearchParams, useSearchParamState, or navigate() with query strings or hash fragments, or fixing browser back\u002Fforward button issues.","mazherbashir\u002Faisecurity-1.3","mazherbashir","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1678063?v=4","01M6K9SJS6ZVC22GBYWXY8ZM6Y","01M6K9SJXBEGBX8W33FSE5PNQ8",0,"MIT","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fsearch-params\u002Fskill.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30],"search","search params","state management","state","issues","browser","management","use","back","query","with","URL","strings","2026-11-10 10:12:30",false,"---\nname: search-params\ndescription: URL search param and hash state management. Use when adding or modifying URL search params, working with useSearchParams, setSearchParams, useSearchParamState, or navigate() with query strings or hash fragments, or fixing browser back\u002Fforward button issues.\n---\n\n# URL Search Param State Management\n\n## Decision Framework\n\nWhen updating the URL (search params or hash), choose between **replace** and **push** based on whether the change represents in-page state or a user-navigable step:\n\n| Change type        | Examples                                                | History behavior                                    |\n| ------------------ | ------------------------------------------------------- | --------------------------------------------------- |\n| **In-page state**  | Filters, sort, pagination, tab switches, search queries | `replace` — don't pollute history                   |\n| **Navigable step** | Wizard progression, multi-step forms                    | `push` — back button should return to previous step |\n| **Unsure?**        |                                                         | **Ask the developer** before choosing               |\n\n**Why this matters:** Pushing in-page state changes clutters the browser history. Users clicking \"back\" expect to leave the page, not undo a filter toggle. This is the #1 cause of \"back button is broken\" bugs.\n\n## Correct Patterns\n\n### Single search param — use `useSearchParamState` (preferred)\n\nThis hook validates with Zod and **always uses `replace: true` internally**, so you get correct history behavior for free.\n\n```tsx\nimport { useSearchParamState } from '@app\u002Fhooks\u002FuseSearchParamState';\nimport { z } from 'zod';\n\nconst TabSchema = z.enum(['overview', 'details', 'settings']);\nconst [activeTab, setActiveTab] = useSearchParamState('tab', TabSchema, 'overview');\n```\n\n**Key file:** `src\u002Fapp\u002Fsrc\u002Fhooks\u002FuseSearchParamState.ts`\n\n### Multiple search params — use `setSearchParams` with `replace: true`\n\nWhen updating multiple params at once, use `setSearchParams` directly but always pass `{ replace: true }` for in-page state:\n\n```tsx\nconst [searchParams, setSearchParams] = useSearchParams();\n\n\u002F\u002F Updating filters (in-page state → replace)\nsetSearchParams(\n  (params) => {\n    params.set('status', 'active');\n    params.set('sort', 'name');\n    return params;\n  },\n  { replace: true },\n);\n```\n\n### Hash-based navigation — `navigate()` with replace or push\n\nFor wizard\u002Fmulti-step flows where back button should traverse steps, use **push** (the default):\n\n```tsx\n\u002F\u002F Wizard step navigation — push so back button works between steps\n\u002F\u002F See: src\u002Fapp\u002Fsrc\u002Fpages\u002Fredteam\u002Fsetup\u002Fpage.tsx\nconst updateHash = (newStep: string) => {\n  navigate(`#${newStep}`); \u002F\u002F push (default) — intentional\n};\n```\n\nFor hash changes that represent in-page state, use replace:\n\n```tsx\n\u002F\u002F Tab switch on a detail page — replace to avoid history clutter\nnavigate(`#${section}`, { replace: true });\n```\n\n### URL normalization after save\n\nWhen the URL needs to be updated to include a new ID after a create\u002Fsave operation (not a user action), use replace:\n\n```tsx\n\u002F\u002F After first save, update URL to include new ID without adding history entry\nnavigate(`\u002Fevals\u002F${newConfigId}`, { replace: true });\n```\n\n## Anti-Patterns\n\n### Pushing in-page state changes (breaks back button)\n\n```tsx\n\u002F\u002F WRONG — every filter change adds a history entry\nsetSearchParams((params) => {\n  params.set('filter', value);\n  return params;\n});\n\n\u002F\u002F WRONG — navigate without replace for state change\nnavigate(`?tab=${newTab}`);\n```\n\n### Using raw `useSearchParams` for a single param without validation\n\n```tsx\n\u002F\u002F WRONG — no validation, easy to forget { replace: true }\nconst [searchParams, setSearchParams] = useSearchParams();\nconst tab = searchParams.get('tab');\nconst setTab = (v: string) => {\n  setSearchParams((p) => {\n    p.set('tab', v);\n    return p;\n  });\n};\n\n\u002F\u002F RIGHT — use the hook instead\nconst [tab, setTab] = useSearchParamState('tab', TabSchema, 'overview');\n```\n\n### Using empty strings instead of null\n\n```tsx\n\u002F\u002F WRONG — useSearchParamState will throw an invariant error\nsetTab('');\n\n\u002F\u002F RIGHT — use null to clear a param\nsetTab(null);\n```\n\n## Key Files\n\n- `src\u002Fapp\u002Fsrc\u002Fhooks\u002FuseSearchParamState.ts` — primary hook (uses replace internally)\n- `src\u002Fapp\u002Fsrc\u002Fpages\u002Feval\u002Fcomponents\u002FResultsView.tsx` — example of correct `{ replace: true }` usage\n- `src\u002Fapp\u002Fsrc\u002Fpages\u002Fredteam\u002Fsetup\u002Fpage.tsx` — example of intentional push for wizard steps\n","# URL Search Param State Management\n\n## Decision Framework\n\nWhen updating the URL (search params or hash), choose between **replace** and **push** based on whether the change represents in-page state or a user-navigable step:\n\n| Change type        | Examples                                                | History behavior                                    |\n| ------------------ | ------------------------------------------------------- | --------------------------------------------------- |\n| **In-page state**  | Filters, sort, pagination, tab switches, search queries | `replace` — don't pollute history                   |\n| **Navigable step** | Wizard progression, multi-step forms                    | `push` — back button should return to previous step |\n| **Unsure?**        |                                                         | **Ask the developer** before choosing               |\n\n**Why this matters:** Pushing in-page state changes clutters the browser history. Users clicking \"back\" expect to leave the page, not undo a filter toggle. This is the #1 cause of \"back button is broken\" bugs.\n\n## Correct Patterns\n\n### Single search param — use `useSearchParamState` (preferred)\n\nThis hook validates with Zod and **always uses `replace: true` internally**, so you get correct history behavior for free.\n\n```tsx\nimport { useSearchParamState } from '@app\u002Fhooks\u002FuseSearchParamState';\nimport { z } from 'zod';\n\nconst TabSchema = z.enum(['overview', 'details', 'settings']);\nconst [activeTab, setActiveTab] = useSearchParamState('tab', TabSchema, 'overview');\n```\n\n**Key file:** `src\u002Fapp\u002Fsrc\u002Fhooks\u002FuseSearchParamState.ts`\n\n### Multiple search params — use `setSearchParams` with `replace: true`\n\nWhen updating multiple params at once, use `setSearchParams` directly but always pass `{ replace: true }` for in-page state:\n\n```tsx\nconst [searchParams, setSearchParams] = useSearchParams();\n\n\u002F\u002F Updating filters (in-page state → replace)\nsetSearchParams(\n  (params) => {\n    params.set('status', 'active');\n    params.set('sort', 'name');\n    return params;\n  },\n  { replace: true },\n);\n```\n\n### Hash-based navigation — `navigate()` with replace or push\n\nFor wizard\u002Fmulti-step flows where back button should traverse steps, use **push** (the default):\n\n```tsx\n\u002F\u002F Wizard step navigation — push so back button works between steps\n\u002F\u002F See: src\u002Fapp\u002Fsrc\u002Fpages\u002Fredteam\u002Fsetup\u002Fpage.tsx\nconst updateHash = (newStep: string) => {\n  navigate(`#${newStep}`); \u002F\u002F push (default) — intentional\n};\n```\n\nFor hash changes that represent in-page state, use replace:\n\n```tsx\n\u002F\u002F Tab switch on a detail page — replace to avoid history clutter\nnavigate(`#${section}`, { replace: true });\n```\n\n### URL normalization after save\n\nWhen the URL needs to be updated to include a new ID after a create\u002Fsave operation (not a user action), use replace:\n\n```tsx\n\u002F\u002F After first save, update URL to include new ID without adding history entry\nnavigate(`\u002Fevals\u002F${newConfigId}`, { replace: true });\n```\n\n## Anti-Patterns\n\n### Pushing in-page state changes (breaks back button)\n\n```tsx\n\u002F\u002F WRONG — every filter change adds a history entry\nsetSearchParams((params) => {\n  params.set('filter', value);\n  return params;\n});\n\n\u002F\u002F WRONG — navigate without replace for state change\nnavigate(`?tab=${newTab}`);\n```\n\n### Using raw `useSearchParams` for a single param without validation\n\n```tsx\n\u002F\u002F WRONG — no validation, easy to forget { replace: true }\nconst [searchParams, setSearchParams] = useSearchParams();\nconst tab = searchParams.get('tab');\nconst setTab = (v: string) => {\n  setSearchParams((p) => {\n    p.set('tab', v);\n    return p;\n  });\n};\n\n\u002F\u002F RIGHT — use the hook instead\nconst [tab, setTab] = useSearchParamState('tab', TabSchema, 'overview');\n```\n\n### Using empty strings instead of null\n\n```tsx\n\u002F\u002F WRONG — useSearchParamState will throw an invariant error\nsetTab('');\n\n\u002F\u002F RIGHT — use null to clear a param\nsetTab(null);\n```\n\n## Key Files\n\n- `src\u002Fapp\u002Fsrc\u002Fhooks\u002FuseSearchParamState.ts` — primary hook (uses replace internally)\n- `src\u002Fapp\u002Fsrc\u002Fpages\u002Feval\u002Fcomponents\u002FResultsView.tsx` — example of correct `{ replace: true }` usage\n- `src\u002Fapp\u002Fsrc\u002Fpages\u002Fredteam\u002Fsetup\u002Fpage.tsx` — example of intentional push for wizard steps\n",{"name":5,"description":7},"main","cfb371efff87b20badc3aa457d529e1ca793ce1f",".claude\u002Fskills\u002Fsearch-params","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3","https:\u002F\u002Fgithub.com\u002Fmazherbashir","2026-05-08 03:41:51",{"source":8,"skillName":5,"commands":43,"prompt":53,"zipAvailable":54},[44,47,50],{"tool":45,"command":46},"npx","npx skills add mazherbashir\u002Faisecurity-1.3 --skill search-params",{"tool":48,"command":49},"bunx","bunx skills add mazherbashir\u002Faisecurity-1.3 --skill search-params",{"tool":51,"command":52},"pnpm","pnpm dlx skills add mazherbashir\u002Faisecurity-1.3 --skill search-params","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fsearch-params\u002Fskill.md",true,[],[57,80,95,118,130,144],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":31},"01M6K9Z78FTHWZZ8K542PYTD8W","promptfoo-evals","Creates or updates promptfoo evaluation suites (promptfooconfig.yaml, prompts, tests, assertions, providers). Use when adding eval coverage, debugging regressions, or scaffolding a new eval matrix.","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002Fplugins\u002Fpromptfoo-evals\u002Fskills\u002Fpromptfoo-evals\u002FSKILL.md",[],[64,65,66,67,68,69,70,71,72,73,74,75,76,77,25,78,79],"promptfoo evals","promptfoo","evals","tests","assertions","matrix","updates","promptfoo evaluation","Providers","scaffolding","debugging","yaml","Evaluation","prompts","coverage","eval",{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":91,"publishedAt":31},"01M6K9Z4RDWW8SSX8MKFYBG8MT","token-skill","Use this skill when the user explicitly asks to use token-skill and wants the special token.","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002Fexamples\u002Fopenai-codex-sdk\u002Fskills\u002Fsample-project\u002F.agents\u002Fskills\u002Ftoken-skill\u002FSKILL.md",[86],{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[92,93,94,25],"token","token skill","user",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":109,"publishedAt":31},"01M6K9Z2BQPH2H9WNGKDF510ZH","code-review","Reviews code for bugs, security issues, and best practices","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002Fexamples\u002Fclaude-agent-sdk\u002Fskills\u002Fsample-project\u002F.claude\u002Fskills\u002Fcode-review\u002FSKILL.md",[101,104],{"categoryNo":102,"categoryName":103,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":105,"categoryName":106,"taxonomyType":107,"taxonomyTypeDesc":108},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[110,111,112,113,114,115,22,116,117],"code","review","code review","reviews","for","bugs","security","best practices",{"skillNo":119,"name":120,"nameZh":6,"description":121,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":124,"publishedAt":31},"01M6K9Z0W3VM60MGGS12B5F6SV","standards-check","Checks that a project follows standard conventions","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002Fexamples\u002Fclaude-agent-sdk\u002Fplugins\u002Fsample-plugin\u002Fskills\u002Fstandards-check\u002FSKILL.md",[],[125,126,127,128,129],"standards","check","standards check","project","conventions",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":136,"publishedAt":31},"01M6K9YRTM2XGTHC118F7677T6","redteam-plugin-development","Standards for creating redteam plugins and graders. Use when creating new plugins, writing graders, or modifying attack templates.","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fredteam-plugin-development\u002Fskill.md",[],[137,138,139,140,141,142,143,25,125,114],"redteam plugin development","plugin development","development","plugin","writing","plugins","templates",{"skillNo":145,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":146,"categories":147,"keywords":148,"publishedAt":31},"01M6K9YK34AHYGZJAHW17TTQHW","https:\u002F\u002Fgithub.com\u002Fmazherbashir\u002Faisecurity-1.3\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fpromptfoo-evals\u002FSKILL.md",[],[64,65,66,69,75,76,72,79,78,25,77,73,67,71,70,68,74]]