{"id":39492556,"url":"https://github.com/crashappsec/cap10","last_synced_at":"2026-01-18T05:37:44.122Z","repository":{"id":204940646,"uuid":"712992007","full_name":"crashappsec/cap10","owner":"crashappsec","description":"Script, capture and replay terminal sessions","archived":false,"fork":false,"pushed_at":"2023-12-05T17:33:44.000Z","size":62,"stargazers_count":7,"open_issues_count":5,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-01-26T23:38:21.404Z","etag":null,"topics":["expect","linux","macos","pty","recorder","terminal"],"latest_commit_sha":null,"homepage":"","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crashappsec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-11-01T16:09:45.000Z","updated_at":"2023-11-24T16:20:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"784c2d66-7b4b-410b-bee6-f9ce8e3ace87","html_url":"https://github.com/crashappsec/cap10","commit_stats":{"total_commits":17,"total_committers":5,"mean_commits":3.4,"dds":"0.23529411764705888","last_synced_commit":"ff5eab30d6069f98c850b09688886958b1c9c085"},"previous_names":["crashappsec/cap10"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/crashappsec/cap10","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crashappsec%2Fcap10","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crashappsec%2Fcap10/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crashappsec%2Fcap10/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crashappsec%2Fcap10/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crashappsec","download_url":"https://codeload.github.com/crashappsec/cap10/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crashappsec%2Fcap10/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28531027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expect","linux","macos","pty","recorder","terminal"],"created_at":"2026-01-18T05:37:43.532Z","updated_at":"2026-01-18T05:37:44.112Z","avatar_url":"https://github.com/crashappsec.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cap10\n## Script, capture and replay terminal sessions\n\n![Cap10 Demo](https://github-production-user-asset-6210df.s3.amazonaws.com/4764481/280741508-3a3d90cd-b4d2-44e0-9b1a-c38543cbd903.gif)\n\nYou record and play back terminal sessions or other terminal programs\nwith the `cap10` command, which will record a process until it exits.\n\nCap10 will automatically remove long pauses in your input stream. So\ntype as slow as you want... walk away and come back an hour\nlater. You're good.\n\n- `cap10 record [optional command]` starts recording.\n- `cap10 play file.cap10`\n- `cap10 convert [filename]` will convert a cap10 file to the _asciicast 2.0_ format.\n\nThe `cap10` capture format is binary, and there's currently not a web\nplayer for it. But you can convert it to asciicast format.\n\nOn Linux, cap10 should build as a static ELF binary, so can run in\nminimal environments like Alpine, without the Python dependencies of\nasciinema.\n\nAlso, we produce a separate input log to make it easier to automate\nscripting for demos (in conjunction w/ our expect capabilities\nbelow). It captures keypresses only, so if you don't type out a full\ncommand, it won't capture the exact commands (in the future we may do\nsome shell integration to get the shell view).\n\nEssentially, cap10 should replace the following tools:\n\n- script\n- asciinema\n- expect\n- autoexpect (which never worked well anyway)\n\n## GIF conversion\n\nIf you'd like to convert the output to a video for a web page, instead\nof an Asciicast, we recommend producing an GIF, which you can do \ndo this by exporting to asciicast and then running the\n[agg tool](https://github.com/asciinema/agg) from asciinema.\n\n## Expect More\n\nYou can also use `cap10` as an expect-like library, with the added\nbenefits:\n\n1. You can fully capture your `expect` sessions if you want.\n2. You can interact with your scripts if you want.\n3. You can capture the input from your interactions.\n\nThe second makes expect-like automation easier to write. I've had many\ncases where the regexp didn't fire, and the result was a hanging\nprocess, with a long iteration cycle to test. Here, you can just\nmanually enter input, which will generate output that runs through the\npattern matcher.\n\nFor example, the below code waits for a prompt, runs a command, then\nwaits for 'hiho' followed by the enter key (The enter key generates\n'\\r' NOT '\\n'; the log file does translate them back to '\\n' to be more\nhuman readable).\n\nBut the code never does anything to send that string to the\nterminal. Instead, you're left to manually interact with it, and when\nthe pattern is matched, the 'expect' call returns.\n\nThe `passthrough` flag specifies that the user should be able to\ninteract. At some point, we'll expose the ability to turn this on and\noff at will, and to provide more control over tty settings. \n\n```\nimport cap10\nvar s: ExpectObject\n\ns.spawnSession(captureFile = \"expect.cap10\", passthrough = true)\ns.expect(\".*\\\\$ \")\ns.send(\"~/dev/chalk/chalk\")\ns.expect(\"hiho\\r\")\ns.send(\"exit\")\ns.expect(\"eof\")\necho \"Capture saved to: \", s.capturePath\n```\n\n## The switchboard\n\nAt some point, we'll package this up as a library with bindings to\nother languages.\n\nUnderlying everything is an IO multiplexing system that allows us to\nabitrarily (and dynamically) route output from file descriptors to\nother file descriptors, callbacks, etc, all without the need for\nthreads. We've got a bunch of little utilities we'd like to see on top\nof this, that we may eventually add.\n\n## Status\n\nIt's early, and there are some rough edges (for instance, if there are\nfile perms issues, we're currently not handling gracefully). This was\ndone for our internal use, but eventually we will polish this\nup. Until then, use at your own risk :)\n\nIn the not too distant future, we'll bundle the API for direct calling\nfrom other languages, with wrappers for (at least) Go and Python.\n\nEventually, we'd like to have a native player and more, and be able to\nnatively produce GIFs. But no hurry; the asciinema tools there are\ngood.\n\n## Building\n\nYou need to have Nim 2.0 installed, and be on a 64-bit posix\nsystem. We really develop only on Linux and Mac, so there's more than\na non-zero chance that *BSD or WSL won't work at this point...\n\nBut all you should need to do to build the `cap10` binary is run from\nthe root of the repo:\n\n```\nnimble build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrashappsec%2Fcap10","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrashappsec%2Fcap10","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrashappsec%2Fcap10/lists"}